diff --git a/.travis.yml b/.travis.yml index 4d36372..18523be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: node_js node_js: - - 6.13 - - 8.10 + - 6.14.1 + - 8.11.1 python: - 2.7 diff --git a/README.md b/README.md index ad3b1ee..788bf20 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,46 @@ node-red-contrib-smartmesh [![GitHub release](https://img.shields.io/github/release/CANDY-LINE/node-red-contrib-smartmesh.svg)](https://github.com/CANDY-LINE/node-red-contrib-smartmesh/releases/latest) [![master Build Status](https://travis-ci.org/CANDY-LINE/node-red-contrib-smartmesh.svg?branch=master)](https://travis-ci.org/CANDY-LINE/node-red-contrib-smartmesh/) -Node-RED nodes for Analog Devices' SmartMesh® IP Motes and Manager +Node-RED nodes for Analog Devices' [DC2274A-A SmartMesh IP™ USB Network Manager](http://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/dc2274a-a.html). -# ALPHA RELEASE +![DC2274A-A, Motes, RPi Zero WH and CANDY_Pi_Lite](images/DC2274A-A_Motes_RPi_CANDY_Pi_Lite.jpg) -These nodes are NOT YET AVAILABLE via Node-RED palette manager. +The above picture shows a typical demonstration set including: + +- DC2274A-A SmartMesh IP™ USB Manager dongle +- SmartMesh IP™ Motes containing controllable LED, temperature sensor and GPIO/UART/SPI/I2C interfaces +- Raspberry Pi Zero WH for running Node-RED/CANDY RED(a custom version of Node-RED dedicated to CANDY Pi Lite) +- CANDY Pi Lite LTE Board for 4G/LTE mobile connection to upload data/download control commands to/from cloud servers + +## Example Flow + +The bundled example flow includes the following operations: + +- Turn on/off LED on remote motes +- Getting LED on/off command results +- Showing temperature data from remote motes +- Showing SmartMesh network event notifications + +![Example flow](images/example-flow-working.jpg) + +## Easy to use + +These are provided by the default firmware on the evaluation kit. So you don't have to flash a specific firmware to work the example but just turn all motes on and connect the USB manager to Raspberry Pi, ASUS Tinker Board or other Linux box where Node-RED runs. + +## Listing Active Motes + +You can find the active (online) motes from the manager dialog while monitoring the flow. + +![DC2274A-A SmartMesh IP™ USB Manager Dialog](images/usb-manager-dialog.jpg) + +## SmartMesh IP Document + +See [SmartMesh IP™ Tools Guide(PDF)](http://cds.linear.com/docs/en/software-and-simulation/SmartMesh_IP_Tools_Guide.pdf) for SmartMesh IP™ technical details. # Prerequisites +[SmartMesh SDK v1.3.0.1](https://dustcloud.atlassian.net/wiki/spaces/SMSDK/overview) ([GitHub repo](https://github.com/dustcloud/smartmeshsdk)) requires the following environments. + 1. Python 2.7 (Python 2.6/3.x are NOT supported) 1. PySerial 3.4+ @@ -30,9 +62,9 @@ sudo npm install --unsafe-perm node-red-contrib-smartmesh Then restart Node-RED process. -`sudo` is used for installing SmartMesh SDK into dist-package directory. +`sudo` is used for installing [SmartMesh SDK](https://dustcloud.atlassian.net/wiki/spaces/SMSDK/overview) into dist-package directory. -**Node-RED users cannot install this node via `Manage Palette` dialog because of insufficient permission.** +**Node-RED users cannot install this node via `Manage Palette` dialog because of insufficient permission unless the process is owned by privileged user. Use the above commands to install it.** ### Uninstallation @@ -87,6 +119,11 @@ $ rm -fr node_modules; \ # Revision History +* 1.0.0 + - Initial General Availability Release + - Add `node-red` keyword + - Fix an issue where Active Motes were never shown in the manager dialog + * 0.3.1 - Fix an issue where Object.value function was missing on Node.js v6 @@ -99,7 +136,7 @@ $ rm -fr node_modules; \ * 0.2.0 - Fix an issue where /usr/local directory was removed when uninstalling this package - - Add a new property to SmartMesh manager node to append a source manager identifier to the mote event message + - Add a new property to SmartMesh IP™ manager node to append a source manager identifier to the mote event message * 0.1.0 - Initial Release (alpha) diff --git a/examples/01-basic-use.json b/examples/01-basic-use.json index 7798f5e..0b2eb83 100644 --- a/examples/01-basic-use.json +++ b/examples/01-basic-use.json @@ -1,57 +1,57 @@ [ { - "id": "c6d89d06.5920f", + "id": "92e1ac59.e47078", "type": "tab", "label": "SmartMesh Example", "disabled": false, "info": "" }, { - "id": "b2986a8f.d9ad7", + "id": "54fcf07a.bf08a", "type": "debug", - "z": "c6d89d06.5920f", + "z": "92e1ac59.e47078", "name": "Data", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", - "x": 483.5, - "y": 338, + "x": 467.5, + "y": 322, "wires": [] }, { - "id": "3ffb1672.a60f62", + "id": "7025063f.b96168", "type": "catch", - "z": "c6d89d06.5920f", + "z": "92e1ac59.e47078", "name": "", "scope": null, - "x": 288.5, - "y": 407.25, + "x": 285.5, + "y": 453.25, "wires": [ [ - "c501407a.4f901" + "c015984c.413828" ] ] }, { - "id": "c501407a.4f901", + "id": "c015984c.413828", "type": "debug", - "z": "c6d89d06.5920f", + "z": "92e1ac59.e47078", "name": "Error", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", - "x": 466, - "y": 430, + "x": 463, + "y": 476, "wires": [] }, { - "id": "ec6099a0.8fa528", + "id": "304fbe9d.7fd2d2", "type": "inject", - "z": "c6d89d06.5920f", + "z": "92e1ac59.e47078", "name": "LED ON (77-66-55-44-33-22-11-00)", "topic": "", "payload": "{\"mac\":\"77-66-55-44-33-22-11-00\",\"id\":\"led_on_1\",\"command\":\"PUT\",\"address\":\"/3/2\",\"tags\":[{\"tag\":0,\"format\":\"byte\",\"value\":\"01\"}]}", @@ -64,14 +64,14 @@ "y": 126.25, "wires": [ [ - "3e057e47.5a7ec2" + "6fc4a724.b5b028" ] ] }, { - "id": "c8ba34be.f56728", + "id": "6b2a80f9.18ed18", "type": "inject", - "z": "c6d89d06.5920f", + "z": "92e1ac59.e47078", "name": "LED OFF (77-66-55-44-33-22-11-00)", "topic": "", "payload": "{\"mac\":\"77-66-55-44-33-22-11-00\",\"id\":\"led_off_1\",\"command\":\"PUT\",\"address\":\"/3/2\",\"tags\":[{\"tag\":0,\"format\":\"byte\",\"value\":\"00\"}]}", @@ -84,14 +84,14 @@ "y": 165, "wires": [ [ - "3e057e47.5a7ec2" + "6fc4a724.b5b028" ] ] }, { - "id": "b108ec89.42f84", + "id": "ea75a621.087868", "type": "debug", - "z": "c6d89d06.5920f", + "z": "92e1ac59.e47078", "name": "Results", "active": true, "tosidebar": true, @@ -103,9 +103,9 @@ "wires": [] }, { - "id": "f24254f3.f27428", + "id": "45c6981.3bbe268", "type": "inject", - "z": "c6d89d06.5920f", + "z": "92e1ac59.e47078", "name": "LED ON (00-11-22-33-44-55-66-77)", "topic": "", "payload": "{\"mac\":\"00-11-22-33-44-55-66-77\",\"id\":\"led_on_2\",\"command\":\"PUT\",\"address\":\"/3/2\",\"tags\":[{\"tag\":0,\"format\":\"byte\",\"value\":\"01\"}]}", @@ -118,14 +118,14 @@ "y": 38, "wires": [ [ - "3e057e47.5a7ec2" + "6fc4a724.b5b028" ] ] }, { - "id": "793d90b2.1e85a", + "id": "af823f6.ba6cd4", "type": "inject", - "z": "c6d89d06.5920f", + "z": "92e1ac59.e47078", "name": "LED OFF (00-11-22-33-44-55-66-77)", "topic": "", "payload": "{\"mac\":\"00-11-22-33-44-55-66-77\",\"id\":\"led_off_2\",\"command\":\"PUT\",\"address\":\"/3/2\",\"tags\":[{\"tag\":0,\"format\":\"byte\",\"value\":\"00\"}]}", @@ -138,29 +138,29 @@ "y": 76, "wires": [ [ - "3e057e47.5a7ec2" + "6fc4a724.b5b028" ] ] }, { - "id": "158ec6f5.4b6a91", + "id": "4885770e.30ee", "type": "SmartMesh in", - "z": "c6d89d06.5920f", + "z": "92e1ac59.e47078", "name": "", "subscriptionType": "data", "smartMeshManager": "ee6b7dce.0f8d9", "x": 287.5, - "y": 317.5, + "y": 304.5, "wires": [ [ - "b2986a8f.d9ad7" + "54fcf07a.bf08a" ] ] }, { - "id": "f93ecaa3.027ad8", + "id": "36e2a78c.1953e8", "type": "SmartMesh in", - "z": "c6d89d06.5920f", + "z": "92e1ac59.e47078", "name": "", "subscriptionType": "result", "smartMeshManager": "ee6b7dce.0f8d9", @@ -168,26 +168,56 @@ "y": 236.5, "wires": [ [ - "b108ec89.42f84" + "ea75a621.087868" ] ] }, { - "id": "3e057e47.5a7ec2", + "id": "6fc4a724.b5b028", "type": "SmartMesh out", - "z": "c6d89d06.5920f", + "z": "92e1ac59.e47078", "name": "", "smartMeshManager": "ee6b7dce.0f8d9", "x": 484.5, "y": 89.5, "wires": [] }, + { + "id": "f45bdede.d01c98", + "type": "debug", + "z": "92e1ac59.e47078", + "name": "Notifications", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "payload", + "x": 489, + "y": 393, + "wires": [] + }, + { + "id": "97ac2d0d.43742", + "type": "SmartMesh in", + "z": "92e1ac59.e47078", + "name": "", + "subscriptionType": "notification", + "smartMeshManager": "ee6b7dce.0f8d9", + "x": 288, + "y": 374.5, + "wires": [ + [ + "f45bdede.d01c98" + ] + ] + }, { "id": "ee6b7dce.0f8d9", "type": "SmartMesh manager", "z": "", "enabled": true, "serialport": "/dev/DC2274A-A.API", + "identifier": "manager1", "redirectSmartMeshManagerLog": true } ] diff --git a/images/DC2274A-A_Motes_RPi_CANDY_Pi_Lite.jpg b/images/DC2274A-A_Motes_RPi_CANDY_Pi_Lite.jpg new file mode 100644 index 0000000..669fe1b Binary files /dev/null and b/images/DC2274A-A_Motes_RPi_CANDY_Pi_Lite.jpg differ diff --git a/images/example-flow-working.jpg b/images/example-flow-working.jpg new file mode 100644 index 0000000..95207e8 Binary files /dev/null and b/images/example-flow-working.jpg differ diff --git a/images/usb-manager-dialog.jpg b/images/usb-manager-dialog.jpg new file mode 100644 index 0000000..925d6a0 Binary files /dev/null and b/images/usb-manager-dialog.jpg differ diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index c41ba4c..be9019f 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-smartmesh", - "version": "0.3.1", + "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 6faeaa0..8c6c10a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "node-red-contrib-smartmesh", - "version": "0.3.1", - "description": "Node-RED nodes for Analog Devices' SmartMesh® IP Motes and Manager", + "version": "1.0.0", + "description": "Node-RED nodes for Analog Devices' SmartMesh IP™ Motes and Manager", "license": "Apache-2.0", "repository": { "type": "git", @@ -25,6 +25,7 @@ ], "homepage": "https://github.com/CANDY-LINE/node-red-contrib-smartmesh#readme", "keywords": [ + "node-red", "smartmesh", "dust networks", "Analog Devices", diff --git a/src/locales/en-US/smartmesh.html b/src/locales/en-US/smartmesh.html index 620f905..2719a17 100644 --- a/src/locales/en-US/smartmesh.html +++ b/src/locales/en-US/smartmesh.html @@ -2,6 +2,9 @@

Emits an OAP (On-chip Application Protocol) request result or notifications coming from the remote motes to the output port.

+

+The connected status below the node shows the number of active motes as well as the SmartMesh manager connection status. +

Outputs

This node emits 2 kinds of message, one is a Response from the mote to the Request sent to SmartMesh out node, and the other is a Notification from the remote motes. @@ -18,7 +21,9 @@

Results

"mac":"00-17-0d-00-00-31-4f-ef", "command":"PUT", "event":"result", - "id":"led_on" + "id":"led_on", + "managerId":"manager-identifier", + "timestamp":1234567890 }

Data

@@ -44,7 +49,9 @@

Data

"num_samples":1, "channel":[ 5 - ] + ], + "managerId":"manager-identifier", + "timestamp":1234567890 }

Notifications

@@ -56,9 +63,22 @@

Notifications

{ "event":"notification", "type":"eventMoteJoin", - "mac":"00-11-22-33-44-55-66-77" + "mac":"00-11-22-33-44-55-66-77", + "managerId":"manager-identifier", + "timestamp":1234567890 } +

+The available event types are: +

+

diff --git a/src/smartmesh-common.js b/src/smartmesh-common.js index 46bad4f..89a684b 100644 --- a/src/smartmesh-common.js +++ b/src/smartmesh-common.js @@ -87,7 +87,7 @@ export class SmartMeshClientProxy { mac: message.mac, }; if (message.event !== 'notification') { - this.motes[message.mac].joinedAt = Date.now(); + this.motes[message.mac].joinedAt = message.timestamp; this.motes[message.mac].active = true; this.fireMoteConnected(); return; @@ -96,14 +96,14 @@ export class SmartMeshClientProxy { switch (message.type) { case 'eventMoteJoin': if (this.motes[message.mac]) { - this.motes[message.mac].joinedAt = Date.now(); + this.motes[message.mac].joinedAt = message.timestamp; this.motes[message.mac].active = true; } break; case 'eventMoteLost': if (this.motes[message.mac]) { this.motes[message.mac].active = false; - this.motes[message.mac].lostAt = Date.now(); + this.motes[message.mac].lostAt = message.timestamp; } break; } @@ -111,7 +111,8 @@ export class SmartMeshClientProxy { } getActiveMotes() { - return Object.keys(this.motes).filter(mac => this.motes[mac].active); + return Object.keys(this.motes).filter(mac => this.motes[mac].active) + .map(mac => Object.assign({}, this.motes[mac])); } getActiveMoteCount() { @@ -164,6 +165,7 @@ export class SmartMeshClientProxy { let procs = lines.map((line) => { try { let message = JSON.parse(line); + message.timestamp = Date.now(); if (message.event === 'error') { this.bus.emit('error-event', message); } else { diff --git a/src/smartmesh.html b/src/smartmesh.html index ac9fdb8..31c175b 100644 --- a/src/smartmesh.html +++ b/src/smartmesh.html @@ -166,8 +166,14 @@ var mote = opt; var row = $('
').appendTo(container); - var mac = $('',{style:'margin-left: 5px;'}).text(mote.mac).appendTo(row); - var joinedAt = $('',{style:'margin-left: 5px;'}).text(' (' + new Date(mote.joinedAt).toLocaleString() + ')').appendTo(row); + var mac = $('',{ + class:'debug-message-element', + style:'margin-left: 5px;width:70%' + }).text(mote.mac).appendTo(row); + var joinedAt = $('',{ + class:'debug-message-element', + style:'margin-left: 5px;width:30%' + }).text('| ' + new Date(mote.joinedAt).toLocaleString()).appendTo(row); }, sortable: false, removable: false,