Greenhouse IOT

Overview

The drawing above shows how the sensor data emanating from ObserverIP is intercepted via iptables running on WRT54G and sent to a Node-RED service running on pi1

Router Setup

You will need to find an old WAP like the Linksys WRT54G, and load DD-WRT

iptables

This section based on this blog post

An iptables entry is created to intercept traffic from ObserverIP to ambientweather.net and redirect it Node-RED running on a Raspberry Pi. The gh-flow service, hosted by Node-RED on pi1, will act as a tee, sending the data to Prometheus before sending it along to its original target ambientweather.net.

#
# ssh to WRT54G
#
ssh root@192.168.2.1 

#
# While on pi1
# redirect traffic from ObserverIP to pi1
#
iptables -t nat -A PREROUTING -s 192.168.2.151 -p tcp --dport 80 -j DNAT --to-destination 192.168.2.160:1880
iptables -t nat -A POSTROUTING -j MASQUERADE

# Allow everything to be forwarded through the router (simple but do not use on routers directly connected to the internet)
iptables -I FORWARD -j ACCEPT

# Verify
iptables -t nat -L PREROUTING

# Save above as Firewall script to survive a reboot

Note to survive a reboot the above commands need to be saved in a Firewall script (see dd-wrt iptables doc)

Pi Setup

Load raspbian lite OS and then set a static IP. For more information see the official Raspberry Pi Doc

raspi-config

Login with the default login pi/raspbery and run rasp-config

raspi-config

This will allow for ssh pi@192.168.2.161

Static IP address

Configure the eth0 interface statically by editing the /etc/dhcpcd.conf file.

For the hostname pi1:

interface eth0
static ip_address=192.168.2.160/24
static routers=192.168.2.1
static domain_name_servers=192.168.2.1 8.8.8.8

For the hostname pi2:

interface eth0
static ip_address=192.168.2.161/24
static routers=192.168.2.1
static domain_name_servers=192.168.2.1 8.8.8.8

Prometheus

The following is based on this article.

sudo apt update
sudo apt full-upgrade

wget https://github.com/prometheus/prometheus/releases/download/v2.22.0/prometheus-2.22.0.linux-armv7.tar.gz
tar xfz prometheus-2.22.0.linux-armv7.tar.gz
mv prometheus-2.22.0.linux-armv7/ prometheus/
rm prometheus-2.22.0.linux-armv7.tar.gz

Create a service config file

sudo nano /etc/systemd/system/prometheus.service

and edit to look like the following.

[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/introduction/overview/
After=network-online.target

[Service]
User=pi
Restart=on-failure

ExecStart=/home/pi/prometheus/prometheus \
  --config.file=/home/pi/prometheus/prometheus.yml \
  --storage.tsdb.path=/home/pi/prometheus/data

[Install]
WantedBy=multi-user.target

Then

sudo systemctl enable prometheus
sudo systemctl start prometheus
sudo systemctl status prometheus

open http://192.168.2.161:9090

Push Gateway

This section base on this github page

wget https://github.com/prometheus/pushgateway/releases/download/v1.4.0/pushgateway-1.4.0.linux-armv7.tar.gz


tar xfz pushgateway-1.4.0.linux-armv7.tar.gz
mv pushgateway-1.4.0.linux-armv7/ pushgateway/
rm pushgateway-1.4.0.linux-armv7.tar.gz

Create a service config file

sudo nano /etc/systemd/system/pushgateway.service

and edit to look like the following.

[Unit]
Description=Prometheus Push Gateway
Documentation=https://prometheus.io/docs/introduction/overview/
After=network-online.target

[Service]
User=pi
Restart=on-failure

ExecStart=/home/pi/pushgateway/pushgateway

[Install]
WantedBy=multi-user.target

Then

sudo systemctl enable pushgateway
sudo systemctl start pushgateway
sudo systemctl status pushgateway

The query API allows accessing pushed metrics and build and runtime information.

curl -X GET http://192.168.2.161:9091/api/v1/status | jq

To configure pushgateway as a scrape target in prometheus edit /home/pi/prometheus/prometheus.yml as shown below (must have correct indentation)

...
scrape_configs:
  ...
  - job_name: 'pushgateway'
    honor_labels: true
    static_configs:
    - targets: ['localhost:9091']
...

Then restart

sudo systemctl restart prometheus

Alert Manager

Setup.

wget https://github.com/prometheus/alertmanager/releases/download/v0.21.0/alertmanager-0.21.0.linux-armv7.tar.gz
tar xfz alertmanager-0.21.0.linux-armv7.tar.gz
mv alertmanager-0.21.0.linux-armv7/ alertmanager/
rm alertmanager-0.21.0.linux-armv7.tar.gz

Create a service config file

sudo vi /etc/systemd/system/alertmanager.service

and edit to look like the following.

[Unit]
Description=Alert Manager
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=pi
Group=pi
ExecStart=/home/pi/alertmanager/alertmanager \
  --config.file=/home/pi/alertmanager/alertmanager.yml \
  --storage.path=/home/pi/alertmanager/data/alertmanager

Restart=always

[Install]
WantedBy=multi-user.target

Configure the alertmanager config

sudo nano /home/pi/alertmanager/alertmanager.yml

and edit to look like the following. See the alertmanager config doc. And here is a good blog

global:
  # URL value not shown becaue it contains a token
  # to get the URL in slack, click more > apps > Browse Apps > Custom Integrations > Incoming WebHooks
  # or go here: https://bagelwarehouse.slack.com/services/1874015307842
  slack_api_url: 'https://hooks.slack.com/services/REDACTED/REDACTED/REDACTED'

route:
  receiver: 'slack-notifications'
  group_by: [alertname, datacenter, app]

receivers:
- name: 'slack-notifications'
  slack_configs:
  - channel: '#weather-alerts'
    send_resolved: true
    text: Detail *Temp* `{{ .CommonAnnotations.description }}` {{ range .Alerts -}}{{ range .Labels.SortedPairs }}  *{{ .Name }}* `{{ .Value }}`{{ end }}{{ end }}

Then

sudo systemctl enable alertmanager
sudo systemctl start alertmanager
sudo systemctl status alertmanager

open http://192.168.2.161:9093

Now go to the Prometheus server directory and add to the prometheus.yml file and add stuff like this:

alerting:  
  alert managers:  
    - static_configs: 
       - targets:  
           - "localhost:9093  
rule_files:  
 - "./rules.yml"

And make the rules.yml look like:

groups:
- name: sensors
  rules:
  - alert: gh-very-cold
    expr: round(avg_over_time(obff_wh31e_temp1f [2m])) < 50
    annotations:
      text: 'Greenhouse is very cold'
      description: "{{ $value }}"
  - alert: gh-cold
    expr: round(avg_over_time(obff_wh31e_temp1f [2m])) < 59
    annotations:
      text: Greenhouse is cold
      description: "{{ $value }}"
  - alert: gh-warm
    expr: round(avg_over_time(obff_wh31e_temp1f [2m])) > 75
    annotations:
      text: Greenhouse is warm
      description: "{{ $value }}"
  - alert: gh-hot
    expr: round(avg_over_time(obff_wh31e_temp1f [2m])) > 85
    annotations:
      text: Greenhouse is hot
      description: "{{ $value }}"
  - alert: gh-very-hot
    expr: round(avg_over_time(obff_wh31e_temp1f [2m])) > 90
    annotations:
      text: Greenhouse is very hot
      description: "{{ $value }}"

If changes are made to the file you need to restart to have them take affect:

vi rules.yml 
sudo systemctl restart prometheus
sudo systemctl status prometheus
sudo journalctl --unit=prometheus -f

to debug:

sudo journalctl --unit=alertmanager.service

Grafana

This section is based on this article

Installing grafana on pi2

# Add the APT key used to authenticate packages:
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -

# Add the Grafana APT repository:
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list

# install grafana
sudo apt-get update
sudo apt-get install -y grafana

Edit the config

vi /etc/grafana/grafana.ini

# set the following
[auth]
disable_login_form = true
...

[auth.anonymous]
# enable anonymous access 
enabled = true

...

# specify organization name that should be used for unauthenticated users
org_name = Ohio Barn Flower Farm


# specify role for unauthenticated users
org_role = Editor

then.

sudo /bin/systemctl enable grafana-server
sudo /bin/systemctl start grafana-server
sudo /bin/systemctl status grafana-server

Open a browser and go to http://192.168.2.161:3000. Log in to Grafana with the default username admin, and the default password admin. Change the password for the admin user when asked.

Metrics

obff_wh31e_temp1f

The gh-flow will generate a metric similar to the following.

cat <<EOF | curl --data-binary @- http://192.168.2.161:9091/metrics/job/sensor_reading/location/greenhouse
# TYPE obff_wh31e_temp1f gauge
# HELP obff_wh31e_temp1f Greenhouse Tempature
obff_wh31e_temp1f 60.25

Miscellaneous

Static Routs

This section based on this

on router 1

Bug fix

Do this on pi1 and pi2

sudo vi /etc/avahi/avahi-daemon.conf

# Comment out
# use-ipv6=yes

# set this
deny-interfaces=wlan0

# Then
sudo systemctl restart avahi-daemon