How to use Node-Red plugin node-bacnet-contrib-extended to read Bacnet Devices

5

The node-bacnet-contrib-extended is built on top of node-bacnet javascript library, in contrast to other bacnet plugins available in Node-red it provides additional functionality such as bacnet COV node to utilize bacnet Change of value (COV) feature.

Github link -> https://github.com/asad-boutique/node-bacnet-contrib-extended

Node-Red Pallete -> https://flows.nodered.org/node/node-bacnet-contrib-extended

This Plugin provides the following nodes.

discover – devices

The discover-devices node would discover all the bacnet devices on a network and would display there bacnet ids and address.

read-single-device

The read-sigle-device node would take deviceId and address as an argument and would read the whole contents of that device. 

example parameters:

msg.deviceId = 9000; 
msg.address = “192.168.20.242”; 
}

read-all-devices

The read-all-devices node would read the complete data of all the available bacnet devices on the network.


read-single-point

The read-single-point node would read the data of the single node or object, it would take inputType, bacnetId and address as an input arguments via a function node. 

example parameters: 

msg.inputType = 3; 

msg.bacnetId = 8; 

msg.address = “192.168.20.242”; 

}

read-objects-list-within-device

The read-objects-list-within-device node would take deviceId and address as an arguments and read all the object/points within that device. 

example parameters: 

msg.deviceId = 9000; 

msg.address = “192.168.20.242”; 

}

read-object-properties

The read-object-properties node would take requestArray as an argument including inputType, bacnetID and read all the object properties defined within requestArray. 

example parameters: 

const requestArray = [ { objectId: { type: msg.inputType, instance: msg.bacnetID }, properties: bacnetProperties } ]; 

msg.requestArray = requestArray 

}

change-of-value

The change-of-value node would take address, inputType, bacnetId and COVtimeout as input and would create and renew subcriptions for the Bacnet change of value, for example whenever the value of binary input would get changed the change-of-value node would trigger an output.


Data Transformation:

The data transformation script can be used in contrast to read-object-properties to show property list in a human readable form.

Example Usage Flow for all the nodes:

[{"id":"e59ccc493ab8713f","type":"tab","label":"node-bacnet-contrib-extended example flow","disabled":false,"info":"","env":[]},{"id":"74bf69659e1974a1","type":"debug","z":"e59ccc493ab8713f","name":"debug 20","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":980,"y":180,"wires":[]},{"id":"fa17fb916284cf19","type":"inject","z":"e59ccc493ab8713f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":260,"y":180,"wires":[["08257e5542d39440"]]},{"id":"411aed243f057296","type":"discover-devices","z":"e59ccc493ab8713f","name":"","x":730,"y":180,"wires":[["74bf69659e1974a1"]]},{"id":"e942e51ca4b4090f","type":"read-all-devices","z":"e59ccc493ab8713f","name":"","x":720,"y":360,"wires":[["3eecc0c9baf5b834"]]},{"id":"c2c992dcda54245d","type":"inject","z":"e59ccc493ab8713f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":260,"y":360,"wires":[["62bd1186e7eaad41"]]},{"id":"62bd1186e7eaad41","type":"function","z":"e59ccc493ab8713f","name":"Inject Parameters","func":"// msg.communicationPort = 47808;\n// msg.interface = '0.0.0.0';\n// msg.broadcastAddress = '255.255.255.255';\n// msg.apduTimeout = 7000;\n// msg.reuseAddr = true;\n// msg.getAllPropertiesManually = \"true\";\n\n//msg.transportClosedDuration = 90000;\n\n\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":360,"wires":[["e942e51ca4b4090f"]]},{"id":"3eecc0c9baf5b834","type":"debug","z":"e59ccc493ab8713f","name":"debug 21","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":980,"y":360,"wires":[]},{"id":"4494f2fbdd6bcf29","type":"inject","z":"e59ccc493ab8713f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":260,"y":260,"wires":[["4fb6bf9552d1c542"]]},{"id":"4fb6bf9552d1c542","type":"function","z":"e59ccc493ab8713f","name":"Inject Parameters","func":"// var randNum = Math.floor(Math.random() * 5100);\n// msg.communicationPort = 47809 + randNum;\n// msg.interface = '0.0.0.0';\n// msg.broadcastAddress = '255.255.255.255';\n// msg.apduTimeout = 3000;\n// msg.reuseAddr = true;\n// msg.transportClosedDuration = 90000;\n//msg.getAllPropertiesManually = \"true\";\n\nmsg.deviceId = 2051;\nmsg.address = \"192.168.10.51\";\n\nmsg.apduTimeout = 20000;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":260,"wires":[["ede5e2d97a9ff630"]]},{"id":"177ff63bf3091b0f","type":"debug","z":"e59ccc493ab8713f","name":"debug 22","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":980,"y":260,"wires":[]},{"id":"ede5e2d97a9ff630","type":"read-single-device","z":"e59ccc493ab8713f","name":"","x":730,"y":260,"wires":[["177ff63bf3091b0f"]]},{"id":"3ed9cb3c68c88c50","type":"read-single-point","z":"e59ccc493ab8713f","name":"","x":730,"y":460,"wires":[["56dcc0c93d7edcc8"]]},{"id":"dfdf9cfae6db316a","type":"inject","z":"e59ccc493ab8713f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":260,"y":460,"wires":[["8b01e8719e4d6d6b"]]},{"id":"8b01e8719e4d6d6b","type":"function","z":"e59ccc493ab8713f","name":"Inject Parameters","func":"// msg.communicationPort = 47811;\n// msg.interface = '0.0.0.0';\n// msg.broadcastAddress = '255.255.255.255';\n// msg.apduTimeout = 4000;\n// msg.reuseAddr = true;\n\n \n// msg.transportClosedDuration = 9000;\n\n\n// msg.inputType = 2;\n// msg.bacnetId = 103;\n// msg.address = \"192.168.10.52\";\n\nmsg.inputType = 2;\nmsg.bacnetId = 26;\nmsg.address = \"192.168.10.50\";\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":460,"wires":[["3ed9cb3c68c88c50"]]},{"id":"56dcc0c93d7edcc8","type":"debug","z":"e59ccc493ab8713f","name":"debug 23","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":980,"y":460,"wires":[]},{"id":"08257e5542d39440","type":"function","z":"e59ccc493ab8713f","name":"Inject Parameters","func":"// msg.communicationPort = 47808;\n// msg.interface = '0.0.0.0';\n// msg.broadcastAddress = '255.255.255.255';\n//msg.apduTimeout = 7000;\nmsg.reuseAddr = true;\nmsg.transportClosedDuration = 8000;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":490,"y":180,"wires":[["411aed243f057296"]]},{"id":"d4e184b3ed27c65c","type":"read-objects-list-within-device","z":"e59ccc493ab8713f","name":"","x":830,"y":580,"wires":[["e2c2a2fd6e536531"]]},{"id":"5515866ca25b964a","type":"read-object-properties","z":"e59ccc493ab8713f","name":"","x":800,"y":660,"wires":[["bf874e495e86a417"]]},{"id":"cfa436b22edec71a","type":"change-of-value","z":"e59ccc493ab8713f","d":true,"name":"","address":"192.168.10.54","inputType":"5","bacnetId":"22","COVtimeout":"120000","x":760,"y":760,"wires":[["1aa268f1a0438dce"]]},{"id":"42ba49ea2bb49724","type":"inject","z":"e59ccc493ab8713f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":240,"y":580,"wires":[["d881f01805f8f779"]]},{"id":"d881f01805f8f779","type":"function","z":"e59ccc493ab8713f","name":"Inject Device Id and Address","func":"msg.deviceId = 2054;\nmsg.address = \"192.168.10.54\";\n\n//msg.communicationPort = 47808;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":580,"wires":[["d4e184b3ed27c65c"]]},{"id":"e2c2a2fd6e536531","type":"debug","z":"e59ccc493ab8713f","name":"debug 24","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1100,"y":580,"wires":[]},{"id":"f53d617dd251dd64","type":"function","z":"e59ccc493ab8713f","name":"Inject Id + Type + Properties","func":"msg.deviceId = 2054;\nmsg.address = \"192.168.10.54\";\nmsg.inputType = 5;\nmsg.bacnetID = 22;\n\nconst bacnetProperties = [\n  { id: 77 }, // OBJECT_NAME\n // { id: 79 }, // OBJECT_TYPE OR INPUT TYPE\n  { id: 85 }, // PRESENT_VALUE\n];\n\n\nconst requestArray = [\n  { objectId: { type: msg.inputType, instance: msg.bacnetID }, properties: bacnetProperties }\n];\n\nmsg.requestArray = requestArray        \n        \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":660,"wires":[["5515866ca25b964a"]]},{"id":"d8d1549a7fbecea0","type":"inject","z":"e59ccc493ab8713f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":220,"y":660,"wires":[["f53d617dd251dd64"]]},{"id":"bf874e495e86a417","type":"debug","z":"e59ccc493ab8713f","name":"debug 25","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1040,"y":660,"wires":[]},{"id":"1aa268f1a0438dce","type":"debug","z":"e59ccc493ab8713f","name":"debug 26","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1000,"y":760,"wires":[]}]

Example usage flow with a coupling of read-object-properties with Transformation Script:-

[{"id":"19b30a6ef4e257f2","type":"tab","label":"coupling of read-object-properties with Transformation Script","disabled":false,"info":"","env":[]},{"id":"1b15b9eb8d4e859f","type":"read-object-properties","z":"19b30a6ef4e257f2","name":"","x":740,"y":320,"wires":[["63de82d1703dcede","98756e5bb72a3685"]]},{"id":"f2ab79c87df39de3","type":"function","z":"19b30a6ef4e257f2","name":"Inject Id + Type + Properties","func":"msg.deviceId = 2054;\nmsg.address = \"192.168.10.54\";\nmsg.inputType = 5;\nmsg.bacnetID = 22;\n\nconst bacnetProperties = [\n  { id: 77 }, // OBJECT_NAME\n // { id: 79 }, // OBJECT_TYPE OR INPUT TYPE\n  { id: 85 }, // PRESENT_VALUE\n];\n\n\nconst requestArray = [\n  { objectId: { type: msg.inputType, instance: msg.bacnetID }, properties: bacnetProperties }\n];\n\nmsg.requestArray = requestArray        \n        \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":320,"wires":[["1b15b9eb8d4e859f"]]},{"id":"a8a816e74c2d2519","type":"inject","z":"19b30a6ef4e257f2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":320,"wires":[["f2ab79c87df39de3"]]},{"id":"63de82d1703dcede","type":"debug","z":"19b30a6ef4e257f2","name":"debug 27","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":980,"y":320,"wires":[]},{"id":"98756e5bb72a3685","type":"function","z":"19b30a6ef4e257f2","name":"Data Transformation","func":"var object = msg.payload;\n\nvar myArray = {};\n\nmyArray[\"BacnetID\"] = msg.bacnetID;\nmyArray[\"InputType\"] = msg.inputType;\n\n\nfor(var j = 0; j < object.values[0].values.length; j++){\n    \n    \n    \n    var k1 = object.values[0].values[j].id.toString();\n    \n    //str = str + k1 + \" ----- \";\n    \n    var v1 = object.values[0].values[j].value[0].value;\n    \n    var k1str = ConvertPropertyIdWithString(k1);\n    \n    myArray[k1str] = v1;\n    \n}\n\n\n//msg.payload = str;\n\nmsg.payload = myArray;\n\nreturn msg;\n\n\n\nfunction ConvertPropertyIdWithString(id){\n    \n    var convertedValue = \" PPPP \";\n    \n    if(id == 0){\n        convertedValue = \"ACKED_TRANSITIONS\";\n    }\n    \n    else if(id == 4){\n        convertedValue = \"ACTIVE_TEXT\";\n    }\n    \n    else if(id == 6){\n        convertedValue = \"ALARM_VALUE\";\n    }\n    \n    else if(id == 15){\n        convertedValue = \"CHANGE_OF_STATE_COUNT\";\n    }\n    \n    else if(id == 16){\n        convertedValue = \"CHANGE_OF _STATE_TIME\";\n    }\n    \n    else if(id == 17){\n        convertedValue = \"NOTIFICATION_CLASS\";\n    }\n    \n    else if(id == 22){\n        convertedValue = \"COV_INCREMENT\";\n    }\n\n    else if(id == 25){\n        convertedValue = \"DEADBAND\";\n    }\n\n    else if(id == 28){\n        convertedValue = \"DESCRIPTION\";\n    }\n    \n    else if(id == 31){\n        convertedValue = \"DEVICE_TYPE\";\n    }\n    \n    else if(id == 33){\n        convertedValue = \"ELAPSED_ACTIVE_TIME\";\n    }\n    \n    else if(id == 35){\n        convertedValue = \"EVENT_ENABLE\";\n    }\n    \n    else if(id == 36){\n        convertedValue = \"EVENT_STATE\";\n    }\n\n    else if(id == 45){\n        convertedValue = \"HIGH_LIMIT\";\n    }\n    \n    else if(id == 46){\n        convertedValue = \"INACTIVE_TEXT\";\n    }\n\n    else if(id == 52){\n        convertedValue = \"LIMIT_ENABLE\";\n    }\n\n    else if(id == 59){\n        convertedValue = \"LOW_LIMIT\";\n    }\n\n    else if(id == 65){\n        convertedValue = \"MAX_PRES_VALUE\";\n    }\n\n    else if(id == 69){\n        convertedValue = \"MIN_PRES_VALUE\";\n    }\n    \n    else if(id == 72){\n        convertedValue = \"NOTIFY_TYPE\";\n    }\n    \n    else if(id == 75){\n        convertedValue = \"OBJECT_IDENTIFIER\";\n    }\n    \n    else if(id == 77){\n        convertedValue = \"OBJECT_NAME\";\n    }\n    \n    else if(id == 79){\n        convertedValue = \"OBJECT_TYPE\";\n    }\n    \n    else if(id == 81){\n        convertedValue = \"OUT_OF_SERVICE\";\n    }\n    \n    else if(id == 84){\n        convertedValue = \"POLARITY\";\n    }\n    \n    else if(id == 85){\n        convertedValue = \"PRESENT_VALUE\";\n    }\n    \n    else if(id == 103){\n        convertedValue = \"RELIABILITY\";\n    }\n\n    else if(id == 106){\n        convertedValue = \"RESOLUTION\";\n    }\n    \n    else if(id == 111){\n        convertedValue = \"STATUS_FLAGS\";\n    }\n    \n    else if(id == 113){\n        convertedValue = \"TIME_DELAY\";\n    }\n    \n    else if(id == 114){\n        convertedValue = \"TIME_OF_ACTIVE_TIME_RESET\";\n    }\n    \n    else if(id == 115){\n        convertedValue = \"TIME_OF_STATE_COUNT_RESET\";\n    }\n\n    else if(id == 117){\n        convertedValue = \"UNITS\";\n    }\n\n    else if(id == 118){\n        convertedValue = \"UPDATE_INTERVAL\";\n    }\n    \n    else if(id == 130){\n        convertedValue = \"EVENT_TIME_STAMPS\";\n    }\n    \n    else if(id == 351){\n        convertedValue = \"EVENT_MESSAGE_TEXTS\";\n    }\n    \n    else if(id == 352){\n        convertedValue = \"EVENT_MESSAGE_TEXTS_CONFIGS\";\n    }\n    \n    else if(id == 353){\n        convertedValue = \"EVENT_DETECTION_ENABLE\";\n    }\n    \n    else if(id == 354){\n        convertedValue = \"EVENT_ALGORITHM_INHIBIT\";\n    }\n    \n    else if(id == 355){\n        convertedValue = \"EVENT_ALGORITHM_INHIBIT_REF\";\n    }\n    \n    else if(id == 356){\n        convertedValue = \"TIME_DELAY_NORMAL\";\n    }\n    \n    return convertedValue;\n    \n    \n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":900,"y":420,"wires":[["3b068278ea802094"]]},{"id":"3b068278ea802094","type":"debug","z":"19b30a6ef4e257f2","name":"debug 28","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1100,"y":420,"wires":[]}]
5/5 - (1 vote)

royal52
royal52

I’m a DevSecOps Software engineer by profession and a SEO hobbyist. I’m passionate about everything Software, including game development.

We will be happy to hear your thoughts

Leave a reply