Node-RED as an Edge Device to connect ThingWrox

💻 Product Information : ThingWrox ThingWorx Industrial IoT

ThingWrox Properties

  • Thing:Building12
  • Building12:# Temperature an alert condition on <= 65
  • Building12:# Humidity
  • Building12:Location Building Number

Using REST API to modify ThingWrox Properties

URL Pattern

The following URL pattern is used when communicating with ThingWorx:

<http/https:><host:port>/Thingworx/<entity collection>/<entity>/<characteristic collection>/<characteristic>?<query parameters>

HTTP Header

newMsg.headers['Accept'] = "application/json";
newMsg.headers['content-type'] = "application/json";
newMsg.headers['content-length'] = newMsg.payload.length;
newMsg.headers["appKey"] = '*********-4958-45db-9789-************';

HTTP URL

http://<host>:<port>/Thingworx/Things/Building12/Properties/*

In Action

Flow

If the connection is down, a single queue will store all events upto totalAllowedQueueSize(20). Once the connection is re-established, the oldest event will be sent first.

[{"id":"4911b967.24ef58","type":"inject","z":"d70af7bd.4d2698","name":"Generate Temp, Humidity 5s","topic":"","payload":"","payloadType":"date","repeat":"5","crontab":"","once":false,"onceDelay":0.1,"x":175.10000610351562,"y":94,"wires":[["d8d8507f.5db5"]]},{"id":"214817f8.7eb3e8","type":"http request","z":"d70af7bd.4d2698","name":"REST PUT -> ThingWrox ","method":"PUT","ret":"txt","url":"http://192.168.1.10:8080/Thingworx/Things/Building12/Properties/*","tls":"","x":749.10009765625,"y":266,"wires":[["5994701.9200d9","ff815965.15afd8"]]},{"id":"2ed759d1.f63c76","type":"debug","z":"d70af7bd.4d2698","name":"HTTP PUT Messasge ","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":934.1000366210938,"y":138,"wires":[]},{"id":"5994701.9200d9","type":"function","z":"d70af7bd.4d2698","name":"Detect HTTP Status","func":"var newMsg = {};\n\nif ( msg.statusCode !== 200 ) {\n    // 'ECONNREFUSED') \n    // 405 : method not allowed\n    console.log(\"Failed !!! statusCode = \", msg.statusCode);\n    newMsg.payload = { op: \"connection\", connected : 0 , statusCode :  msg.statusCode };\n} else \n    newMsg.payload = { op: \"connection\", connected : 1 , statusCode :  msg.statusCode };\nreturn newMsg;","outputs":1,"noerr":0,"x":483,"y":330,"wires":[["cdc0336b.69b3e"]]},{"id":"c76fa51a.555828","type":"function","z":"d70af7bd.4d2698","name":"Build HTTP Header w/ appKey","func":"\n// payload\nvar newMsg = {};\nnewMsg.payload = msg.payload;\n\nnewMsg.headers = {};\nnewMsg.headers['Accept'] = \"application/json\";\nnewMsg.headers['content-type'] = \"application/json\";\nnewMsg.headers['content-length'] = newMsg.payload.length;\nnewMsg.headers[\"appKey\"] = '*********-4958-45db-9789-**********';\n\nreturn newMsg;\n","outputs":1,"noerr":0,"x":678,"y":188,"wires":[["214817f8.7eb3e8","2ed759d1.f63c76"]]},{"id":"cdc0336b.69b3e","type":"function","z":"d70af7bd.4d2698","name":"Event Queue (max 20)","func":"context.queue = context.queue || [];\nvar http_connected = context.connected || 0 ;\n\nvar totalAllowedQueueSize = 20;\nvar blocked = false;\nvar newMsg = null;\n\nif (context.queue.length >= totalAllowedQueueSize) blocked = true;\n\nswitch( msg.payload.op ) {\ncase \"connection\" :\n    context.connected = msg.payload.connected;\n    http_connected = msg.payload.connected;\n    break;\ncase \"reset\" :\n    context.queue = [];\n    blocked = false;\n    context.connected = 1;\n    break;\ncase \"trigger\" :\n    // dequeue\n    if ( context.queue.length !== 0 && http_connected ) newMsg = { payload : context.queue.shift() } ;\n    else newMsg = { payload : { op : \"trigger\" } };\n    break;\ndefault :\n    // enqueue\n    if ( !blocked ) context.queue.push(msg.payload);\n    break;\n}\n\nif (http_connected) {\n    if( !blocked )\n        node.status({fill:\"green\",shape:\"dot\",text: '('+context.queue.length+') stored, connected' });\n    else \n        node.status({fill:\"red\",shape:\"ring\",text: 'blocked,('+context.queue.length+') stored, connected' });\n} else {\n    if( !blocked ) \n        node.status({fill:\"red\",shape:\"dot\",text: '('+context.queue.length+') stored, disconnected' });\n    else\n        node.status({fill:\"red\",shape:\"ring\",text: 'blocked,('+context.queue.length+') stored, disconnected' });\n}\n\nreturn newMsg;\n","outputs":1,"noerr":0,"x":416,"y":190,"wires":[["c76fa51a.555828"]]},{"id":"4745042.308b8fc","type":"inject","z":"d70af7bd.4d2698","name":"Trigger Event every 3s","topic":"","payload":" { \"op\" : \"trigger\" }","payloadType":"json","repeat":"3","crontab":"","once":false,"onceDelay":0.1,"x":157,"y":243,"wires":[["cdc0336b.69b3e"]]},{"id":"d8d8507f.5db5","type":"function","z":"d70af7bd.4d2698","name":"Read Temp, Humidity Values","func":"var tempF = Math.floor(Math.random() * 40 + 60);\nvar tempC = Math.floor( (tempF-32)/1.8 ) ;\nvar humidity = Math.floor(Math.random() * 80 + 20);\nmsg.payload = {\n    op : \"store\",\n    timestamp : Math.floor(Date.now() / 1000),\n    Temperature: tempF,\n    Humidity: humidity,\n    Location : \"B12\"\n    };\nreturn msg;\n","outputs":1,"noerr":0,"x":452,"y":94,"wires":[["cdc0336b.69b3e"]]},{"id":"9683d41c.1a5358","type":"inject","z":"d70af7bd.4d2698","name":"Reset","topic":"","payload":"{\"op\" : \"reset\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":98,"y":161,"wires":[["cdc0336b.69b3e"]]},{"id":"bdac5bea.6d4128","type":"comment","z":"d70af7bd.4d2698","name":"Events","info":"","x":87,"y":49,"wires":[]},{"id":"ff815965.15afd8","type":"debug","z":"d70af7bd.4d2698","name":"HTTP Response Message","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":930,"y":339,"wires":[]},{"id":"4ca174e.870b18c","type":"comment","z":"d70af7bd.4d2698","name":"Periodic Reporting","info":"","x":122,"y":204,"wires":[]},{"id":"f581d59d.b605f8","type":"comment","z":"d70af7bd.4d2698","name":"Simpel Queue (or Time-series dataase)","info":"","x":379,"y":146,"wires":[]}]

Alert

When an alert condition ( #Temperature <= 65 ) is met, ThingWorx fires off an alert. Alerts are written to the alert history file and can be viewed through the Alert Summary and Alert History Mashups.

Alert Subscription

Create a Subscription to the Alert so that you are automatically notified when an alert is triggered.

Send a message from ThingWrox to Node-RED (Edge Device) using HTTP REST API when an alert is triggered.

var headers = { 
    "content-type": "application/json",
    "Accept":"*/*"            
};

var content = "{ \"op\" : \"inc_temperature\" }";

var params = { 
    headers: headers,
    url: "http://192.168.1.8:1880/alerts" /* STRING */,
    content: content /* STRING */,
};
var result = Resources["ContentLoaderFunctions"].PostJSON(params);

Node-RED executes an appropriate action based on the payload received by http in node. In this example, simply display msg.payload.

Related Posts