Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info
iconfalse
Excerpt

ThingWorx is a complete development solution for enterprise IoT: it can receive, store, display and analyze your data. This guide shows you how to integrate your SmartMesh IP network into ThingWorx

Table of Contents

Tip
iconfalse

This post recipe focuses on the integration of SmartMesh IP into ThingWorx. If you don't know what ThingWorx is, we recommend the excellent guides from the ThingWorx developer portal.

The goal of this blogpost recipe is to get you started integrating your SmartMesh IP network into ThingWorx. After following these steps, you will be able to explore all the possibilities ThingWorx offers, including analytics.

Overview

The setup you will build contains the following:

  • DC9000 SmartMesh IP starter kit, with all 5 motes publishing temperature data to the SmartMesh IP manager every 30 s
  • the SmartMesh IP manager connected to a computer over USB
  • the JsonServer application running on the computer, and connected to the SmartMesh IP manager's serial port
  • a Node-RED instance running on the computer, publishing temperature data to your ThingWorx instance
Note

To replicate this blog postrecipe, you need a  DC9000 SmartMesh IP starter kit, and a ThingWorx account (which is free for a 30-day trial).

Tutorial

Start your ThingWorx instance

Tip
titleWhat just happened?

At this point, there is an instance of ThingWorx running just for you in the cloud. We are only interested in the foundation server for this postrecipe.

From your ThingWorx dashboard, you can "launch" it, i.e. open its web interface.

Note that your instance has its own IP address, in my case 52.215.35.70. Take a note of that, as you will be issuing RESTful commands to it.

Configure your ThingWorx instance

Create an application key called "motekey" which you associate with user name "Administrator".

Once you save, the actual key is in field "keyId". In my case a807cb5d-6425-4786-95df-e09e2171a85d.

Tip
titleWhat just happened?

Your Thingworx instance is now configured so you can issue RESTful commands, and authenticate as Administrator using an application key.

Yes, that's it! Pretty simple, right?

Prepare your SmartMesh IP network

  • Switch on your SmartMesh IP manager and motes

    Note

    We assume all SmartMesh IP motes are running the default firmware in master mode, and publish temperature data every 30 seconds.

  • Start the SmartMesh IP JsonServer application and Node-RED, and connect the JsonServer application to your SmartMesh IP manager's serial API port.

    Tip

    See the SmartMesh IP and Node-RED, revisited recipe to see how to do that.

Tip
titleWhat just happened?

Your SmartMesh IP network is running, and the JsonServer application is forwarding all temperature measurements to Node-RED.

All you have to do now is have Node-RED publish those sensors' measurements to your ThingWorx instance!

Publish Temperature to ThingWorx

Almost there, this is the last step!

All we need to do is create a Node-RED flow which:

  • listens for an HTTP POST request to URL /oap to receive the OAP notifications form the JsonServer
  • filters temperature notifications, and extracts:
    • the MAC address of the mote publishing
    • the temperature
  • try to publish the temperature value, as if a Thing already exists on ThingWorx for that mote
  • if we receive HTTP status code 404, it indicates that mote hasn't been registered yet on Thingworx; in this case, do the following:
    • issue an HTTP request to ThingWorx to create a Thing corresponding to this MAC address
    • issue an HTTP request to ThingWorx to enable that Thing
    • issue an HTTP request to ThingWorx to restart that Thing
    • issue an HTTP request to ThingWorx to add property "temperature" to that Thing
    • try to publish temperature again

This is what the resulting Node-RED flow looks like:


Info
titleJSON version of the flow
Code Block
[{"id":"c69cd86b.477718","type":"http in","z":"a1220086.57409","name":"oap from motes","url":"/oap","method":"post","swaggerDoc":"","x":92,"y":80.1819076538086,"wires":[["f7bf052f.c64c68","d74a72ba.3257b"]]},{"id":"f7bf052f.c64c68","type":"http response","z":"a1220086.57409","name":"http response","x":250.2726593017578,"y":38.454559326171875,"wires":[]},{"id":"d74a72ba.3257b","type":"function","z":"a1220086.57409","name":"extract mac and temperature","func":"// ThingWorx global variables\nflow.set(\"tw_host\", \"52.215.35.70\")\nflow.set(\"tw_appKey\", \"a807cb5d-6425-4786-95df-e09e2171a85d\")\n\nif (msg.payload.name==\"oap\" && msg.payload.fields.channel_str==\"temperature\") {\n    // packet contents\n    flow.set(\"mac\",        msg.payload.mac)\n    flow.set(\"temperature\",msg.payload.fields.samples[0]/100.0)\n    return msg;\n}","outputs":1,"noerr":0,"x":318.2725067138672,"y":92.45457458496094,"wires":[["caf1178.eedaae8"]]},{"id":"32b0750b.37da4a","type":"function","z":"a1220086.57409","name":"create mote","func":"var tw_url = \"http://\"+flow.get(\"tw_host\")+\"/Thingworx/\"\ntw_url    += \"Resources/EntityServices/Services/CreateThing\"\n\nreturn {\n    url:     tw_url,\n    method:  \"POST\",\n    headers: {\n        \"content-type\":     \"application/json\",\n        \"appKey\":           flow.get(\"tw_appKey\")\n    },\n    payload: {  \n        \"name\":             flow.get(\"mac\"),\n        \"description\":      \"SmartMesh IP mote\",\n        \"thingTemplateName\":\"GenericThing\"\n    }\n};","outputs":1,"noerr":0,"x":173.5908660888672,"y":276.0000534057617,"wires":[["309507d7.332918"]]},{"id":"e1478436.a76ba8","type":"function","z":"a1220086.57409","name":"enable mote","func":"var tw_url = \"http://\"+flow.get(\"tw_host\")+\"/Thingworx/\"\ntw_url    += \"Things/\"+flow.get(\"mac\")+\"/Services/EnableThing\"\n\nreturn {\n    url:     tw_url,\n    method:  \"POST\",\n    headers: {\n        \"content-type\":     \"application/json\",\n        \"appKey\":           flow.get(\"tw_appKey\")\n    },\n};","outputs":1,"noerr":0,"x":165.272705078125,"y":313.2727241516113,"wires":[["8c576462.257d78"]]},{"id":"b785f623.f63b68","type":"switch","z":"a1220086.57409","name":"statusCode","property":"statusCode","propertyType":"msg","rules":[{"t":"eq","v":"404","vt":"num"},{"t":"else"}],"checkall":"true","outputs":2,"x":526.4090423583984,"y":183.09095001220703,"wires":[["32b0750b.37da4a"],[]]},{"id":"309507d7.332918","type":"http request","z":"a1220086.57409","name":"","method":"use","ret":"txt","url":"","tls":"","x":335.2726593017578,"y":276.27278900146484,"wires":[["e1478436.a76ba8"]]},{"id":"8c576462.257d78","type":"http request","z":"a1220086.57409","name":"","method":"use","ret":"txt","url":"","tls":"","x":333.2726593017578,"y":315.18184661865234,"wires":[["a760436b.57ffa"]]},{"id":"a760436b.57ffa","type":"function","z":"a1220086.57409","name":"restart thing","func":"var tw_url = \"http://\"+flow.get(\"tw_host\")+\"/Thingworx/\"\ntw_url    += \"Things/\"+flow.get(\"mac\")+\"/Services/RestartThing\"\n\nreturn {\n    url:     tw_url,\n    method:  \"POST\",\n    headers: {\n        \"content-type\":     \"application/json\",\n        \"appKey\":           flow.get(\"tw_appKey\")\n    },\n};","outputs":1,"noerr":0,"x":169.27272033691406,"y":349.18184661865234,"wires":[["8e5c0cad.d27a8"]]},{"id":"8e5c0cad.d27a8","type":"http request","z":"a1220086.57409","name":"","method":"use","ret":"txt","url":"","tls":"","x":335.2726745605469,"y":349.0909652709961,"wires":[["4593fa88.7e3e84"]]},{"id":"4593fa88.7e3e84","type":"function","z":"a1220086.57409","name":"add property","func":"var tw_url = \"http://\"+flow.get(\"tw_host\")+\"/Thingworx/\"\ntw_url    += \"Things/\"+flow.get(\"mac\")+\"/Services/AddPropertyDefinition\"\n\nreturn {\n    url:     tw_url,\n    method:  \"POST\",\n    headers: {\n        \"content-type\":     \"application/json\",\n        \"appKey\":           flow.get(\"tw_appKey\")\n    },\n    payload: {  \n        \"name\":             \"temperature\",  \n        \"description\":      \"temperature\",  \n        \"type\":             \"NUMBER\"\n    }\n};","outputs":1,"noerr":0,"x":170.27272033691406,"y":385.2727584838867,"wires":[["38520cb.9adf4f4"]]},{"id":"38520cb.9adf4f4","type":"http request","z":"a1220086.57409","name":"","method":"use","ret":"txt","url":"","tls":"","x":338.2726593017578,"y":385.18187713623047,"wires":[["caf1178.eedaae8"]]},{"id":"caf1178.eedaae8","type":"function","z":"a1220086.57409","name":"put temperature","func":"var tw_url = \"http://\"+flow.get(\"tw_host\")+\"/Thingworx/\"\ntw_url    += \"Things/\"+flow.get(\"mac\")+\"/Properties/temperature\"\n\nreturn {\n    url:     tw_url,\n    method:  \"PUT\",\n    headers: {\n        \"content-type\":     \"application/json\",\n        \"appKey\":           flow.get(\"tw_appKey\")\n    },\n    payload: {  \n        \"temperature\":      flow.get(\"temperature\")\n    }\n};","outputs":1,"noerr":0,"x":151.27272033691406,"y":185.27274322509766,"wires":[["f77d7059.9a8f2"]]},{"id":"f77d7059.9a8f2","type":"http request","z":"a1220086.57409","name":"","method":"use","ret":"txt","url":"","tls":"","x":349.2726287841797,"y":183.18186950683594,"wires":[["b785f623.f63b68"]]}]

Include Page
_inc_node-red_import_flow
_inc_node-red_import_flow

Note

In the function "extract mac and temperature", don't forget to change the variables tw_host and tw_appKey to your ThingWorx instance's hostname/IP address and application key, respectively.

Once everything is running, in your ThingWorx console, you can see the Things corresponding to your motes (we use the mote's MAC address at the name of the thing):

If you click on a mote, and list its properties, you will see there is a property called "temperature" with the latest published value:

Discussion

This post recipe doesn't even scratch the surface of what ThingWorx can do.

Things you can build now:

  • create a "Mashup", i.e. a webpage which can serve as a dashboard to see the state and data of your Things
  • add interactions between Things
  • start an analytics server to analyze your data
  • etc.
Warning
titleAbout Security

Security MUST be taken seriously in all applications, including end-to-end IoT solutions like the one we are building here. This post recipe is minimal by design, and doesn't detail nor contain the level of security you need for a production system.

Thing we haven't touched upon:

  • proper end-to-end security between Node-RED and ThingWorx
    • in particular, in the Node-RED flow above, transactions are done through HTTP rather than HTTPS
  • proper ThingWorx application keying
    • in particular, in this post, we use a single application key which administrative privileges sent "in the clear" in an HTTP header field
  • proper security between the JsonServer and Node-RED
    • in particular, in this postrecipe, the JsonServer doesn't authenticate to Node-RED

When building a production system, we strongly recommend implementing industry-standard security methods.

Some links for your further exploration.