Here’s a quick dashboard we put together with Node-red and the Grove Pi+ sensor kit. We built a little on our previous project to pull in more environmental data, but by using our Heroku platform (with its bundled CloudMQTT broker) we have a free, web-hosted dashboard we can access from anywhere.
This is part of our series on Node-red; If you’d like to see more, see our Technology for Non-technologists post, or our series of posts on Node-red and sensors.
Things you’ll need to re-create this project
To realise this project, you’ll need a Pi with Node-red and a Grove Pi+, with the software installed as per the instructions. Like our previous project, we will need access to an internet-hosted system running Node-red and MQTT (often called cloud platform-as-a–service by the tattooed and bearded young hipsters of technology). If you have your own MQTT broker already, you can use that, but our run-down of creating a (free) Node-red Heroku App, with a free-tier MQTT, is here – you can get a free-tier hosted Node-red with a MQTT broker by just validating your account with a credit card.
Sensor Configuration on the Pi
You’re welcome to customise your sensors (remembering to adjust your dashboard accordingly) but be mindful that some sensors are only compatible with certain types of node – use this handy diagram to check before connecting.
We have configured the Grove interface on the Pi to use the following connections:
Port | Sensor | Notes |
---|---|---|
A0 | Light | This is an analogue sensor |
A1 | Sound | This is an analogue sensor |
D3 | Temperature/Humidity | This sensor sends digitally-encoded data |
(You can copy-and-paste this patch below: on your Raspberry Pi, click the Node-red edit menu then Import→Clipboard, paste the following, then click Import
).
[{"id":"504bbc2a.7b68bc","type":"grove analog sensor","z":"bd846919.9dde78","name":"Light(A0)","pin":"0","sensor":"light","repeat":"1","board":"6e2ddd30.cb2234","x":200,"y":320,"wires":[["ae6f2c0.2362858","2aa7d69a.c83a0a"]]},{"id":"2aa7d69a.c83a0a","type":"debug","z":"bd846919.9dde78","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":410,"y":260,"wires":[]},{"id":"ae6f2c0.2362858","type":"mqtt out","z":"bd846919.9dde78","name":"Light","topic":"Light","qos":"","retain":"","broker":"d5bfb501.0df038","x":390,"y":320,"wires":[]},{"id":"42af3ae6.926f74","type":"grove analog sensor","z":"bd846919.9dde78","name":"Sound(A1)","pin":"1","sensor":"sound","repeat":"1","board":"6e2ddd30.cb2234","x":200,"y":180,"wires":[["ac8a660a.a2b36","abffdef1.dcb988"]]},{"id":"abffdef1.dcb988","type":"debug","z":"bd846919.9dde78","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":410,"y":120,"wires":[]},{"id":"ac8a660a.a2b36","type":"mqtt out","z":"bd846919.9dde78","name":"Sound","topic":"Sound","qos":"","retain":"","broker":"d5bfb501.0df038","x":390,"y":180,"wires":[]},{"id":"6030ce99.68b2e","type":"grove digital sensor","z":"bd846919.9dde78","name":"Temp/Humidity (D3)","board":"6e2ddd30.cb2234","sensor":"dht11","repeat":"10","pin":"3","x":170,"y":460,"wires":[["999ee959.01387","a6c604e7.58a26"]]},{"id":"e1772ee8.11de48","type":"debug","z":"bd846919.9dde78","name":"TEMPERATURE","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":700,"y":360,"wires":[]},{"id":"999ee959.01387","type":"function","z":"bd846919.9dde78","name":"Split Readings","func":"// break our single message into an array \n// of 3 messages, each with a msg.payload from \n// each of the main properties from the sensor\n\nreturn(\n [\n {\n payload:msg.payload.temperature\n },\n {\n payload:msg.payload.humidity\n },\n {\n payload:msg.payload.heatIndex\n }\n ]\n);\n","outputs":3,"noerr":0,"x":420,"y":460,"wires":[["e1772ee8.11de48","5525fcdd.533db4"],["22b00e49.f1398a","725c3dc5.f9988c"],["3e8d1f4d.b15f8","d8d97082.572af"]]},{"id":"313af579.4fea0a","type":"comment","z":"bd846919.9dde78","name":"Multiple Sensor Node","info":"## Outputs from nodes:\n\n1. Temperature *(°C)*\n2. Humidity *(%)*\n3. Heat Index *()*\n\nThe original msg.payload is an object with three\nproperties: we will extract each one in the \n`Split Readings` function node and return an\narray of new `msg` objects, each one sent to a\ndiscrete outlet.\n","x":180,"y":420,"wires":[]},{"id":"22b00e49.f1398a","type":"debug","z":"bd846919.9dde78","name":"HUMIDITY","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":690,"y":460,"wires":[]},{"id":"3e8d1f4d.b15f8","type":"debug","z":"bd846919.9dde78","name":"HEAT INDEX","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":690,"y":560,"wires":[]},{"id":"a6c604e7.58a26","type":"debug","z":"bd846919.9dde78","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":410,"y":400,"wires":[]},{"id":"5525fcdd.533db4","type":"mqtt out","z":"bd846919.9dde78","name":"Temperature","topic":"Temperature","qos":"","retain":"","broker":"d5bfb501.0df038","x":690,"y":400,"wires":[]},{"id":"d8d97082.572af","type":"mqtt out","z":"bd846919.9dde78","name":"HeatIndex","topic":"HeatIndex","qos":"","retain":"","broker":"d5bfb501.0df038","x":690,"y":600,"wires":[]},{"id":"725c3dc5.f9988c","type":"mqtt out","z":"bd846919.9dde78","name":"Humidity","topic":"Humidity","qos":"","retain":"","broker":"d5bfb501.0df038","x":680,"y":500,"wires":[]},{"id":"6e2ddd30.cb2234","type":"board-config","z":"","board":"GrovePi"},{"id":"d5bfb501.0df038","type":"mqtt-broker","z":"","name":"UPDATE YOUR BROKER!","broker":"mqtt://username:password@host.name.here","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","willTopic":"","willQos":"0","willRetain":"false","willPayload":""}]
You will need to update the MQTT broker endpoint in your patch. The easiest way to do this is to click the Node-red edit menu, then pick Configuration Nodes. On the right hand side of the window, a configuration tab becomes selected. Under a mqtt broker section, a node with a 5 is listed – mouse over it to see the nodes which use it highlight in the flow editor, then double-click it to bring up the edit panel (The 5 is a reference to how many nodes are using this MQTT configuration, so you can visually confirm which configurable items are of use from this tab just by mousing over it).
Once this is configured with your Heroku-provided CloudMQTT broker and deployed on your Pi, you’ll be sending regular readings and updates on your Grove-connected sensors to ‘the cloud’.
Making the Dashboard
The dashboard is built by subscribing to the same MQTT broker that the Pi publishes to, and feeds the named data points out to a series of Node-red dashboard nodes.
Log in to your Heroku Node-red system (you’ll be prompted to to provide the credentials you set up when instancing your Heroku box – these may reacquaint yourself with these through the Heroku dashboard, under the Settings sections NODE_RED_PASSWORD
and NODE_RED_USERNAME
, should you need to).
Make sure to install the node-red-dashboard
module – click the edit menu (in the top-right), then pick Manage palette, then Palette on the left of the panel that appears, then Install on the tabs along the top that come next. In the search box, look for node-red-dashboard
and click install
to install them, if you haven’t already – this will add a whole suite of interface elements under a new dashboard section under the node palette, on the left.
You can paste in the patch below, but remember to update your mqtt broker (which will be listed in the panel that appears by clicking the edit menu in the top right, then the Configuration nodes item under it). You’ll also need to adjust the items you add to the dashboard and the Topics you subscribe to from the MQTT broker, if you’ve added or re-configured sensors.
[{"id":"6de9acb9.fd519c","type":"mqtt in","z":"83a55bb2.a1bfd","name":"","topic":"Light","qos":"2","broker":"d76a1508.8f5a7","x":130,"y":60,"wires":[["4c1842d6.cbfd04","37000348.f2f5b4"]]},{"id":"37000348.f2f5b4","type":"ui_gauge","z":"83a55bb2.a1bfd","name":"","group":"cce8a1de.f44dd","order":1,"width":"3","height":"3","gtype":"gage","title":"Light","label":"","format":"{{value}}","min":"0","max":"1000","colors":["#444455","#99AABB","#E6E6CC"],"seg1":"500","seg2":"800","x":370,"y":100,"wires":[]},{"id":"4c1842d6.cbfd04","type":"ui_chart","z":"83a55bb2.a1bfd","name":"","group":"cce8a1de.f44dd","order":2,"width":"9","height":"3","label":"Light (last hour)","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"Loading...","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1F77B4","#AEC7E8","#FF7F0E","#2CA02C","#98DF8A","#D62728","#FF9896","#9467BD","#C5B0D5"],"useOldStyle":false,"x":400,"y":60,"wires":[[],[]]},{"id":"8a155742.2ed4d","type":"mqtt in","z":"83a55bb2.a1bfd","name":"","topic":"Sound","qos":"2","broker":"d76a1508.8f5a7","x":130,"y":140,"wires":[["8e2b35cc.1f1558"]]},{"id":"655ad28f.4e7aac","type":"ui_gauge","z":"83a55bb2.a1bfd","name":"","group":"cce8a1de.f44dd","order":7,"width":"4","height":"4","gtype":"compass","title":"Noise","label":"","format":"{{value}}","min":0,"max":"100","colors":["#00B500","#E6E600","#CA3838"],"seg1":"","seg2":"","x":370,"y":140,"wires":[]},{"id":"2e408d8c.2a245a","type":"mqtt in","z":"83a55bb2.a1bfd","name":"Temperature","topic":"Temperature","qos":"2","broker":"d76a1508.8f5a7","x":110,"y":180,"wires":[["6c74be3d.5cea6","a5e06e93.b192c"]]},{"id":"253a96cb.f25d02","type":"mqtt in","z":"83a55bb2.a1bfd","name":"Humidity","topic":"Humidity","qos":"2","broker":"d76a1508.8f5a7","x":120,"y":280,"wires":[["8f97b9b3.49a4d"]]},{"id":"535e502d.91bfc8","type":"mqtt in","z":"83a55bb2.a1bfd","name":"HeatIndex","topic":"HeatIndex","qos":"2","broker":"d76a1508.8f5a7","x":120,"y":340,"wires":[["43548ecf.adfb1"]]},{"id":"a5e06e93.b192c","type":"ui_gauge","z":"83a55bb2.a1bfd","name":"","group":"cce8a1de.f44dd","order":3,"width":"3","height":"3","gtype":"gage","title":"Temperature","label":"centigrade","format":"{{value}}","min":0,"max":"40","colors":["#1D83FC","#A2F0FF","#CA3838"],"seg1":"20","seg2":"28","x":390,"y":220,"wires":[]},{"id":"6c74be3d.5cea6","type":"ui_chart","z":"83a55bb2.a1bfd","name":"","group":"cce8a1de.f44dd","order":4,"width":"9","height":"3","label":"Temperature (last hour)","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"Loading...","dot":false,"ymin":"10","ymax":"40","removeOlder":"24","removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1F77B4","#AEC7E8","#FF7F0E","#2CA02C","#98DF8A","#D62728","#FF9896","#9467BD","#C5B0D5"],"useOldStyle":false,"x":420,"y":180,"wires":[[],[]]},{"id":"8f97b9b3.49a4d","type":"ui_gauge","z":"83a55bb2.a1bfd","name":"","group":"cce8a1de.f44dd","order":5,"width":"3","height":"3","gtype":"wave","title":"Humidity","label":"","format":"{{value}}","min":"0","max":"100","colors":["#00B500","#E6E600","#CA3838"],"seg1":"","seg2":"","x":380,"y":280,"wires":[]},{"id":"43548ecf.adfb1","type":"ui_gauge","z":"83a55bb2.a1bfd","name":"","group":"cce8a1de.f44dd","order":6,"width":"4","height":"4","gtype":"donut","title":"Heat Index","label":"","format":"{{value}}","min":"0","max":"100","colors":["#00B500","#E6E600","#CA3838"],"seg1":"","seg2":"","x":390,"y":340,"wires":[]},{"id":"8e2b35cc.1f1558","type":"function","z":"83a55bb2.a1bfd","name":"/ 10","func":"msg.payload = msg.payload / 10;\nreturn msg;","outputs":1,"noerr":0,"x":250,"y":140,"wires":[["655ad28f.4e7aac"]]},{"id":"d76a1508.8f5a7","type":"mqtt-broker","z":"","name":"","broker":"mqtt://username:password@broker_url","port":"1883","tls":"f05336d4.0d2538","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","willTopic":"","willQos":"0","willRetain":"false","willPayload":""},{"id":"cce8a1de.f44dd","type":"ui_group","z":"","name":"MQTT Feed","tab":"804cad54.8a47e8","disp":false,"width":"12","collapse":false},{"id":"f05336d4.0d2538","type":"tls-config","z":"","name":"","cert":"","key":"","ca":"","certname":"Certificates.cer","keyname":"Certificates.p12","caname":"","verifyservercert":false},{"id":"804cad54.8a47e8","type":"ui_tab","z":"","name":"Home","icon":"dashboard"}]
That’s it! After you deploy, your dashboard is available at /ui
under your Heroku server’s address – http://digitallabs-node-red.herokuapp.com
/ui
in our case.
Further uses
We’ve seen how easy it is to push data to an MQTT broker, and then to drag a mqtt
in node to a dashboard
output node, to create a visualisation – for both live(ish) and historical time-series data.
It’s worth double-clicking the chart
and gauge
nodes in the Heroku-hosted application. There’s a number of configuration options and visualisation types. If you want to explore Node-red more, it’s even possible to combine data sources and overlay them in a single graph.
Remote environmental sensing
If you can attach a solar panel and lithium battery to your Pi, and connect it to a wireless network, you have a remote environmental monitoring system. You could even patch in nodes on the Heroku side to notify you if the temperature or another sensor crossed a threshold. This could be useful for a wide range of applications – farming and agricultural uses, mushroom growing, even monitoring apiaries.
Equally, by using different sensors, water and flood monitoring applications become available. Instead of using Wifi or Ethernet for network connections, the open ThingsNetwork provides a Node-red module for sending and receiving to devices, and a large number of contract-less LoRaWAN devices capable of sending sensory and telemetry data long distances without using much power. Node-red can be used to accumulate data and push it to dashboards and databases, either through a Pi or through a Heroku-hosted instance.
If you’d like a workshop or support for your project or department in using Node-red, please contact us through our contact form or email!