-
-
Notifications
You must be signed in to change notification settings - Fork 20
node red
To test VSCP with node-red you can use the VSCP demo server located at demo.vscp.org. This server has a MQTT broker active for public use at port 1883 which can be accessed with user="vscp" and password="secret". Also this server have websocket support on port 9001. The demo server is fully described here.
This is a simple flow that display the temperature in our kitchen. The temperature is displayed in a gauge as well as in a diagram and looks like this
The code for the flow is
[
{
"id": "8102f2ad6305cf60",
"type": "tab",
"label": "Kitchen",
"disabled": false,
"info": ""
},
{
"id": "7a22f145c2557f3e",
"type": "mqtt in",
"z": "8102f2ad6305cf60",
"name": "Fridge compressor OFF",
"topic": "vscp/25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:01/30/6/#",
"qos": "2",
"datatype": "json",
"broker": "5438645a.6577cc",
"nl": false,
"rap": true,
"rh": 0,
"x": 180,
"y": 160,
"wires": [
[
"480d0ecbeb2ee39b",
"a668bbf077a1232e"
]
]
},
{
"id": "a668bbf077a1232e",
"type": "debug",
"z": "8102f2ad6305cf60",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 410,
"y": 300,
"wires": []
},
{
"id": "480d0ecbeb2ee39b",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "",
"func": "msg.payload = false;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 400,
"y": 160,
"wires": [
[
"c76bea61c33e4196"
]
]
},
{
"id": "c22646aa5b800608",
"type": "mqtt in",
"z": "8102f2ad6305cf60",
"name": "Fride compressor ON",
"topic": "vscp/25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:01/30/5/#",
"qos": "2",
"datatype": "json",
"broker": "5438645a.6577cc",
"nl": false,
"rap": true,
"rh": 0,
"x": 180,
"y": 240,
"wires": [
[
"a4e0a0479ddb8d36",
"a668bbf077a1232e"
]
]
},
{
"id": "c76bea61c33e4196",
"type": "ui_switch",
"z": "8102f2ad6305cf60",
"name": "Show status for fridge compressor",
"label": "Fridge Compressor Status",
"tooltip": "",
"group": "ff769916b5262def",
"order": 0,
"width": "6",
"height": "4",
"passthru": true,
"decouple": "false",
"topic": "topic",
"topicType": "msg",
"style": "",
"onvalue": "true",
"onvalueType": "bool",
"onicon": "",
"oncolor": "",
"offvalue": "false",
"offvalueType": "bool",
"officon": "",
"offcolor": "",
"animate": false,
"x": 720,
"y": 240,
"wires": [
[]
]
},
{
"id": "a4e0a0479ddb8d36",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "",
"func": "msg.payload = true;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 400,
"y": 240,
"wires": [
[
"c76bea61c33e4196"
]
]
},
{
"id": "ba72084256e982f2",
"type": "mqtt in",
"z": "8102f2ad6305cf60",
"name": "Kelvin NTC10K control unit temperature",
"topic": "vscp/25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:01/1040/6/1/0/#",
"qos": "2",
"datatype": "json",
"broker": "5438645a.6577cc",
"nl": false,
"rap": true,
"rh": 0,
"x": 230,
"y": 380,
"wires": [
[
"8e8b7e7b7ec27109",
"0a01abc011e9341a",
"2d068c9e1486b16c"
]
]
},
{
"id": "5ede0c98001c8d5f",
"type": "ui_gauge",
"z": "8102f2ad6305cf60",
"name": "Kelvin NTC10K control unit temperature",
"group": "ff769916b5262def",
"order": 1,
"width": "6",
"height": "4",
"gtype": "gage",
"title": "Kelvin NTC10K control unit temperature",
"label": "Degrees Celsius",
"format": "{{value}}",
"min": 0,
"max": "40",
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "30",
"seg2": "35",
"x": 740,
"y": 380,
"wires": []
},
{
"id": "8e8b7e7b7ec27109",
"type": "debug",
"z": "8102f2ad6305cf60",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 490,
"y": 460,
"wires": []
},
{
"id": "0a01abc011e9341a",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "",
"func": "msg.value = msg.payload.measurement.value;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 380,
"wires": [
[
"5ede0c98001c8d5f"
]
]
},
{
"id": "fcfc9205225da3e1",
"type": "mqtt in",
"z": "8102f2ad6305cf60",
"name": "Fridge temperature",
"topic": "vscp/25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:01/1040/6/1/1/#",
"qos": "2",
"datatype": "json",
"broker": "5438645a.6577cc",
"nl": false,
"rap": true,
"rh": 0,
"x": 170,
"y": 540,
"wires": [
[
"b88d9004557f918b",
"b764a68b8c2b279a",
"677ae44fd21716e0"
]
]
},
{
"id": "df692dc6de983a9d",
"type": "ui_gauge",
"z": "8102f2ad6305cf60",
"name": "Fridge temperature",
"group": "ff769916b5262def",
"order": 1,
"width": "6",
"height": "4",
"gtype": "gage",
"title": "Fridge temperature",
"label": "Degrees Celsius",
"format": "{{value}}",
"min": "-40",
"max": "20",
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "-15",
"seg2": "-10",
"x": 670,
"y": 540,
"wires": []
},
{
"id": "b88d9004557f918b",
"type": "debug",
"z": "8102f2ad6305cf60",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 490,
"y": 640,
"wires": []
},
{
"id": "b764a68b8c2b279a",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "",
"func": "msg.value = msg.payload.measurement.value;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 540,
"wires": [
[
"df692dc6de983a9d"
]
]
},
{
"id": "0fd4abed36d9bbc4",
"type": "mqtt in",
"z": "8102f2ad6305cf60",
"name": "Fridge compressor temperature",
"topic": "vscp/25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:01/1040/6/1/2/#",
"qos": "2",
"datatype": "json",
"broker": "5438645a.6577cc",
"nl": false,
"rap": true,
"rh": 0,
"x": 210,
"y": 700,
"wires": [
[
"e79d32790ed5be0f",
"64a2391749022276",
"254162848a40c9c8"
]
]
},
{
"id": "5fb8cec38b8dedf9",
"type": "ui_gauge",
"z": "8102f2ad6305cf60",
"name": "Fridge compressor temperature",
"group": "ff769916b5262def",
"order": 1,
"width": "6",
"height": "4",
"gtype": "gage",
"title": "Fridge compressor temperature",
"label": "Degrees Celsius",
"format": "{{value}}",
"min": "0",
"max": "100",
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "40",
"seg2": "50",
"x": 710,
"y": 700,
"wires": []
},
{
"id": "e79d32790ed5be0f",
"type": "debug",
"z": "8102f2ad6305cf60",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 490,
"y": 780,
"wires": []
},
{
"id": "64a2391749022276",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "",
"func": "msg.value = msg.payload.measurement.value;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 700,
"wires": [
[
"5fb8cec38b8dedf9"
]
]
},
{
"id": "232909de7ea3c2a6",
"type": "mqtt in",
"z": "8102f2ad6305cf60",
"name": "Kitchen temperature",
"topic": "vscp/25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:01/1040/6/1/4",
"qos": "2",
"datatype": "json",
"broker": "5438645a.6577cc",
"nl": false,
"rap": true,
"rh": 0,
"x": 170,
"y": 880,
"wires": [
[
"0872eb4b26853ba0",
"758cfa9b809619d8",
"c6c6231fd7b036f4",
"42b0b8dd162f8ac1"
]
]
},
{
"id": "87755f461260e112",
"type": "ui_gauge",
"z": "8102f2ad6305cf60",
"name": "Kitchen temperature",
"group": "ff769916b5262def",
"order": 1,
"width": "6",
"height": "4",
"gtype": "gage",
"title": "Kitchen temperature",
"label": "Degrees Celsius",
"format": "{{value}}",
"min": "0",
"max": "40",
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "25",
"seg2": "30",
"x": 680,
"y": 880,
"wires": []
},
{
"id": "0872eb4b26853ba0",
"type": "debug",
"z": "8102f2ad6305cf60",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 490,
"y": 960,
"wires": []
},
{
"id": "758cfa9b809619d8",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "",
"func": "msg.value = msg.payload.measurement.value;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 880,
"wires": [
[
"87755f461260e112"
]
]
},
{
"id": "c8aaa698852ae30e",
"type": "ui_chart",
"z": "8102f2ad6305cf60",
"name": "Kitchen temperature",
"group": "ff769916b5262def",
"order": 5,
"width": "11",
"height": "5",
"label": "Kitchen Temperature",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm",
"interpolate": "linear",
"nodata": "No data",
"dot": false,
"ymin": "0",
"ymax": "40",
"removeOlder": "12",
"removeOlderPoints": "",
"removeOlderUnit": "3600",
"cutout": 0,
"useOneColor": false,
"useUTC": false,
"colors": [
"#1d6faa",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"outputs": 1,
"useDifferentColor": false,
"x": 680,
"y": 920,
"wires": [
[]
]
},
{
"id": "c6c6231fd7b036f4",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "",
"func": "msg.payload = msg.payload.measurement.value;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 920,
"wires": [
[
"c8aaa698852ae30e"
]
]
},
{
"id": "894822392515d165",
"type": "ui_chart",
"z": "8102f2ad6305cf60",
"name": "Fridge Compressor temperature",
"group": "ff769916b5262def",
"order": 5,
"width": "11",
"height": "5",
"label": "Fridge compressor Temperature",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm",
"interpolate": "linear",
"nodata": "No data",
"dot": false,
"ymin": "0",
"ymax": "70",
"removeOlder": "12",
"removeOlderPoints": "",
"removeOlderUnit": "3600",
"cutout": 0,
"useOneColor": false,
"useUTC": false,
"colors": [
"#1d6faa",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"outputs": 1,
"useDifferentColor": false,
"x": 710,
"y": 740,
"wires": [
[]
]
},
{
"id": "254162848a40c9c8",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "",
"func": "msg.payload = msg.payload.measurement.value;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 740,
"wires": [
[
"894822392515d165"
]
]
},
{
"id": "677ae44fd21716e0",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "",
"func": "msg.payload = msg.payload.measurement.value;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 580,
"wires": [
[
"0970931d00cf465d"
]
]
},
{
"id": "0970931d00cf465d",
"type": "ui_chart",
"z": "8102f2ad6305cf60",
"name": "Fridge temperature",
"group": "ff769916b5262def",
"order": 5,
"width": "11",
"height": "5",
"label": "Fridge Temperature",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm",
"interpolate": "linear",
"nodata": "No data",
"dot": false,
"ymin": "-30",
"ymax": "20",
"removeOlder": "12",
"removeOlderPoints": "",
"removeOlderUnit": "3600",
"cutout": 0,
"useOneColor": false,
"useUTC": false,
"colors": [
"#1d6faa",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"outputs": 1,
"useDifferentColor": false,
"x": 670,
"y": 580,
"wires": [
[]
]
},
{
"id": "2d068c9e1486b16c",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "",
"func": "msg.payload = msg.payload.measurement.value;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 420,
"wires": [
[
"0581c00e3ba5b83a"
]
]
},
{
"id": "0581c00e3ba5b83a",
"type": "ui_chart",
"z": "8102f2ad6305cf60",
"name": "Kelvin NTC temperature",
"group": "ff769916b5262def",
"order": 5,
"width": "11",
"height": "5",
"label": "Kelvin NTC10K Temperature",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm",
"interpolate": "linear",
"nodata": "No data",
"dot": false,
"ymin": "0",
"ymax": "40",
"removeOlder": "12",
"removeOlderPoints": "",
"removeOlderUnit": "3600",
"cutout": 0,
"useOneColor": false,
"useUTC": false,
"colors": [
"#1d6faa",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"outputs": 1,
"useDifferentColor": false,
"x": 690,
"y": 420,
"wires": [
[]
]
},
{
"id": "42b0b8dd162f8ac1",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "",
"func": "var utcDate = msg.payload.vscpDateTime;\nmsg.payload.localtime = new Date(utcDate);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 1020,
"wires": [
[
"b948c487abc81fe6"
]
]
},
{
"id": "b948c487abc81fe6",
"type": "debug",
"z": "8102f2ad6305cf60",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 670,
"y": 1020,
"wires": []
},
{
"id": "1808f66585de11aa",
"type": "mqtt in",
"z": "8102f2ad6305cf60",
"name": "Kitchen temperature",
"topic": "vscp/25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:01/1040/6/1/4",
"qos": "2",
"datatype": "json",
"broker": "d5c2659b.267728",
"nl": false,
"rap": true,
"rh": 0,
"x": 170,
"y": 1120,
"wires": [
[
"eb77935aa44eeb1e"
]
]
},
{
"id": "83e4c24fab4c374b",
"type": "ui_gauge",
"z": "8102f2ad6305cf60",
"name": "Kitchen temperature",
"group": "ff769916b5262def",
"order": 1,
"width": "6",
"height": "4",
"gtype": "gage",
"title": "Kitchen temperature",
"label": "Degrees Celsius",
"format": "{{value}}",
"min": "0",
"max": "40",
"colors": [
"#00b500",
"#e6e600",
"#ca3838"
],
"seg1": "25",
"seg2": "30",
"x": 920,
"y": 1120,
"wires": []
},
{
"id": "efc68f7b1ad54ff1",
"type": "debug",
"z": "8102f2ad6305cf60",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 630,
"y": 1200,
"wires": []
},
{
"id": "0e5e19ded032ba48",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "Set measurement value",
"func": "msg.value = msg.payload.measurement.value;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 670,
"y": 1120,
"wires": [
[
"83e4c24fab4c374b"
]
]
},
{
"id": "21a9fd8531d7d058",
"type": "ui_chart",
"z": "8102f2ad6305cf60",
"name": "Kitchen temperature",
"group": "ff769916b5262def",
"order": 5,
"width": "11",
"height": "5",
"label": "Kitchen Temperature",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm",
"interpolate": "linear",
"nodata": "No data",
"dot": false,
"ymin": "0",
"ymax": "40",
"removeOlder": "12",
"removeOlderPoints": "",
"removeOlderUnit": "3600",
"cutout": 0,
"useOneColor": false,
"useUTC": false,
"colors": [
"#1d6faa",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"outputs": 1,
"useDifferentColor": false,
"x": 920,
"y": 1160,
"wires": [
[]
]
},
{
"id": "e4be5ab290fee203",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "Set measurement value",
"func": "msg.payload = msg.payload.measurement.value;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 670,
"y": 1160,
"wires": [
[
"21a9fd8531d7d058"
]
]
},
{
"id": "eb77935aa44eeb1e",
"type": "function",
"z": "8102f2ad6305cf60",
"name": "Add localtime",
"func": "var utcDate = msg.payload.vscpDateTime;\nmsg.payload.localtime = new Date(utcDate);\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 380,
"y": 1120,
"wires": [
[
"0e5e19ded032ba48",
"e4be5ab290fee203",
"efc68f7b1ad54ff1"
]
]
},
{
"id": "5438645a.6577cc",
"type": "mqtt-broker",
"name": "Local",
"broker": "localhost",
"port": "1883",
"clientid": "lynx",
"usetls": false,
"compatmode": false,
"protocolVersion": "4",
"keepalive": "60",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"birthMsg": {},
"closeTopic": "",
"closeQos": "0",
"closePayload": "",
"closeMsg": {},
"willTopic": "",
"willQos": "0",
"willPayload": "",
"willMsg": {},
"sessionExpiry": ""
},
{
"id": "ff769916b5262def",
"type": "ui_group",
"name": "Brattberg",
"tab": "a4efd49613773787",
"order": 1,
"disp": true,
"width": "11",
"collapse": false
},
{
"id": "d5c2659b.267728",
"type": "mqtt-broker",
"name": "Demo server",
"broker": "demo.vscp.org",
"port": "1883",
"clientid": "",
"usetls": false,
"protocolVersion": "4",
"keepalive": "60",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"birthMsg": {},
"closeTopic": "",
"closePayload": "",
"closeMsg": {},
"willTopic": "",
"willQos": "0",
"willPayload": "",
"willMsg": {},
"sessionExpiry": "",
"credentials": {}
},
{
"id": "a4efd49613773787",
"type": "ui_tab",
"name": "Kitchen",
"icon": "dashboard",
"disabled": false,
"hidden": false
}
]
Copy to clipboard and import in [node-red]](https://nodered.org/docs/user-guide/editor/workspace/import-export).
Note that you need to add the user and the password (vscp/secret) manually to the security tab of the node-red MQTT in node.
The subscribe topic may need an explanation. It is set to
vscp/25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:01/1040/6/1/4/#
The
25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:01
is the GUID for the node that publish the events we are interested in. In this case
25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:00
is assigned to a CAN driver CAN4VSCP and the 01 at the end of the GUID is one of a nodes on the bus. In this case a Kelvin NTC10K module.
The
1040/6
says that we are interested only in temperature events from the node.
The
1
is for node with nickname 1. and the
4
is for sensor 4 on this board. Changing this to
vscp/25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:01/1040/6/#
would give us all temperature event from all sensors of the node.
Changing it to
vscp/25:00:00:00:00:00:00:00:00:00:00:00:06:00:00:01/#
would give all events from the node (heartbeats for instance). Not just temperature events.
This topic organisation is just one way to do it so don't expect all VSCP MQTT topics to be on this form. How this is setup on the demo server is described here
In the above flow we don't care about the unit of the temperature measurement. If we look in the specification we see that it is actually there as for all measurement events. In this case set to 1 which is degrees Celsius. The other unit options Kelvin (=0) and Fahrenheit (=2) could also be expected here. General code should handle this and don't expect the measurement unit to be in a specific unit as in this simple example.
VSCP event have date and time set in UTC to be universally usable. To get local time you have to convert this UTC time to a local time. But don't despair the conversion is easy.
Add a function node in the flow from the MQTT broker with the following content
var utcDate = msg.payload.vscpDateTime;
msg.payload.localtime = new Date(utcDate);
return msg;
you will now have the localtime in msg.payload.localtime and can
The VSCP Project (https://www.vscp.org) - Copyright © 2000-2024 Åke Hedman, the VSCP Project