After hearing over and over how quick and easy the graphical programming environment for Node-Red was we decided to give it a try with an old Raspberry PI Model B that was 'resting' in a drawer. Conclusion: It's easy; it's really really easy. Plus, there is a large user base that has created examples and libraries for just about any application you can dream up.
-----
Node-Red is free and the install is easy and well documented on their website. For our Node-Red experiment we decide to graph the ambient air temperature as measured by a DS18B20 and the CPU core temperature of the Raspberry PI Model B. Connect the DS18B20 sensor like this:
-----
It didn't take us long at all to 'noodle' up this:
-----
Then we went into the "Layout" tab to format what the graphs would look like:
----
All in all the project, including the Node-Red install; was probably under two hours. That's pretty damn quick for going from zero knowledge to serving up nice graphs.
-----
Importing or Exporting code is easy as well. It's basically "copy/past". Here is our code for the project:
[
{
"id": "018abb4b7bfb7e86",
"type": "exec",
"z": "c0bb5756099d6dbc",
"command": "vcgencmd measure_temp",
"addpay": false,
"append": "",
"useSpawn": "false",
"timer": "",
"oldrc": false,
"name": "Get CPU Temp",
"x": 420,
"y": 40,
"wires": [
[
"05c0f7272e5bc7e0"
],
[],
[]
]
},
{
"id": "05c0f7272e5bc7e0",
"type": "function",
"z": "c0bb5756099d6dbc",
"name": "Parse Temp",
"func": "var tempC = parseFloat(msg.payload.replace('temp=', '').replace(\"'C\", ''));\nvar tempF = (tempC * 9/5) + 32;\nmsg.payload = tempF.toFixed(2);\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 630,
"y": 40,
"wires": [
[
"7dfbce89f48de845",
"d97496ad6fb77af6"
]
]
},
{
"id": "7dfbce89f48de845",
"type": "ui_chart",
"z": "c0bb5756099d6dbc",
"name": "",
"group": "7",
"order": 8,
"width": 11,
"height": 5,
"label": "CPU (°F)",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm",
"interpolate": "linear",
"nodata": "",
"dot": false,
"ymin": "",
"ymax": "",
"removeOlder": "7",
"removeOlderPoints": "10080",
"removeOlderUnit": "86400",
"cutout": 0,
"useOneColor": false,
"useUTC": false,
"colors": [
"#00b500",
"#e6e600",
"#ca3838",
"#000000",
"#000000",
"#000000",
"#000000",
"#000000",
"#000000"
],
"outputs": 1,
"useDifferentColor": false,
"className": "",
"x": 880,
"y": 40,
"wires": [
[]
]
},
{
"id": "d97496ad6fb77af6",
"type": "ui_gauge",
"z": "c0bb5756099d6dbc",
"name": "",
"group": "7",
"order": 7,
"width": 5,
"height": 5,
"gtype": "donut",
"title": "CPU (°F)",
"label": "°F",
"format": "{{value}}",
"min": "110",
"max": "175",
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "",
"seg2": "",
"diff": false,
"className": "",
"x": 880,
"y": 80,
"wires": []
},
{
"id": "3b8516632c6153ec",
"type": "debug",
"z": "c0bb5756099d6dbc",
"name": "DC18B20 Temp",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 900,
"y": 260,
"wires": []
},
{
"id": "e19a60a2f08ac386",
"type": "inject",
"z": "c0bb5756099d6dbc",
"name": "Every 60 secs",
"props": [],
"repeat": "60",
"crontab": "",
"once": true,
"onceDelay": "1",
"topic": "",
"x": 160,
"y": 40,
"wires": [
[
"018abb4b7bfb7e86"
]
]
},
{
"id": "a3b79e7f7975fa73",
"type": "ds18b20",
"z": "c0bb5756099d6dbc",
"name": "DS18B20",
"sensorid": "28-089bd445e089",
"timer": "1",
"x": 380,
"y": 220,
"wires": [
[
"3d28949a3fa611d3"
]
]
},
{
"id": "3d28949a3fa611d3",
"type": "function",
"z": "c0bb5756099d6dbc",
"name": "C_to_F",
"func": "var tempc = msg.payload;\nvar tempf = tempc * 9/5 + 32;\ntempf = tempf.toFixed(2);\nmsg.payload = tempf;\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 600,
"y": 220,
"wires": [
[
"3b8516632c6153ec",
"61cf75a9eeeb79be",
"e146810a6d814e42"
]
]
},
{
"id": "e146810a6d814e42",
"type": "ui_chart",
"z": "c0bb5756099d6dbc",
"name": "",
"group": "7",
"order": 3,
"width": 11,
"height": 9,
"label": "°F",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm",
"interpolate": "linear",
"nodata": "",
"dot": false,
"ymin": "",
"ymax": "",
"removeOlder": "7",
"removeOlderPoints": "10080",
"removeOlderUnit": "86400",
"cutout": 0,
"useOneColor": false,
"useUTC": false,
"colors": [
"#00b500",
"#e6e600",
"#ca3838",
"#000000",
"#000000",
"#000000",
"#000000",
"#000000",
"#000000"
],
"outputs": 1,
"useDifferentColor": false,
"className": "",
"x": 870,
"y": 180,
"wires": [
[]
]
},
{
"id": "61cf75a9eeeb79be",
"type": "ui_gauge",
"z": "c0bb5756099d6dbc",
"name": "",
"group": "7",
"order": 2,
"width": 5,
"height": 9,
"gtype": "donut",
"title": "Ambient (°F)",
"label": "°F",
"format": "{{value}}",
"min": "80",
"max": "110",
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "",
"seg2": "",
"diff": false,
"className": "",
"x": 890,
"y": 220,
"wires": []
},
{
"id": "cc4248afd8356380",
"type": "debug",
"z": "c0bb5756099d6dbc",
"name": "debug 1",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 880,
"y": 400,
"wires": []
},
{
"id": "1553124d816901d2",
"type": "inject",
"z": "c0bb5756099d6dbc",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "1",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 170,
"y": 360,
"wires": [
[
"cc4248afd8356380",
"6f3d2d25b6ad464e"
]
]
},
{
"id": "6f3d2d25b6ad464e",
"type": "ui_digital_clock",
"z": "c0bb5756099d6dbc",
"name": "",
"group": "7",
"order": 5,
"width": 4,
"height": 1,
"x": 890,
"y": 360,
"wires": []
},
{
"id": "7",
"type": "ui_group",
"name": "RasPI-3B",
"tab": "6",
"order": 1,
"disp": true,
"width": 16,
"collapse": false,
"className": ""
},
{
"id": "6",
"type": "ui_tab",
"name": "Home",
"icon": "dashboard",
"order": 1
}
]
-----