emonPi, NodeRed and MQTT
Using a tool called Node-Red the emonPi can become a central hub for home automation, control and notification. Node-RED is a tool for wiring together hardware devices, APIs and online services in new and interesting ways. At the heart of Node-RED is a visual editor allowing complex data flows to be wired together with only a little coding skills. Here are some of my ideas of things I might like to achieve with Node-RED, For more inspiration check out Martin's IoT Google hangout 29min in:
- Send power consumption notifications to my phone using Node-RED and Pushover
- Send a notification to my phone when it's a good time to use power e.g national power demand is low and grid renewable generation input is high
- Use an emonTH as a room thermostat temperature input to control my heating using WiFi MQTT relay board (blog post coming soon... :-) )
- Switch my heating on when I arrive home using node-RED and IFTT android / iOS location
- Post energy data to another service e.g. thingspeak.com, pvoutput.org, xively.com etc..
- Use node-RED to post data from other services to Emoncms e.g national power demand, home weather station, weather forecast
- Periodically tweet my home power consumption or solar PV output
- Set an email when you emonTH batteries run low (see example below)
Install Node-RED on emonPi / emonHub / Raspberry Pi
Make emonPi file-system RW:$ rpi-rw
Install Node-RED (taken from node-RED RaspberryPi install guide):
$ curl -sL https://deb.nodesource.com/setup_0.12 | sudo bash -
$ sudo apt-get install -y build-essential python-dev python-rpi.gpio nodejs
$ sudo npm install -g --unsafe-perm node-red
Open up port 1880 so we can access Node-RED editor:
$ sudo iptables -A INPUT -p tcp -m tcp --dport 1880 -j ACCEPT
Open up port 1883 so we can access MQTT server:
$ sudo iptables -A INPUT -p tcp -m tcp --dport 1883 -j ACCEPT
Make iptables rules persistent
$ apt-get install iptables-persistent
Choose yes to save rules, if needed edit the persistent rules:
$ sudo nano /etc/iptables/rules.v4
Start Node-RED with:
$ node-red-pi --max-old-space-size=128
To view the node-RED graphical editor browse to:
http://emonpi:1880/ (or use IP address if this does not work)
To use Node-RED as a permanent setup you will want to set it up as a service to autostart at boot and enable secure authentication access to node-RED editor.
When you are done don't forget to put the emonPi back to read-only mode to preserve SD card lifespan:
$ rpi-ro
Getting data from the emonPi into Node-RED
There are two options to get our energy data into Node-RED:1. Real-time data from emonHub using MQTT (see example below):
MQTT is a lightweight communication protocol for small web-connected devices. The latest version of emonHub as setup on the emonPi (and emonHub from July 15) uses MQTT as a link to Emoncms and also to provide data to the emonPi LCD script. Since MQTT is already running all we need to do is to point Node-RED MQTT input block to subscribe to the 'emonhub/rx/#' MQTT topic on port 1883. The '#' topic includes data received from all nodes. To subscribe to just one node use e.g. emonPi use: 'emonhub/5/values' or 'emonhub/10/values' for emonTx.
To subscribe the the emonPi's MQTT topics externally (if your running node-RED on another machine) you will need to open up the MQTT port on the emonPi:
$ sudo iptables -A INPUT -p tcp -m tcp --dport 1883 -j ACCEPT
2. Historic data from Emoncms using HTTP API:
To pull historic data already logged to Emoncms (e.g KWh data) into Node-RED we can use Emoncms's API. Here is a simple example to pull in the latest value from the KWh feed, just enter your RW API key and feed ID:
http://emoncms.org/feed/value.json&apikey=APIKEY&id=FEED_ID
To view all Emoncms API see: http://emoncms.org/input/api
Node-RED example: send warning email when emonTH battery is low
Simple but useful example, use Node-RED connecting to emonPi in real-time data via MQTT (localhost) and sending email (via Gmail SMTP) if emonTH battery drops below 1.7V. Also in this flow as an example is a node to decode emonPi power data.
Here is the contents of each node:
MQTT Node subscribing to emonhub mqtt topic on localhost (running node-RED on emonPi) |
Separate node to split the MQTT data up into nodes based on ID: e.g emonTx = 10, emonPi = 5, emonTH = 19 |
CSV node to split up MQTT CSV string |
If function node |
email node, enter your Gmail (or otherwise) SMTP login |
[{"id":"eb57a13e.14a86","type":"mqtt-broker","broker":"localhost","port":"1883","clientid":""},{"id":"44c7eefa.bb381","type":"mqtt in","name":"MQTT: emonhub/rx/#","topic":"emonhub/rx/#","broker":"eb57a13e.14a86","x":159,"y":386,"z":"fa6ca080.05936","wires":[["2c7fcc53.d38034","eb7e04d9.1481f8"]]},{"id":"2c7fcc53.d38034","type":"debug","name":"RAW MQTT output: emonhub/rx/#","active":false,"console":"false","complete":"topic","x":242,"y":461,"z":"fa6ca080.05936","wires":[]},{"id":"eb7e04d9.1481f8","type":"switch","name":"Seperate Nodes","property":"topic","rules":[{"t":"cont","v":"5"},{"t":"cont","v":"19"},{"t":"cont","v":"20"}],"checkall":"true","outputs":3,"x":343,"y":317,"z":"fa6ca080.05936","wires":[["b0618044.4f9e8"],["9077dea0.6f882"],[]]},{"id":"9077dea0.6f882","type":"csv","name":"emonTH 1: emonhub/19/values > Decode MQTT CSV","sep":",","hdrin":"","hdrout":"","multi":"one","ret":"\\n","temp":"temp,temp_external,humidity,battery,pulsecount","x":664,"y":373,"z":"fa6ca080.05936","wires":[["75ee731f.8a118c"]]},{"id":"b0618044.4f9e8","type":"csv","name":"emonPi: emonhub/5/values > Decode MQTT CSV","sep":",","hdrin":"","hdrout":"","multi":"one","ret":"\\n","temp":"power1,power2,power1_plus_2,Vrms,temp1,temp2,temp3,temp4,temp5,temp6,pulseCount","x":647,"y":236,"z":"fa6ca080.05936","wires":[["cda897fa.325768"]]},{"id":"cda897fa.325768","type":"debug","name":"Debug: emonPi Power1 output","active":false,"console":"false","complete":"payload.power1","x":1015,"y":235,"z":"fa6ca080.05936","wires":[]},{"id":"75ee731f.8a118c","type":"function","name":"If emonTH battery < 1.7V","func":"if (msg.payload.battery < 1.7) {\n return {payload:'WARNING: emonTH battery low '+msg.payload.battery+'V' };\n}","outputs":1,"noerr":0,"x":1015,"y":363,"z":"fa6ca080.05936","wires":[["f8d8fd72.0727"]]},{"id":"f8d8fd72.0727","type":"delay","name":"Limit 1 email per day","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"day","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":948,"y":447,"z":"fa6ca080.05936","wires":[["1d4154b2.e2beab"]]},{"id":"1d4154b2.e2beab","type":"e-mail","server":"smtp.gmail.com","port":"465","name":"","dname":"Send warning email","x":1198,"y":439,"z":"fa6ca080.05936","wires":[]}] To engage in discussion regarding this post, please post on our Community Forum.