Skip to content

Commit

Permalink
Merge branch 'release/0.3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Daisuke Baba committed Apr 17, 2018
2 parents 91c048e + 15af0e3 commit 533cdfb
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 33 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ $ rm -fr node_modules; \

# Revision History

* 0.3.0
- Add the mac property only when it's available
- Fix an issue where some of events didn't contain the mac address
- Show active motes on the manager dialog for better user experience
- Add the connected mote counter to the connected status label
- Add a new type 'Data' for subscription type

* 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
Expand Down
24 changes: 22 additions & 2 deletions deps/python/oapclient_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ def __init__(self, serialport=DEFAULT_SERIALPORT):
fun=self.oap_dispatch.dispatch_pkt,
isRlbl=False,
)
self.subscriber.subscribe(
notifTypes=[
IpMgrSubscribe.IpMgrSubscribe.NOTIFEVENT,
IpMgrSubscribe.IpMgrSubscribe.NOTIFHEALTHREPORT,
],
fun=self.on_notification_event,
isRlbl=True,
)
self.subscriber.subscribe(
notifTypes=[
IpMgrSubscribe.IpMgrSubscribe.ERROR,
Expand Down Expand Up @@ -216,6 +224,19 @@ def start(self):
if message_lines:
self.process_message(message_lines)

def on_notification_event(self, notifName, notifParams):
"""Called when a mote event is issued.
"""
message = {
'event': 'notification',
'type': notifName
}
try:
message['mac'] = self.format_mac_address(notifParams.macAddress)
except Exception:
pass
self.emit_event(message)

def on_disconnected(self, notifName, notifParams):
"""Called when the connectionFrame has disconnected.
"""
Expand All @@ -233,7 +254,7 @@ def handle_oap_data(self, mac, notif):
mac_address = self.format_mac_address(mac)
try:
message = notif._asdict()
message['event'] = 'notification'
message['event'] = 'data'
message['mac'] = mac_address
self.send_message(message)
except Exception as err:
Expand Down Expand Up @@ -322,7 +343,6 @@ def to_byte_array_mac(self, mac):
return mac_address



if __name__ == "__main__":
# ask user for serial port number
if len(sys.argv) < 2:
Expand Down
4 changes: 2 additions & 2 deletions examples/01-basic-use.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"id": "b2986a8f.d9ad7",
"type": "debug",
"z": "c6d89d06.5920f",
"name": "Notifications",
"name": "Data",
"active": false,
"tosidebar": true,
"console": false,
Expand Down Expand Up @@ -147,7 +147,7 @@
"type": "SmartMesh in",
"z": "c6d89d06.5920f",
"name": "",
"subscriptionType": "notification",
"subscriptionType": "data",
"smartMeshManager": "ee6b7dce.0f8d9",
"x": 287.5,
"y": 317.5,
Expand Down
24 changes: 12 additions & 12 deletions npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "node-red-contrib-smartmesh",
"version": "0.2.0",
"version": "0.3.0",
"description": "Node-RED nodes for Analog Devices' SmartMesh® IP Motes and Manager",
"license": "Apache-2.0",
"repository": {
Expand Down Expand Up @@ -35,14 +35,15 @@
],
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1",
"babel-preset-minify": "^0.3.0",
"chai": "^4.1.2",
"del": "^2.2.2",
"gulp": "^3.9.1",
"gulp-babel": "^7.0.0",
"gulp-babel": "^7.0.1",
"gulp-clean": "^0.4.0",
"gulp-clean-css": "^3.9.3",
"gulp-cli": "^2.0.1",
Expand All @@ -61,7 +62,7 @@
"jshint": "^2.9.5",
"jshint-stylish": "^2.2.1",
"mocha": "^5.0.4",
"sinon": "^4.4.6",
"sinon": "^4.5.0",
"supertest": "^3.0.0"
},
"dependencies": {
Expand Down
20 changes: 16 additions & 4 deletions src/locales/en-US/smartmesh.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ <h3>Outputs</h3>
This node emits 2 kinds of message, one is a <b>Response</b> from the mote to the <b>Request</b> sent to <b>SmartMesh out</b> node, and the other is a <b>Notification</b> from the remote motes.
You can filter the subscription message types on the selection list.
</p>
<h4>Response</h4>
<h4>Results</h4>
<p>
The command result message looks likt this.
The <code>id</code> is an arbitrary value you can set in the request message, which allows you to associate the request with the result.
Expand All @@ -21,14 +21,14 @@ <h4>Response</h4>
"id":"led_on"
}
</pre>
<h4>Notification</h4>
<h4>Data</h4>
<p>
The Notification message contains the temperature value measured in the remote mote.
The Data message contains the temperature value measured in the remote mote.
The following message shows the Cellcius temperature is <code>18.70°C</code>, which is computed by the sampled value <code>1870</code> divided by <code>100</code>.
</p>
<pre>
{
"event":"notification",
"event":"data",
"packet_timestamp":[
1025737777,
379480
Expand All @@ -47,6 +47,18 @@ <h4>Notification</h4>
]
}
</pre>
<h4>Notifications</h4>
<p>
The Notification message contains the SmartMesh network events issued when a remote mote is joined or lost, for instance.
The following message shows a new mote is joined.
</p>
<pre>
{
"event":"notification",
"type":"eventMoteJoin",
"mac":"00-11-22-33-44-55-66-77"
}
</pre>
</script>

<script type="text/x-red" data-help-name="SmartMesh out">
Expand Down
4 changes: 3 additions & 1 deletion src/locales/en-US/smartmesh.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ smartmesh:
smartMeshManager: Manager
subscriptionType: Subscribe
redirectSmartMeshManagerLog: Redirect Manager Error
motes: Active Motes
subscriptionType:
all: All Events
result: Command Results
data: Data Events
notification: Notifications
placeholder:
serialport: e.g. /dev/ttyUSB3 /dev/DC2274A-A.API
identifier: USB Manager Identifier
status:
connected: connected
connected: connected __n__
disconnected: disconnected
error: error
49 changes: 48 additions & 1 deletion src/smartmesh-common.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class SmartMeshClientProxy {
} else {
this.bus = opts.bus || new EventEmitter();
}
this.motes = {};
}

isConnected() {
Expand Down Expand Up @@ -76,6 +77,51 @@ export class SmartMeshClientProxy {
}
}

fireMoteConnected() {
this.bus.emit('connected', this.getActiveMoteCount());
}

processEvent(message) {
if (message.mac && !this.motes[message.mac]) {
this.motes[message.mac] = {
mac: message.mac,
};
if (message.event !== 'notification') {
this.motes[message.mac].joinedAt = Date.now();
this.motes[message.mac].active = true;
this.fireMoteConnected();
return;
}
}
switch (message.type) {
case 'eventMoteJoin':
if (this.motes[message.mac]) {
this.motes[message.mac].joinedAt = Date.now();
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();
}
break;
}
this.fireMoteConnected();
}

getActiveMotes() {
return Object.values(this.motes).filter(mote => mote.active);
}

getActiveMoteCount() {
return this.getActiveMotes().length;
}

getMoteCount() {
return Object.keys(this.motes).length;
}

start() {
// This function call may throw an exception on error
this.cproc = cproc.spawn(`${PYTHON_EXEC}`,
Expand All @@ -86,7 +132,7 @@ export class SmartMeshClientProxy {
stdio: ['pipe', 'pipe', this.redirectSmartMeshManagerLog ? process.stderr : 'ignore']
}
);
this.bus.emit('connected');
this.fireMoteConnected();
this.cproc.on('exit', (code) => {
let message = '';
switch (code) {
Expand Down Expand Up @@ -122,6 +168,7 @@ export class SmartMeshClientProxy {
this.bus.emit('error-event', message);
} else {
this.bus.emit('event', message);
this.processEvent(message);
}
} catch (_) {
return;
Expand Down
46 changes: 46 additions & 0 deletions src/smartmesh.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<select type='text' id='node-input-subscriptionType' style='width: 70%;'>
<option value='all' data-i18n='smartmesh.subscriptionType.all'></option>
<option value='result' data-i18n='smartmesh.subscriptionType.result'></option>
<option value='data' data-i18n='smartmesh.subscriptionType.data'></option>
<option value='notification' data-i18n='smartmesh.subscriptionType.notification'></option>
</select>
</div>
Expand Down Expand Up @@ -112,6 +113,10 @@
<input type="checkbox" id="node-config-input-redirectSmartMeshManagerLog" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-config-input-redirectSmartMeshManagerLog" style="width: 70%;" data-i18n="smartmesh.label.redirectSmartMeshManagerLog"></label>
</div>
<div class='form-row node-config-input-motes-container-row'>
<i class='fa fa-braille'></i> <span data-i18n='smartmesh.label.motes'></span>
<ol id='node-config-input-motes-container'></ol>
</div>
</script>

<script type="text/javascript">
Expand Down Expand Up @@ -152,6 +157,47 @@
}).autocomplete('search', '');
});
});

$('#node-config-input-motes-container').css('min-height','250px').css('min-width','450px').editableList({
addItem: function(container, i, opt) {
if (!opt || !opt.mac) {
return;
}
var mote = opt;
var row = $('<div/>').appendTo(container);

var mac = $('<span/>',{style:'margin-left: 5px;'}).text(mote.mac).appendTo(row);
var joinedAt = $('<span/>',{style:'margin-left: 5px;'}).text(' (' + new Date(mote.joinedAt).toLocaleString() + ')').appendTo(row);
},
sortable: false,
removable: false,
addButton: false
});

function clearMotes() {
var children = $('#node-config-input-motes-container')[0].children;
var len = children.length;
for (var i = 0; i < len; i++) {
children[0].remove();
}
}

$.ajax({
cache: false,
url: 'smartmesh/' + encodeURIComponent(this.serialport) + '/motes',
dataType: 'json',
success: function(motes) {
for (var i = 0; i < motes.length; i++) {
$('#node-config-input-motes-container').editableList('addItem', motes[i]);
}
if (motes.length === 0) {
clearMotes();
}
},
error: function () {
clearMotes();
}
});
}
});
</script>
Loading

0 comments on commit 533cdfb

Please sign in to comment.