Skip to content

Instantly share code, notes, and snippets.

@ubi-gists
Created March 7, 2023 21:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ubi-gists/25ab0e2ffeecfcfef6cd66d402fa214f to your computer and use it in GitHub Desktop.
Save ubi-gists/25ab0e2ffeecfcfef6cd66d402fa214f to your computer and use it in GitHub Desktop.
[
{
"id": "1e3ade0e.dd0622",
"type": "tab",
"label": "Data and Device Manager",
"disabled": false,
"info": ""
},
{
"id": "otaManager",
"type": "tab",
"label": "OTA Manager",
"disabled": false,
"info": ""
},
{
"id": "837142ce.132b28",
"type": "ncd-gateway-config",
"name": "",
"comm_type": "serial",
"ip_address": "",
"tcp_port": "2101",
"port": "/dev/ttyS1",
"baudRate": "115200",
"pan_id": "7FFF",
"rssi": true
},
{
"id": "a2af30673810cf0b",
"type": "ncd-gateway-config",
"name": "",
"comm_type": "serial",
"ip_address": "",
"tcp_port": "2101",
"port": "COM7",
"baudRate": "115200",
"pan_id": "7fff",
"rssi": false
},
{
"id": "32075b5e.a38564",
"type": "tls-config",
"name": "",
"cert": "",
"key": "",
"ca": "",
"certname": "",
"keyname": "",
"caname": "cert.pem",
"servername": "",
"verifyservercert": true
},
{
"id": "c3234b3e.b3c4a",
"type": "debug",
"z": "1e3ade0e.dd0622",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 410,
"y": 300,
"wires": []
},
{
"id": "1cda1635.32f03a",
"type": "http request",
"z": "1e3ade0e.dd0622",
"name": "Send to Plugin",
"method": "use",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 1100,
"y": 260,
"wires": [
[
"f4dea380.cc9d1"
]
]
},
{
"id": "f4dea380.cc9d1",
"type": "debug",
"z": "1e3ade0e.dd0622",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1310,
"y": 260,
"wires": []
},
{
"id": "c21ff918.954578",
"type": "function",
"z": "1e3ade0e.dd0622",
"name": "Check Raw or Processed",
"func": "const supportedDeviceTypes = [\n 8, // Vibration\n 81, // Two channel vibration sensor\n 82, // Condition monitoting (Viibration and Temp)\n 84 // Standalong vibration sensor\n]\nlet message = msg.payload;\n\nif (typeof message == 'object' && 'sensor_type' in message){\n if ('data' in message['sensor_data'] && supportedDeviceTypes.includes(message.sensor_type)){\n // Data is raw\n return [msg, null];\n \n } else if (!('data' in message['sensor_data']) && supportedDeviceTypes.includes(message.sensor_type)) {\n // Data is processed\n return [null, msg];\n }\n}\n\nreturn;",
"outputs": 2,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 450,
"y": 260,
"wires": [
[
"1c32fc1b.970494"
],
[
"c1f32b8b.7fc238",
"2636e711.0f42c8"
]
]
},
{
"id": "1c32fc1b.970494",
"type": "function",
"z": "1e3ade0e.dd0622",
"name": "Format Data",
"func": "var data = msg.payload;\nvar payload = {};\nlet ubidotsToken = global.get('UbidotsToken')\n\npayload['data'] = data['sensor_data']['data'];\npayload['deviceLabel'] = data.addr;\npayload['temp'] = data['sensor_data']['device_temp'];\npayload['nodeId'] = data.nodeId;\npayload['firmware'] = data.firmware;\npayload['battery'] = data.battery;\npayload['battery_percent'] = data['battery_percent'];\npayload['counter'] = data.counter;\npayload['sensor_type'] = data['sensor_type'];\npayload['odr'] = data['sensor_data']['odr'];\n\nmsg.payload = payload;\nmsg.headers = {};\nmsg.headers[\"Content-Type\"] = \"application/json\";\nmsg.headers[\"X-Auth-Token\"] = ubidotsToken;\nmsg.method = \"POST\";\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 890,
"y": 260,
"wires": [
[
"1cda1635.32f03a",
"49480086.2e71b"
]
]
},
{
"id": "6d042a82.e8e534",
"type": "comment",
"z": "1e3ade0e.dd0622",
"name": "Send through FFT Plugin",
"info": "",
"x": 930,
"y": 220,
"wires": []
},
{
"id": "14ec9f1f.c92321",
"type": "comment",
"z": "1e3ade0e.dd0622",
"name": "Send through API",
"info": "",
"x": 900,
"y": 320,
"wires": []
},
{
"id": "c1f32b8b.7fc238",
"type": "function",
"z": "1e3ade0e.dd0622",
"name": "Format Data",
"func": "let data = msg.payload['sensor_data'];\nmsg.ubidotsDeviceLabel = msg.payload.addr;\nlet ubidotsToken = global.get('UbidotsToken')\nlet payload = {};\n\npayload = data;\nif (msg.payload.sensor_type != 8) {\n payload.odr = payload.odr.slice(0,-2);\n}\npayload['battery_percentage'] = msg.payload['battery_percent'];\npayload.battery = msg.payload.battery;\ndelete payload['Ext_temperature'];\n\nmsg.payload = payload;\nmsg.headers = {};\nmsg.headers[\"Content-Type\"] = \"application/json\";\nmsg.headers[\"X-Auth-Token\"] = ubidotsToken;\nmsg.method = \"POST\";\n\nmsg.url = 'http://industrial.api.ubidots.com/api/v1.6/devices/' + msg.ubidotsDeviceLabel;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 890,
"y": 360,
"wires": [
[
"c4526b89.6e82c8"
]
]
},
{
"id": "93725a8b.f625b8",
"type": "http request",
"z": "1e3ade0e.dd0622",
"name": "GET OTA Flow",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "http://localhost:1880/flow/otaManager",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 400,
"y": 600,
"wires": [
[
"468c636.cebe79c",
"140a2667.c87b0a"
]
]
},
{
"id": "468c636.cebe79c",
"type": "function",
"z": "1e3ade0e.dd0622",
"name": "Flow Updater",
"func": "/* \n * This function checks if the Device already has an associated\n * \"Wireless Device Node\" in the OTA Manager flow. If not, sends a message\n * to update the flow via the Node-Red API and the type of sensor. \n * See supported type of sensor below.\n/*\n\n/* \n * Supported NCD Sensor types:\n * Type 81 \"Two Channel Vibration Plus\" https://store.ncd.io/product/2-channel-vibration-sensor-v3/ \n * type 82 \"Condition Based/Predictive Maintenance Sensor\" https://store.ncd.io/product/iot-wireless-predictive-maintenance-sensor/\n * Type 84 \"Vibration on a stick\" https://store.ncd.io/product/smart-industrial-iot-wireless-vibration-temperature-sensor/\n *\n * For additional technical documentation, click on the Resources tab, then on the Product manual\n * in each of the links.\n*/\nconst initialNodes = {\n //81: \"initialWirelessNode81\", \n 82: \"initialWirelessNode82\",\n 84: \"initialWirelessNode84\",\n}\n\n// Id of the flow where the Wireless Device Node reside.\nconst otaFlowId = 'otaManager';\n// Id of the function node to confirm. Resides in OTA Manager flow\nconst configConfirmationNodeId = 'config.confirmation';\n\nlet deviceSensorType = msg.deviceSensorType;\nif (!Object.keys(initialNodes).includes(String(deviceSensorType))) {\n return; // While developing only Type 82 and 84 are supported.\n}\nlet initialWirelessNodeID = initialNodes[deviceSensorType];\n\nlet nodes = msg.payload.nodes;\nlet newNodes = JSON.parse(JSON.stringify(nodes));\nlet maxY = 0;\n\nconst wirelessNode = nodes.filter(node => node.id == initialWirelessNodeID)[0];\nconst configConfirmation = nodes.filter(node => node.id == configConfirmationNodeId)[0];\nlet newDevAddr = msg.deviceLabel;\n\nlet existentNode = nodes.filter(node => node.id == newDevAddr)[0];\n\nif (existentNode != undefined){\n return; // Meaning the node already exists\n}\n\n// This finds the graphically lowest Wireless node\nnodes.forEach((node) => {\n if (node.type == \"ncd-wireless-node\") {\n if (node.y > maxY) {\n maxY = node.y\n }\n }\n});\n\n// Create copy of target nodes\nlet newWirelessNode = JSON.parse(JSON.stringify(wirelessNode));\nlet newConfigConfirmationNode = JSON.parse(JSON.stringify(configConfirmation));\n\n// Change new Config confirmation node\nnewConfigConfirmationNode.id = \"config.confirmation.\"+newDevAddr;\nnewConfigConfirmationNode.y = maxY+60;\nnewConfigConfirmationNode.func = newConfigConfirmationNode.func.replace(\"MAC\",newDevAddr);\n// Connects the config confirmation node to Delay for Config Ubidots Post node\nnewConfigConfirmationNode.wires = [[\"config.post.delay\"]];\n\n// Change new Wireless Device node\nnewWirelessNode.id = newDevAddr;\nnewWirelessNode.name = newDevAddr;\nnewWirelessNode.addr = newDevAddr;\nnewWirelessNode.on_the_fly_enable = true;\nnewWirelessNode.y = maxY+60;\n// Connects the wireless node to its corresponding function node\nnewWirelessNode.wires = [[\"config.confirmation.\"+newDevAddr]];\n\nnewNodes.push(newWirelessNode);\nnewNodes.push(newConfigConfirmationNode);\n\nmsg.payload.nodes = newNodes;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 600,
"y": 600,
"wires": [
[
"89326274.73b33"
]
]
},
{
"id": "8cdab17a.208ff",
"type": "function",
"z": "1e3ade0e.dd0622",
"name": "Assign DevLabel",
"func": "let message = msg.payload;\nlet topic = msg.topic;\nvar gatewayMAC = global.get('gatewayMAC');\nlet commandSent = global.get(\"commandSent\");\nconst supportedDeviceTypes = [\n 81,\n 82,\n 84\n]\n\n//if (typeof message == 'object' && 'sensor_type' in message){\nif (topic === 'sensor_data'){\n if ('addr' in message && supportedDeviceTypes.includes(message.sensor_type)){\n msg.deviceLabel = message.addr;\n msg.deviceSensorType = message.sensor_type;\n \n // Check if device has already been added to commandSent obj\n if (!(message.addr in commandSent)){\n // if device not added, then add it with command = False\n //global.set(message.addr,false)\n commandSent[message.addr] = false\n }\n return msg;\n }\n}\n\nif (typeof message == 'string' && message.length == 23){\n let MAC = message;\n global.set('gatewayMAC', MAC)\n return;\n}\n\n\nreturn;",
"outputs": 1,
"noerr": 0,
"initialize": "// Code added here will be run once\n// whenever the node is deployed.\nlet gatewayMAC = global.get(\"gatewayMAC\");\nlet commandSent = global.get(\"commandSent\");\nif (!gatewayMAC){\n global.set(\"gatewayMAC\", {});\n}\n\nif (!commandSent){\n global.set(\"commandSent\", {});\n}",
"finalize": "",
"x": 150,
"y": 600,
"wires": [
[
"93725a8b.f625b8",
"a67427dd.f5a8d8",
"d2a229d6.7ead68"
]
]
},
{
"id": "1d617671.db939a",
"type": "http request",
"z": "1e3ade0e.dd0622",
"name": "POST to API",
"method": "use",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 1370,
"y": 360,
"wires": [
[
"bc2e7e32.5aef3"
]
]
},
{
"id": "bc2e7e32.5aef3",
"type": "debug",
"z": "1e3ade0e.dd0622",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1530,
"y": 360,
"wires": []
},
{
"id": "89326274.73b33",
"type": "http request",
"z": "1e3ade0e.dd0622",
"name": "Update Flow",
"method": "PUT",
"ret": "obj",
"paytoqs": "ignore",
"url": "http://localhost:1880/flow/otaManager",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 790,
"y": 600,
"wires": [
[]
]
},
{
"id": "1f5b0595.e7ccda",
"type": "inject",
"z": "1e3ade0e.dd0622",
"name": "Assign Token here",
"props": [
{
"p": "token",
"v": "",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"x": 690,
"y": 40,
"wires": [
[
"6ba14572.88b03c"
]
]
},
{
"id": "6ba14572.88b03c",
"type": "function",
"z": "1e3ade0e.dd0622",
"name": "Token into Context",
"func": "let ubidotsToken = msg.token;\n\nglobal.set('UbidotsToken',ubidotsToken)\n\nreturn;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 910,
"y": 40,
"wires": [
[]
]
},
{
"id": "2cd8ce6c.0409c2",
"type": "ncd-gateway-node",
"z": "1e3ade0e.dd0622",
"name": "",
"connection": "837142ce.132b28",
"unknown_devices": 0,
"outputs": 1,
"x": 170,
"y": 260,
"wires": [
[
"c21ff918.954578",
"c3234b3e.b3c4a",
"8cdab17a.208ff"
]
]
},
{
"id": "c4526b89.6e82c8",
"type": "delay",
"z": "1e3ade0e.dd0622",
"name": "",
"pauseType": "rate",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "4",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 1190,
"y": 360,
"wires": [
[
"1d617671.db939a"
]
]
},
{
"id": "1b6bed69.27b783",
"type": "function",
"z": "1e3ade0e.dd0622",
"name": "Assign Raw command to Device",
"func": "let deviceLabel = Object.keys(msg.payload)[0].slice(0,-12);\nlet commandInfo = msg.payload[deviceLabel+'/request-raw'];\nlet commandSent = global.get(\"commandSent\");\n\nif (deviceLabel in commandSent && commandInfo.value == 1){\n //if the device exists, it means it's a local device\n commandSent[deviceLabel] = true\n}\n\n\nreturn msg; ",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 370,
"y": 40,
"wires": [
[]
]
},
{
"id": "a67427dd.f5a8d8",
"type": "function",
"z": "1e3ade0e.dd0622",
"name": "Check if command is due",
"func": "var commandSent = global.get('commandSent');\nvar deviceLabel = msg.payload.addr;\n\nif (deviceLabel in commandSent){\n if (commandSent[deviceLabel] == true && msg.payload.sensor_data.hasOwnProperty(\"x_rms_ACC_G\")) {\n msg.payload.address = deviceLabel; \n\n msg.payload.data = [0xF4,0x4F,0x00,0x00,0x50,0x13];\n commandSent[deviceLabel] = false\n return msg;\n \n }\n}",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 410,
"y": 500,
"wires": [
[
"65b0cedc.47657"
]
]
},
{
"id": "65b0cedc.47657",
"type": "delay",
"z": "1e3ade0e.dd0622",
"name": "",
"pauseType": "delay",
"timeout": "100",
"timeoutUnits": "milliseconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 670,
"y": 500,
"wires": [
[
"2cd8ce6c.0409c2"
]
]
},
{
"id": "49480086.2e71b",
"type": "debug",
"z": "1e3ade0e.dd0622",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1120,
"y": 160,
"wires": []
},
{
"id": "d2a229d6.7ead68",
"type": "debug",
"z": "1e3ade0e.dd0622",
"name": "msg",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 380,
"y": 660,
"wires": []
},
{
"id": "e04f1aa9.077bf8",
"type": "ubidots_in",
"z": "1e3ade0e.dd0622",
"tier": "business",
"name": "Ubidots in ",
"token": "",
"device_label": "",
"tls_checkbox_in": false,
"custom_topic_checkbox": true,
"label_variable_1": "+/request-raw",
"label_variable_2": "",
"label_variable_3": "",
"label_variable_4": "",
"label_variable_5": "",
"label_variable_6": "",
"label_variable_7": "",
"label_variable_8": "",
"label_variable_9": "",
"label_variable_10": "",
"checkbox_variable_1_last_value": true,
"checkbox_variable_2_last_value": true,
"checkbox_variable_3_last_value": true,
"checkbox_variable_4_last_value": true,
"checkbox_variable_5_last_value": true,
"checkbox_variable_6_last_value": true,
"checkbox_variable_7_last_value": true,
"checkbox_variable_8_last_value": true,
"checkbox_variable_9_last_value": true,
"checkbox_variable_10_last_value": true,
"x": 130,
"y": 40,
"wires": [
[
"1b6bed69.27b783"
]
]
},
{
"id": "436d708e.9c9c8",
"type": "comment",
"z": "1e3ade0e.dd0622",
"name": "Update Node-red flow",
"info": "These Nodes: \"Get OTA Flow\", \"Flow Updater\", \"Update flow\" do the following:\n\n1. Verify if the Vibration sensor sending data is already taken into account in the OTA Manager flow, that is, if it already has a pair of Wireless device and Config confirmation\n\n2. If t doesn't exist yet, it creates the pair of nodes\n\n3. Updates the flow to reflect the new pair of nodes\n",
"x": 400,
"y": 560,
"wires": []
},
{
"id": "140a2667.c87b0a",
"type": "debug",
"z": "1e3ade0e.dd0622",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 570,
"y": 660,
"wires": []
},
{
"id": "config.confirmation",
"type": "function",
"z": "otaManager",
"name": "Config Confirmation",
"func": "let message = msg.payload;\nlet topic = msg.topic;\nlet deviceLabel = \"MAC\";\nlet OTAResults = msg.payload;\nlet devOtaStatus = global.get('devOtaStatus');\nlet ubidotsToken = global.get('UbidotsToken')\n\nif (deviceLabel == \"MAC\") {\n return;\n}\n\n\nif (topic == 'Config Results' && devOtaStatus[deviceLabel] != 2){\n msg.payload = {\"ota\":{\"value\": 2, \"context\": {\"status\": \"OTA finished: \" + JSON.stringify(OTAResults)}}}\n \n msg.ubidotsDeviceLabel = deviceLabel;\n msg.headers = {};\n msg.headers[\"Content-Type\"] = \"application/json\";\n msg.headers[\"X-Auth-Token\"] = ubidotsToken;\n msg.method = \"POST\";\n \n \n return msg\n \n}\n\nreturn;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 380,
"y": 40,
"wires": [
[
"config.post.delay"
]
]
},
{
"id": "d84f2ab.787bbd8",
"type": "debug",
"z": "otaManager",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1950,
"y": 200,
"wires": []
},
{
"id": "693a84d3.a9635c",
"type": "http request",
"z": "otaManager",
"name": "GET OTA Flow",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "http://localhost:1880/flow/otaManager",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 1960,
"y": 160,
"wires": [
[
"d84f2ab.787bbd8",
"ff875536.729ab8"
]
]
},
{
"id": "ff875536.729ab8",
"type": "function",
"z": "otaManager",
"name": "Change flow JSON",
"func": "let otaData = msg.otaData.context;\nlet deviceLabel = msg.ubidotsDeviceLabel;\nlet otaKeyList = Object.keys(otaData);\nlet devOtaStatus = global.get('devOtaStatus');\n\nlet nodes = msg.payload.nodes;\n\nlet config = {\n\t'output_data_rate_101':{\n\t\t\"50\":\"6\",\n\t\t\"100\":\"7\",\n\t\t\"200\":\"8\",\n\t\t\"400\":\"9\",\n\t\t\"800\":\"10\",\n\t\t\"1600\":\"11\",\n\t\t\"3200\":\"12\",\n\t\t\"6400\":\"13\",\n\t\t\"12800\":\"14\",\n\t\t\"25600\":\"15\"\n\t},\n\t'sampling_duration_101': {\n\t\t\n\t},\n\t'sampling_interval_101': {\n\t\t\"5\":\"0\",\n\t\t\"10\":\"1\",\n\t\t\"15\":\"2\",\n\t\t\"20\":\"3\",\n\t\t\"30\":\"4\",\n\t\t\"60\":\"5\",\n\t\t\"120\":\"6\",\n\t\t\"180\":\"7\",\n\t\t\"1\":\"8\"\n\t},\n\t'mode_80':{\n\t '0': '0',\n\t '1': '1',\n\t '2': '2'\n\t \n }\n}\n\nif (msg.otaAllDevices == true){\n //Global OTA\n \n for (let i = 0; i < nodes.length; i++){\n if (nodes[i][\"type\"]==\"ncd-wireless-node\" && nodes[i][\"sensor_type\"] == '82'){\n for (let value in otaKeyList){\n var key = otaKeyList[value];\n if (key in config){\n if (key == \"sampling_duration_101\" && !isNaN(otaData[key])){\n nodes[i][key] = otaData[key].toString();\n nodes[i][key + \"_active\"] = true;\n continue;\n }\n nodes[i][key] = config[key][otaData[key].toString()];\n nodes[i][key + \"_active\"] = true;\n \n }\n }\n }\n }\n \n} else {\n // Not Global OTA\n for (let i = 0; i < nodes.length; i++){\n if (nodes[i][\"type\"]==\"ncd-wireless-node\" && nodes[i][\"addr\"] == deviceLabel){\n devOtaStatus[deviceLabel]=1;\n for (let value in otaKeyList){\n let key = otaKeyList[value];\n if (key in config){\n if (key == \"sampling_duration_101\" && !isNaN(otaData[key])){\n nodes[i][key] = otaData[key].toString();\n nodes[i][key + \"_active\"] = true;\n continue;\n }\n nodes[i][key] = config[key][otaData[key].toString()];\n nodes[i][key + \"_active\"] = true;\n \n }\n }\n }\n }\n \n}\n\n\n\n \nmsg.payload.nodes = nodes;\n\nmsg.headers = {};\nmsg.headers[\"Content-Type\"] = \"application/json\";\n//msg.headers[\"Node-RED-Deployment-Type\"] = \"nodes\";\nmsg.method = \"PUT\";\n \n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 2170,
"y": 160,
"wires": [
[
"321690ea.9e7a1",
"ff55be7f.0c1f9"
]
]
},
{
"id": "f29f0ec8.52898",
"type": "function",
"z": "otaManager",
"name": "Assign DevLabel and check for Global OTA",
"func": "let deviceLabel = Object.keys(msg.payload)[0].slice(0,-4);\nlet otaData = msg.payload[deviceLabel+'/ota'];\nmsg.otaData = otaData;\nmsg.ubidotsDeviceLabel = deviceLabel; \nmsg.otaAllDevices = false;\nlet devOtaStatus = global.get('devOtaStatus');\n\n\n//This is for Global OTA of Devices\nif ('otaAllDevices' in otaData.context){\n msg.otaAllDevices = true;\n}\n\n\nif (otaData.value == 1 || otaData.value == 2 ){\n //Ignore flow if value received is 1 or 2\n //The value is 1 when the OTA Ack dot is sent\n //The value is 2 when the OTA confirmation dot is sent\n \n //set the device's OTA status to this value\n devOtaStatus[deviceLabel] = otaData.value; \n return;\n}\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "// Code added here will be run once\n// whenever the node is deployed.\nlet devOtaStatus = global.get(\"devOtaStatus\");\nif (!devOtaStatus){\n global.set(\"devOtaStatus\", {});\n}",
"finalize": "",
"x": 1430,
"y": 240,
"wires": [
[
"cb75c97b.d508b8",
"c3cbdd86.5497"
]
]
},
{
"id": "324f6a7f.7c1ef6",
"type": "debug",
"z": "otaManager",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 2410,
"y": 200,
"wires": []
},
{
"id": "ff55be7f.0c1f9",
"type": "http request",
"z": "otaManager",
"name": "POST Flow Changes (OTA)",
"method": "use",
"ret": "obj",
"paytoqs": "ignore",
"url": "http://localhost:1880/flow/otaManager",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 2420,
"y": 160,
"wires": [
[
"324f6a7f.7c1ef6"
]
]
},
{
"id": "config.ubi.post",
"type": "http request",
"z": "otaManager",
"name": "POST to Ubidots",
"method": "use",
"ret": "obj",
"paytoqs": "ignore",
"url": "http://industrial.api.ubidots.com/api/v1.6/devices/{{ubidotsDeviceLabel}}",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 850,
"y": 240,
"wires": [
[
"ebbd0d50.93fe7"
]
]
},
{
"id": "ebbd0d50.93fe7",
"type": "debug",
"z": "otaManager",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 830,
"y": 280,
"wires": []
},
{
"id": "321690ea.9e7a1",
"type": "debug",
"z": "otaManager",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 2170,
"y": 200,
"wires": []
},
{
"id": "cb75c97b.d508b8",
"type": "function",
"z": "otaManager",
"name": "Setup OTA Ack POST",
"func": "\n\nlet ubidotsToken = global.get('UbidotsToken')\nlet payload = {};\n\npayload = {\"ota\": {\"value\":1,\"context\": {\"status\": \"OTA Data Received\"}}};\n\nmsg.payload = payload;\nmsg.headers = {};\nmsg.headers[\"Content-Type\"] = \"application/json\";\nmsg.headers[\"X-Auth-Token\"] = ubidotsToken;\nmsg.method = \"POST\";\n\nmsg.url = 'http://industrial.api.ubidots.com/api/v1.6/devices/' + msg.ubidotsDeviceLabel;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 1800,
"y": 320,
"wires": [
[
"55c6048.3813bfc"
]
]
},
{
"id": "e4901eef.e0f1d",
"type": "http request",
"z": "otaManager",
"name": "POST OTA Ack",
"method": "use",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"x": 2200,
"y": 320,
"wires": [
[
"f6378dbb.53204"
]
]
},
{
"id": "35f95c83.445a74",
"type": "comment",
"z": "otaManager",
"name": "Send OTA Ack",
"info": "This sub-flow sends a value of 1.5 to the variable OTA, meaning the OTA configuration has been received and it's waiting to be applied to the sensor",
"x": 1770,
"y": 280,
"wires": []
},
{
"id": "b384fe0.6d8f4",
"type": "comment",
"z": "otaManager",
"name": "Request OTA",
"info": "This sub-flow updates the Node Red flow \"OTA Manager\" so that the Wireless Devices have the OTA data sent from Ubidots, meaning that once the next FLY message is sent by the Device, it will perform the OTA\n\nNote: This flow updates one sensor, or all sensors depending on whether the key otaAllDevices is present on the OTA data sent by Ubidots",
"x": 1770,
"y": 120,
"wires": []
},
{
"id": "c3cbdd86.5497",
"type": "delay",
"z": "otaManager",
"name": "",
"pauseType": "delay",
"timeout": "400",
"timeoutUnits": "milliseconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 1770,
"y": 160,
"wires": [
[
"693a84d3.a9635c"
]
]
},
{
"id": "f6378dbb.53204",
"type": "debug",
"z": "otaManager",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 2370,
"y": 320,
"wires": []
},
{
"id": "config.post.delay",
"type": "delay",
"z": "otaManager",
"name": "",
"pauseType": "rate",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "4",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 650,
"y": 240,
"wires": [
[
"config.ubi.post"
]
]
},
{
"id": "55c6048.3813bfc",
"type": "delay",
"z": "otaManager",
"name": "",
"pauseType": "rate",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "4",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 2010,
"y": 320,
"wires": [
[
"e4901eef.e0f1d"
]
]
},
{
"id": "d8ebe42c.09c148",
"type": "ubidots_in",
"z": "otaManager",
"tier": "business",
"name": "Subscribe to OTA variables",
"token": "",
"device_label": "00:13:a2:00:41:ee:32:a8",
"tls_checkbox_in": false,
"custom_topic_checkbox": true,
"label_variable_1": "+/ota",
"label_variable_2": "",
"label_variable_3": "",
"label_variable_4": "",
"label_variable_5": "",
"label_variable_6": "",
"label_variable_7": "",
"label_variable_8": "",
"label_variable_9": "",
"label_variable_10": "",
"checkbox_variable_1_last_value": false,
"checkbox_variable_2_last_value": true,
"checkbox_variable_3_last_value": true,
"checkbox_variable_4_last_value": true,
"checkbox_variable_5_last_value": true,
"checkbox_variable_6_last_value": true,
"checkbox_variable_7_last_value": true,
"checkbox_variable_8_last_value": true,
"checkbox_variable_9_last_value": true,
"checkbox_variable_10_last_value": true,
"x": 1110,
"y": 240,
"wires": [
[
"f29f0ec8.52898"
]
]
},
{
"id": "initialWirelessNode84",
"type": "ncd-wireless-node",
"z": "otaManager",
"name": "Initial Wireless Type 84",
"connection": "837142ce.132b28",
"config_comm": "837142ce.132b28",
"addr": "",
"sensor_type": "84",
"auto_config": true,
"on_the_fly_enable": false,
"node_id_delay_active": "",
"node_id": 0,
"delay": 300,
"form_network": false,
"destination_active": false,
"destination": "0000FFFF",
"power_active": "",
"power": 4,
"retries_active": "",
"retries": 10,
"pan_id_active": "",
"pan_id": "7FFF",
"change_enabled": "",
"change_pr": "0",
"change_interval": "0",
"cm_calibration": "60.6",
"bp_altitude": "0",
"bp_pressure": "0",
"bp_temp_prec": "0",
"bp_press_prec": "0",
"amgt_accel": "0",
"amgt_mag": "0",
"amgt_gyro": "0",
"impact_accel": "0",
"impact_data_rate": "4",
"impact_threshold": 25,
"impact_duration": 1,
"activ_interr_x": 1,
"activ_interr_y": 2,
"activ_interr_z": 4,
"activ_interr_op": 8,
"force_calibration_co2_auto_config": "",
"force_calibration_co2": 400,
"filtering": 0,
"data_rate": 5,
"time_series": 0,
"reading_type": 1,
"mode_80_active": true,
"mode_80": "2",
"measurement_mode_80_active": "",
"measurement_mode_80": 0,
"on_request_timeout_80_active": "",
"on_request_timeout_80": "1",
"deadband_80_active": "",
"deadband_80": 0,
"filter_80_active": "",
"filter_80": 0,
"output_data_rate_p1_81_active": "",
"output_data_rate_p1_81": 0,
"output_data_rate_p2_81_active": "",
"output_data_rate_p2_81": 0,
"sampling_duration_p1_81_active": "",
"sampling_duration_p1_81": 0,
"sampling_duration_p2_81_active": "",
"sampling_duration_p2_81": 0,
"led_alert_mode_84_active": "",
"led_alert_mode_84": 0,
"led_accelerometer_threshold_84_active": "",
"led_accelerometer_threshold_84": "",
"led_velocity_threshold_84_active": "",
"led_velocity_threshold_84": "",
"acceleration_interrupt_threshold_84_active": "",
"acceleration_interrupt_threshold_84": "",
"set_rtc_101": 0,
"current_calibration_82": "",
"current_calibration_82_active": false,
"current_calibration_c1_80": "178",
"current_calibration_c1_80_active": false,
"current_calibration_c2_80": "178",
"current_calibration_c2_80_active": false,
"current_calibration_c3_80": "178",
"current_calibration_c3_80_active": false,
"output_data_rate_101_active": true,
"output_data_rate_101": "10",
"output_data_rate_101_m2_active": false,
"sampling_duration_101_active": true,
"sampling_duration_101": 1,
"sampling_interval_101_active": true,
"sampling_interval_101": "4",
"full_scale_range_101_active": "",
"full_scale_range_101": 1,
"full_scale_range_101_m2_active": false,
"x_axis_101": false,
"y_axis_101": false,
"z_axis_101": false,
"low_pass_filter_80_active": "",
"low_pass_filter_80": 0,
"high_pass_filter_80_active": "",
"high_pass_filter_80": 0,
"low_pass_filter_81_p2_active": "",
"low_pass_filter_81_p2": 0,
"high_pass_filter_81_p2_active": "",
"high_pass_filter_81_p2": 0,
"roll_angle_threshold_47": "0",
"roll_angle_threshold_47_active": false,
"pitch_angle_threshold_47": "0",
"pitch_angle_threshold_47_active": false,
"x": 140,
"y": 100,
"wires": [
[
"8c0b203a.057e2"
]
]
},
{
"id": "8c0b203a.057e2",
"type": "function",
"z": "otaManager",
"name": "Config Confirmation",
"func": "let message = msg.payload;\nlet topic = msg.topic;\nlet deviceLabel = \"MAC\";\nlet OTAResults = msg.payload;\nlet devOtaStatus = global.get('devOtaStatus');\nlet ubidotsToken = global.get('UbidotsToken')\n\nif (deviceLabel == \"MAC\") {\n return;\n}\n\n\nif (topic == 'Config Results' && devOtaStatus[deviceLabel] != 2){\n msg.payload = {\"ota\":{\"value\": 2, \"context\": {\"status\": \"OTA finished: \" + JSON.stringify(OTAResults)}}}\n \n msg.ubidotsDeviceLabel = deviceLabel;\n msg.headers = {};\n msg.headers[\"Content-Type\"] = \"application/json\";\n msg.headers[\"X-Auth-Token\"] = ubidotsToken;\n msg.method = \"POST\";\n \n \n return msg\n \n}\n\nreturn;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"x": 380,
"y": 100,
"wires": [
[
"config.post.delay"
]
]
},
{
"id": "initialWirelessNode82",
"type": "ncd-wireless-node",
"z": "otaManager",
"name": "Initial Wireless Type 82",
"connection": "837142ce.132b28",
"config_comm": "837142ce.132b28",
"addr": "",
"sensor_type": "82",
"auto_config": true,
"on_the_fly_enable": false,
"node_id_delay_active": "",
"node_id": 0,
"delay": 300,
"form_network": false,
"destination_active": false,
"destination": "0000FFFF",
"power_active": "",
"power": 4,
"retries_active": "",
"retries": 10,
"pan_id_active": "",
"pan_id": "7FFF",
"change_enabled": "",
"change_pr": "0",
"change_interval": "0",
"cm_calibration": "60.6",
"bp_altitude": "0",
"bp_pressure": "0",
"bp_temp_prec": "0",
"bp_press_prec": "0",
"amgt_accel": "0",
"amgt_mag": "0",
"amgt_gyro": "0",
"impact_accel": "0",
"impact_data_rate": "4",
"impact_threshold": 25,
"impact_duration": 1,
"activ_interr_x": 1,
"activ_interr_y": 2,
"activ_interr_z": 4,
"activ_interr_op": 8,
"force_calibration_co2_auto_config": "",
"force_calibration_co2": 400,
"filtering": 0,
"data_rate": 5,
"time_series": 0,
"reading_type": 1,
"mode_80_active": true,
"mode_80": "1",
"measurement_mode_80_active": "",
"measurement_mode_80": 0,
"on_request_timeout_80_active": "",
"on_request_timeout_80": "1",
"deadband_80_active": "",
"deadband_80": 0,
"filter_80_active": "",
"filter_80": 0,
"output_data_rate_p1_81_active": "",
"output_data_rate_p1_81": 0,
"output_data_rate_p2_81_active": "",
"output_data_rate_p2_81": 0,
"sampling_duration_p1_81_active": "",
"sampling_duration_p1_81": 0,
"sampling_duration_p2_81_active": "",
"sampling_duration_p2_81": 0,
"led_alert_mode_84_active": "",
"led_alert_mode_84": 0,
"led_accelerometer_threshold_84_active": "",
"led_accelerometer_threshold_84": "",
"led_velocity_threshold_84_active": "",
"led_velocity_threshold_84": "",
"acceleration_interrupt_threshold_84_active": "",
"acceleration_interrupt_threshold_84": "",
"set_rtc_101": 0,
"current_calibration_82": "",
"current_calibration_82_active": false,
"current_calibration_c1_80": "178",
"current_calibration_c1_80_active": false,
"current_calibration_c2_80": "178",
"current_calibration_c2_80_active": false,
"current_calibration_c3_80": "178",
"current_calibration_c3_80_active": false,
"output_data_rate_101_active": true,
"output_data_rate_101": "10",
"output_data_rate_101_m2_active": false,
"sampling_duration_101_active": true,
"sampling_duration_101": "20",
"sampling_interval_101_active": true,
"sampling_interval_101": "0",
"full_scale_range_101_active": "",
"full_scale_range_101": 1,
"full_scale_range_101_m2_active": false,
"x_axis_101": "",
"y_axis_101": "",
"z_axis_101": "",
"low_pass_filter_80_active": "",
"low_pass_filter_80": 0,
"high_pass_filter_80_active": "",
"high_pass_filter_80": 0,
"low_pass_filter_81_p2_active": "",
"low_pass_filter_81_p2": 0,
"high_pass_filter_81_p2_active": "",
"high_pass_filter_81_p2": 0,
"roll_angle_threshold_47": "0",
"roll_angle_threshold_47_active": false,
"pitch_angle_threshold_47": "0",
"pitch_angle_threshold_47_active": false,
"x": 140,
"y": 40,
"wires": [
[
"config.confirmation"
]
]
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment