@ncd-io/node-red-enterprise-sensors 0.1.23 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/DigiParser.js CHANGED
@@ -122,6 +122,7 @@ module.exports = class DigiComm{
122
122
  that.serial.write(packet, (err) => {
123
123
  that.lastSent = packet;
124
124
  if(err){
125
+ console.log('_send frame error');
125
126
  console.log(err);
126
127
  }
127
128
  });
@@ -172,8 +173,8 @@ class outgoingFrame{
172
173
  var config = this.transmissionOptions(opts);
173
174
  var frame = [17, this.master.getId()];
174
175
  frame.push(...mac);
175
- var stuff = [255, 254, source, destination, cluster[0], cluster[1], profile[0], profile[1], (config >> 8), (config & 255)];
176
- frame.push(...stuff);
176
+ var payload = [255, 254, source, destination, cluster[0], cluster[1], profile[0], profile[1], (config >> 8), (config & 255)];
177
+ frame.push(...payload);
177
178
  if(data.constructor != Array) data = [data];
178
179
  frame.push(...data);
179
180
  return this.master._send(frame);
@@ -136,6 +136,11 @@ module.exports = class WirelessSensor{
136
136
  var is_new = typeof this.sensor_pool[frame.mac] == 'undefined';
137
137
  var new_mode = is_new;
138
138
  var mode = (type == 'power_up') ? data.mode : ((type == 'sensor_data') ? 'RUN' : ((type == 'config_ack') ? 'ACK' : 'PGM'));
139
+ if(mode == 'ACK'){
140
+ if(data.data.length == 37){
141
+ this._emitter.emit('manifest_received', data);
142
+ }
143
+ }
139
144
  // #OTF
140
145
  var otf_devices = [23,26,39,45,48,52,76,78,79,80,81,82,84,88,89,90,91,101,102,107,108,180,181,519,520,521,531,535,537];
141
146
  var device_type = msbLsb(frame.data[6], frame.data[7]);
@@ -492,18 +497,6 @@ module.exports = class WirelessSensor{
492
497
  if('z_offset' in en_axis_data){
493
498
  fft_concat[label].z = parseFloat((signInt(((raw_data[i+en_axis_data.z_offset]<<8)+(raw_data[i+en_axis_data.z_offset+1])), 16)*fsr_mult).toFixed(5));
494
499
  }
495
-
496
-
497
- // fft.push(fft_data);
498
- // if(label< 40){
499
- // fft_concat[label] = {
500
- // // label: label,
501
- // x: parseFloat((signInt(((raw_data[i]<<8)+(raw_data[i+1]&255)), 16)*.00006).toFixed(5)),
502
- // y: parseFloat((signInt(((raw_data[i+2]<<8)+(raw_data[i+3]&255)), 16)*.00006).toFixed(5)),
503
- // z: parseFloat((signInt(((raw_data[i+4]<<8)+(raw_data[i+5]&255)), 16)*.00006).toFixed(5)),
504
- // };
505
- // }
506
-
507
500
  }
508
501
  var fft_concat_obj = {
509
502
  time_id: globalDevices[deviceAddr].hour +':'+ globalDevices[deviceAddr].minute,
@@ -733,6 +726,41 @@ module.exports = class WirelessSensor{
733
726
  }
734
727
  return parsed;
735
728
  }
729
+ firmware_set_to_ota_mode(sensor_mac){
730
+ console.log('firmware_set_to_ota_mode');
731
+ var packet = [245, 56, 0, 0, 0];
732
+ return this.config_send(sensor_mac, packet);
733
+ }
734
+ // TODO no code basis
735
+ firmware_exit_ota_mode(sensor_mac){
736
+ console.log('firmware_exit_ota_mode');
737
+ var packet = [245, 57, 0, 0, 0];
738
+ return this.config_send(sensor_mac, packet);
739
+ }
740
+ firmware_request_manifest(sensor_mac){
741
+ console.log('firmware_request_manifest');
742
+ var packet = [245, 60, 0, 0, 0];
743
+ return this.config_send(sensor_mac, packet);
744
+ }
745
+ firmware_send_manifest(sensor_mac, manifest){
746
+ console.log('firmware_send_manifest');
747
+ // sensor_mac = "00:00:00:00:00:00:ff:ff";
748
+ let packet = [245, 58, 0, 0, 0].concat(Array.prototype.slice.call(manifest));
749
+ return this.config_send(sensor_mac, packet);
750
+ }
751
+ firmware_send_chunk(sensor_mac, offset, chunk){
752
+ console.log('firmware_send_chunk');
753
+ // sensor_mac = "00:00:00:00:00:00:ff:ff";
754
+ let packet = [245, 59, 0, 0, 0].concat(offset, Array.prototype.slice.call(chunk));
755
+ // console.log(packet);
756
+ return this.config_send(sensor_mac, packet);
757
+ }
758
+ firmware_request_last_segment(sensor_mac){
759
+ console.log('firmware_request_last_segment');
760
+ let packet = [245, 61, 0, 0, 0];
761
+ // console.log(packet);
762
+ return this.config_send(sensor_mac, packet);
763
+ }
736
764
  config_reboot_sensor(sensor_mac){
737
765
  console.log('config_reboot_sensor: '+sensor_mac)
738
766
  var packet = [247, 64, 0, 0, 0];
@@ -916,7 +944,6 @@ module.exports = class WirelessSensor{
916
944
  console.log('config_set_sensor_forced_calibration_535');
917
945
  // convert before processing
918
946
  var packet = [244, 32, 0, 0, 0];
919
- console.log(packet);
920
947
  return this.config_send(sensor_mac, packet);
921
948
  }
922
949
  config_set_sensor_temperature_offset_44(sensor_mac, value){
@@ -1136,7 +1163,7 @@ module.exports = class WirelessSensor{
1136
1163
  return this.config_send(sensor_mac, packet);
1137
1164
  }
1138
1165
  config_set_roll_threshold_47(sensor_mac, threshold){
1139
- console.log('config_set_pitch_threshold_47');
1166
+ console.log('config_set_roll_threshold_47');
1140
1167
  var packet = [244, 1, 0, 0, 47, 0, threshold];
1141
1168
  console.log(packet);
1142
1169
  return this.config_send(sensor_mac, packet);
@@ -1147,7 +1174,6 @@ module.exports = class WirelessSensor{
1147
1174
  console.log(packet);
1148
1175
  return this.config_send(sensor_mac, packet);
1149
1176
  }
1150
-
1151
1177
  config_set_accelerometer_threshold_108(sensor_mac, value){
1152
1178
  console.log('config_set_accelerometer_threshold_108');
1153
1179
  var packet = [244, 32, 0, 0, 0, 1, value];
@@ -1498,6 +1524,11 @@ module.exports = class WirelessSensor{
1498
1524
  };
1499
1525
  return this.config_send(sensor_mac, [(data ? 247 : 248), params[param], ...data]);
1500
1526
  }
1527
+ clear_queue(){
1528
+ this.queue.queue = new Array;
1529
+ delete this.queue;
1530
+ this.queue = new Queue(1);
1531
+ }
1501
1532
  config_send(sensor_mac, data, opts){
1502
1533
  var that = this;
1503
1534
  return new Promise((fulfill, reject) => {
@@ -4093,7 +4124,6 @@ function sensor_types(parent){
4093
4124
  }
4094
4125
  }
4095
4126
  },
4096
-
4097
4127
  '82': {
4098
4128
  name: 'Condition Based/Predictive Maintenance Sensor',
4099
4129
  parse: (payload, parsed, mac) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ncd-io/node-red-enterprise-sensors",
3
- "version": "0.1.23",
3
+ "version": "1.0.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/wireless.html CHANGED
@@ -953,7 +953,7 @@
953
953
  </select>
954
954
  </div>
955
955
  </div>
956
- <div class="ncd-dependent" data-sensor-7 data-sensor-24>
956
+ <div class="ncd-dependent" data-sensor-7 data-sensor-24 data-sensor-25>
957
957
  <hr>
958
958
  <div class="form-row ncd-active-check">
959
959
  <div>
@@ -1026,7 +1026,7 @@
1026
1026
  </div>
1027
1027
  </div>
1028
1028
  </div>
1029
- <div class="ncd-dependent" data-sensor-24>
1029
+ <div class="ncd-dependent" data-sensor-24 data-sensor-25>
1030
1030
  <div class="form-row">
1031
1031
  <label for="node-input-activ_interr_x"><i class="icon-tag"></i> Interrupt X-Axis</label>
1032
1032
  <select id="node-input-activ_interr_x">
@@ -1820,7 +1820,6 @@
1820
1820
  </div>
1821
1821
  </div>
1822
1822
  </div>
1823
-
1824
1823
  <div class="ncd-dependent" data-sensor-108>
1825
1824
  <div class="form-row ncd-active-check">
1826
1825
  <strong>Enable Accelerometer Error Reporting</strong>
@@ -1872,7 +1871,6 @@
1872
1871
  </div>
1873
1872
  </div>
1874
1873
  </div>
1875
-
1876
1874
  <div class="ncd-dependent" data-sensor-35 data-sensor-36>
1877
1875
  <hr>
1878
1876
  <div class="form-row ncd-active-check">
package/wireless.js CHANGED
@@ -3,7 +3,8 @@ const comms = require('ncd-red-comm');
3
3
  const sp = require('serialport');
4
4
  const Queue = require("promise-queue");
5
5
  const events = require("events");
6
-
6
+ const fs = require('fs');
7
+ const home_dir = require('os').homedir
7
8
  module.exports = function(RED) {
8
9
  var gateway_pool = {};
9
10
  function NcdGatewayConfig(config){
@@ -14,6 +15,8 @@ module.exports = function(RED) {
14
15
 
15
16
  this.listeners = [];
16
17
  this.sensor_pool = [];
18
+ // TODO sensor_list is a temporary property, should be combined with sensor_pool
19
+ this.sensor_list = {};
17
20
  this._emitter = new events.EventEmitter();
18
21
  this.on = (e,c) => this._emitter.on(e, c);
19
22
 
@@ -72,6 +75,67 @@ module.exports = function(RED) {
72
75
  node.gateway.digi.serial.reconnect();
73
76
  });
74
77
  }
78
+ // Event listener to make sure this only triggers once no matter how many gateway nodes there are
79
+ node.gateway.on('sensor_mode', (d) => {
80
+ if(d.mode == "FLY"){
81
+ if(Object.hasOwn(node.sensor_list, d.mac) && Object.hasOwn(node.sensor_list[d.mac], 'update_request')){
82
+ node.request_manifest(d.mac);
83
+ };
84
+ };
85
+ });
86
+ node.gateway.on('manifest_received', (manifest_data) => {
87
+ // read manifest length is 37. Could use the same event for both
88
+ if(Object.hasOwn(node.sensor_list, manifest_data.addr) && Object.hasOwn(node.sensor_list[manifest_data.addr], 'update_request')){
89
+ // TODO check manifest data and start update process
90
+ }
91
+ manifest_data.data = node._parse_manifest_read(manifest_data.data);
92
+ node._emitter.emit('send_manifest', manifest_data);
93
+ let firmware_data = node._compare_manifest(manifest_data);
94
+ if(!firmware_data){
95
+ delete node.sensor_list[manifest_data.addr].update_request;
96
+ return;
97
+ }
98
+
99
+ // TODO Right now assume everything is good
100
+ // node.gateway.firmware_set_to_ota_mode(manifest_data.addr);
101
+
102
+ setTimeout(() => {
103
+ var tout = setTimeout(() => {
104
+ console.log('Start OTA Timed Out');
105
+ }, 10000);
106
+
107
+ var promises = {};
108
+ promises.firmware_set_to_ota_mode = node.gateway.firmware_set_to_ota_mode(manifest_data.addr);
109
+ promises.finish = new Promise((fulfill, reject) => {
110
+ node.gateway.queue.add(() => {
111
+ return new Promise((f, r) => {
112
+ clearTimeout(tout);
113
+ // node.status(modes.FLY);
114
+ fulfill();
115
+ f();
116
+ });
117
+ });
118
+ });
119
+ for(var i in promises){
120
+ (function(name){
121
+ promises[name].then((f) => {
122
+ if(name != 'finish'){
123
+ console.log(name);
124
+ }
125
+ else{
126
+ // enter ota mode
127
+ node.gateway.digi.send.at_command("ID", [0x7a, 0xaa]).then().catch().then(() => {
128
+ node.start_firmware_update(manifest_data, firmware_data);
129
+ });
130
+ }
131
+ }).catch((err) => {
132
+ console.log(err);
133
+ // msg[name] = err;
134
+ });
135
+ })(i);
136
+ }
137
+ });
138
+ });
75
139
  }));
76
140
  });
77
141
  node.gateway.digi.serial.on('closed_comms', () => {
@@ -102,6 +166,81 @@ module.exports = function(RED) {
102
166
  });
103
167
  };
104
168
 
169
+ node.start_firmware_update = function(manifest_data, firmware_data){
170
+ return new Promise((top_fulfill, top_reject) => {
171
+ var success = {};
172
+
173
+ setTimeout(() => {
174
+ let chunk_size = 128;
175
+ let image_start = firmware_data.firmware.slice(1, 5).reduce(msbLsb)+6;
176
+
177
+ var promises = {};
178
+ promises.manifest = node.gateway.firmware_send_manifest(manifest_data.addr, firmware_data.firmware.slice(5, image_start-1));
179
+ firmware_data.firmware = firmware_data.firmware.slice(image_start+4);
180
+
181
+ var index = 0;
182
+ if(Object.hasOwn(node.sensor_list[manifest_data.addr], 'last_chunk_success')){
183
+ index = node.sensor_list[manifest_data.addr].last_chunk_success;
184
+ }
185
+ var temp_count = 0;
186
+ while(index*chunk_size < firmware_data.manifest.image_size){
187
+ let offset = index*chunk_size;
188
+ // console.log(index);
189
+ // let packet = [254, 59, 0, 0, 0];
190
+ let offset_bytes = int2Bytes(offset, 4);
191
+ let firmware_chunk = firmware_data.firmware.slice(index*chunk_size, index*chunk_size+chunk_size);
192
+ temp_count += 1;
193
+ // packet = packet.concat(offset_bytes, firmware_chunk);
194
+ promises[index] = node.gateway.firmware_send_chunk(manifest_data.addr, offset_bytes, firmware_chunk);
195
+ index++;
196
+ }
197
+
198
+ promises.reboot = node.gateway.config_reboot_sensor(manifest_data.addr);
199
+
200
+ for(var i in promises){
201
+ (function(name){
202
+ promises[name].then((f) => {
203
+ if(name == 'manifest'){
204
+ // delete node.sensor_list[manifest_data.addr].promises[name];
205
+ node.sensor_list[manifest_data.addr].test_check = {name: true};
206
+ node.sensor_list[manifest_data.addr].update_in_progress = true;
207
+ }else {
208
+ success[name] = true;
209
+ node.sensor_list[manifest_data.addr].test_check[name] = true;
210
+ node.sensor_list[manifest_data.addr].last_chunk_success = name;
211
+ // delete node.sensor_list[manifest_data.addr].promises[name];
212
+ }
213
+ }).catch((err) => {
214
+ if(name != 'reboot'){
215
+ node.gateway.clear_queue();
216
+ success[name] = err;
217
+ }else{
218
+ delete node.sensor_list[manifest_data.addr].last_chunk_success;
219
+ delete node.sensor_list[manifest_data.addr].update_request;
220
+ node._emitter.emit('send_firmware_stats', {state: success, addr: manifest_data.addr});
221
+ // #OTF
222
+ // node.send({topic: 'Config Results', payload: success, time: Date.now(), addr: manifest_data.addr});
223
+ top_fulfill(success);
224
+ }
225
+ node._emitter.emit('send_firmware_stats', {state: success, addr: manifest_data.addr});
226
+ node.resume_normal_operation();
227
+ });
228
+ })(i);
229
+ }
230
+ }, 1000);
231
+ });
232
+ }
233
+ node.resume_normal_operation = function(){
234
+ let pan_id = parseInt(config.pan_id, 16);
235
+ node.gateway.digi.send.at_command("ID", [pan_id >> 8, pan_id & 255]).then().catch().then(() => {
236
+ console.log('Set Pan ID to: '+pan_id);
237
+ });
238
+ }
239
+
240
+ node.request_manifest = function(sensor_addr){
241
+ // Request Manifest
242
+ node.gateway.firmware_request_manifest(sensor_addr);
243
+ };
105
244
 
106
245
  node.close_comms = function(){
107
246
  // node.gateway._emitter.removeAllListeners('sensor_data');
@@ -118,7 +257,55 @@ module.exports = function(RED) {
118
257
  // });
119
258
  }
120
259
  }
260
+ }
261
+ node._compare_manifest = function(sensor_manifest){
262
+ let firmware_dir = home_dir()+'/.node-red/node_modules/@ncd-io/node-red-enterprise-sensors/firmware_files';
263
+ let filename = '/' + sensor_manifest.data.device_type + '-' + sensor_manifest.data.hardware_id[0] + '_' + sensor_manifest.data.hardware_id[1] + '_' + sensor_manifest.data.hardware_id[2] + '.ncd';
264
+
265
+ try {
266
+ let firmware_file = fs.readFileSync(firmware_dir+filename,)
267
+ let stored_manifest = node._parse_manifest(firmware_file);
268
+ if(stored_manifest.firmware_version === sensor_manifest.data.firmware_version){
269
+ console.log('firmware versions SAME');
270
+ return false;
271
+ }
121
272
 
273
+ if(stored_manifest.max_image_size < sensor_manifest.data.image_size){
274
+ console.log('firmware image too large');
275
+ return false;
276
+ }
277
+ return {manifest: stored_manifest, firmware: firmware_file};
278
+ } catch(err){
279
+ console.log(err);
280
+ return err;
281
+ }
282
+ }
283
+ node._parse_manifest = function(bin_data){
284
+ return {
285
+ manifest_check: bin_data[0] == 0x01,
286
+ manifest_size: bin_data.slice(1, 5).reduce(msbLsb),
287
+ firmware_version: bin_data[5],
288
+ image_start_address: bin_data.slice(6, 10).reduce(msbLsb),
289
+ image_size: bin_data.slice(10, 14).reduce(msbLsb),
290
+ max_image_size: bin_data.slice(14, 18).reduce(msbLsb),
291
+ image_digest: bin_data.slice(18, 34),
292
+ device_type: bin_data.slice(34, 36).reduce(msbLsb),
293
+ hardware_id: bin_data.slice(36, 39),
294
+ reserve_bytes: bin_data.slice(39, 42)
295
+ }
296
+ };
297
+ node._parse_manifest_read = function(bin_data){
298
+ return {
299
+ // manifest_size: bin_data.slice(0,4).reduce(msbLsb),
300
+ firmware_version: bin_data[0],
301
+ image_start_address: bin_data.slice(1, 5).reduce(msbLsb),
302
+ image_size: bin_data.slice(5, 9).reduce(msbLsb),
303
+ max_image_size: bin_data.slice(9, 13).reduce(msbLsb),
304
+ image_digest: bin_data.slice(13, 29),
305
+ device_type: bin_data.slice(29, 31).reduce(msbLsb),
306
+ hardware_id: bin_data.slice(31, 34),
307
+ reserve_bytes: bin_data.slice(34, 37)
308
+ }
122
309
  }
123
310
  }
124
311
 
@@ -149,7 +336,17 @@ module.exports = function(RED) {
149
336
  node.set_status = function(){
150
337
  node.status(statuses[node._gateway_node.is_config]);
151
338
  };
152
-
339
+ node._gateway_node.on('send_manifest', (manifest_data) => {
340
+ node.send({
341
+ topic: 'sensor_manifest',
342
+ payload: {
343
+ addr: manifest_data.addr,
344
+ sensor_type: manifest_data.sensor_type,
345
+ manifest: manifest_data.data
346
+ },
347
+ time: Date.now()
348
+ });
349
+ });
153
350
  node.on('input', function(msg){
154
351
  switch(msg.topic){
155
352
  case "route_trace":
@@ -187,7 +384,133 @@ module.exports = function(RED) {
187
384
  // if(msg.topic == "fidelity_test"){
188
385
  // }
189
386
  });
387
+ node._gateway_node.on('send_firmware_stats', (data) => {
388
+ node.send({
389
+ topic: 'update_stats',
390
+ payload: data.state,
391
+ addr: data.addr,
392
+ time: Date.now()
393
+ });
394
+ });
395
+ node.on('input', function(msg){
396
+ switch(msg.topic){
397
+ case "route_trace":
398
+ var opts = {trace:1};
399
+ node.gateway.route_discover(msg.payload.address,opts).then().catch(console.log);
400
+ break;
401
+ case "link_test":
402
+ node.gateway.link_test(msg.payload.source_address,msg.payload.destination_address,msg.payload.options);
403
+ break;
404
+ case "fidelity_test":
405
+ break;
406
+ case "add_firmware_file":
407
+ // Parse Manifest to grab information and store it for later use
408
+ // msg.payload = [0x01, 0x00, ...]
409
+ let new_msg = {
410
+ topic: 'add_firmware_file_response',
411
+ payload: node._gateway_node._parse_manifest(msg.payload)
412
+ }
413
+ let firmware_dir = home_dir()+'/.node-red/node_modules/@ncd-io/node-red-enterprise-sensors/firmware_files';
414
+ if (!fs.existsSync(firmware_dir)) {
415
+ fs.mkdirSync(firmware_dir);
416
+ };
417
+ let filename = '/' + new_msg.payload.device_type + '-' + new_msg.payload.hardware_id[0] + '_' + new_msg.payload.hardware_id[1] + '_' + new_msg.payload.hardware_id[2] + '.ncd';
418
+ fs.writeFile(firmware_dir+filename, msg.payload, function(err){
419
+ if(err){
420
+ console.log(err);
421
+ };
422
+ console.log('Success');
423
+ });
424
+ node.send(new_msg);
425
+ break;
426
+ // case "get_firmware_file":
427
+ // Commented out as I'd rather use a flow to request the file. More robust. Maybe more complicated, wait for feedback.
428
+ // // This input makes a request to the specified url and downloads a firmware file at that location
429
+ // // msg.payload = "https://github.com/ncd-io/WiFi_MQTT_Temperature_Firmware/raw/main/v1.0.3/firmware.bin"
430
+
431
+ case "check_firmware_file":
432
+ // Read file that should be at location and spit out the binary
433
+ // Example msg.payload
434
+ // msg.payload = {
435
+ // device_type: 80,
436
+ // hardware_id: [88, 88, 88]
437
+ // }
438
+ break;
439
+ case "ota_firmware_update_single":
440
+ // msg.payload = {
441
+ // 'address': "00:13:a2:00:42:2c:d2:aa"
442
+ // }
443
+ if(!Object.hasOwn(node._gateway_node.sensor_list, msg.payload)){
444
+ node._gateway_node.sensor_list[msg.payload] = {};
445
+ };
446
+ if(!Object.hasOwn(node._gateway_node.sensor_list[msg.payload], 'update_request')){
447
+ node._gateway_node.sensor_list[msg.payload].update_request = true;
448
+ };
449
+ break;
450
+ case "ota_firmware_update_multiple":
451
+ // set the devices user wants to upload new firmware to
452
+ // msg.payload = {
453
+ // 'addresses': [
454
+ // "00:13:a2:00:42:2c:d2:aa",
455
+ // "00:13:a2:00:42:2c:d2:ab"
456
+ // ];
457
+ // }
458
+ // TODO unfinished
459
+ msg.payload.addresses.forEach((address) => {
460
+ if(!Object.hasOwn(node._gateway_node.sensor_list, msg.payload.address)){
461
+ node._gateway_node.sensor_list[address] = {};
462
+ };
463
+ if(!Object.hasOwn(node._gateway_node.sensor_list[msg.payload.address], 'update_request')){
464
+ node._gateway_node.sensor_list[address].update_request = true;
465
+ };
466
+ });
467
+ break;
468
+ case "get_manifest":
469
+ // Allows user to request manifest from one or more devices
470
+ // Primarily envisioned used for troubleshooting or engineer determination
471
+ // msg.payload = {
472
+ // 'addresses': [
473
+ // "00:13:a2:00:42:2c:d2:aa",
474
+ // "00:13:a2:00:42:2c:d2:ab"
475
+ // ];
476
+ // }
477
+ // OR
478
+ // msg.payload = {
479
+ // 'address': "00:13:a2:00:42:2c:d2:aa"
480
+ // }
481
+ break;
482
+ default:
483
+ const byteArrayToHexString = byteArray => Array.from(msg.payload.address, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
484
+ node.gateway.control_send(msg.payload.address, msg.payload.data, msg.payload.options).then().catch(console.log);
485
+ }
486
+
487
+
488
+ // console.log("input triggered, topic:"+msg.topic);
489
+ // if(msg.topic == "transmit"){
490
+ // const byteArrayToHexString = byteArray => Array.from(msg.payload.address, byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
491
+ // node.gateway.control_send(msg.payload.address, msg.payload.data, msg.payload.options).then().catch(console.log);
492
+ // }
493
+ // if(msg.topic == "route_trace"){
494
+ // var opts = {trace:1};
495
+ // node.gateway.route_discover(msg.payload.address,opts).then().catch(console.log);
496
+ // }
497
+ // if(msg.topic == "link_test"){
498
+ // node.gateway.link_test(msg.payload.source_address,msg.payload.destination_address,msg.payload.options);
499
+ // }
500
+ // if(msg.topic == "fft_request"){
190
501
 
502
+ // }
503
+ // if(msg.topic == "fidelity_test"){
504
+ // }
505
+ });
506
+ node.gateway.on('ncd_error', (data) => {
507
+ node.send({
508
+ topic: 'ncd_error',
509
+ data: data,
510
+ payload: data.error,
511
+ time: Date.now()
512
+ });
513
+ });
191
514
  node.gateway.on('sensor_data', (d) => {
192
515
  node.set_status();
193
516
  node.send({topic: 'sensor_data', payload: d, time: Date.now()});
@@ -237,7 +560,7 @@ module.exports = function(RED) {
237
560
  this.config_gateway = this.config_gateway_node.gateway;
238
561
  dedicated_config = true;
239
562
  }
240
- this.queue = new Queue(1);
563
+ // this.queue = new Queue(1);
241
564
  var node = this;
242
565
  var modes = {
243
566
  PGM: {fill:"red",shape:"dot",text:"Config Mode"},
@@ -247,6 +570,7 @@ module.exports = function(RED) {
247
570
  RUN: {fill:"green",shape:"dot",text:"Running"},
248
571
  PUM: {fill:"yellow",shape:"ring",text:"Module was factory reset"},
249
572
  ACK: {fill:"green",shape:"ring",text:"Configuration Acknowledged"},
573
+ STREAM_ERR: {fill:"red",shape:"ring",text:"Multi-Packet Stream Error"},
250
574
  // FLY: {fill:"yellow",shape:"ring",text:"FLY notification received"},
251
575
  // OTN: {fill:"yellow",shape:"ring",text:"OTN Received, OTF Configuration Initiated"},
252
576
  // OFF: {fill:"green",shape:"dot",text:"OFF Recieved, OTF Configuration Completed"}
@@ -498,6 +822,21 @@ module.exports = function(RED) {
498
822
  }
499
823
  var interr = parseInt(config.activ_interr_x) | parseInt(config.activ_interr_y) | parseInt(config.activ_interr_z) | parseInt(config.activ_interr_op);
500
824
  promises.activity_interrupt = node.config_gateway.config_set_interrupt_24(mac, interr);
825
+ case 25:
826
+ if(config.impact_accel_active){
827
+ promises.impact_accel = node.config_gateway.config_set_acceleration_range_24(mac, parseInt(config.impact_accel));
828
+ }
829
+ if(config.impact_data_rate_active){
830
+ promises.impact_data_rate = node.config_gateway.config_set_data_rate_24(mac, parseInt(config.impact_data_rate));
831
+ }
832
+ if(config.impact_threshold_active){
833
+ promises.impact_threshold = node.config_gateway.config_set_threshold_24(mac, parseInt(config.impact_threshold));
834
+ }
835
+ if(config.impact_duration_active){
836
+ promises.impact_duration = node.config_gateway.config_set_duration_24(mac, parseInt(config.impact_duration));
837
+ }
838
+ var interr = parseInt(config.activ_interr_x) | parseInt(config.activ_interr_y) | parseInt(config.activ_interr_z) | parseInt(config.activ_interr_op);
839
+ promises.activity_interrupt = node.config_gateway.config_set_interrupt_24(mac, interr);
501
840
  case 35:
502
841
  if(config.counter_threshold_35_active){
503
842
  promises.config_set_counter_threshold_35 = node.config_gateway.config_set_counter_threshold_35(mac, parseInt(config.counter_threshold_35));
@@ -1600,3 +1939,4 @@ function toHex(n){return ('00' + n.toString(16)).substr(-2);}
1600
1939
  function toMac(arr){
1601
1940
  return arr.reduce((h,c,i) => {return ((i==1?toHex(h):h)+':'+toHex(c)).toUpperCase();});
1602
1941
  }
1942
+ function msbLsb(m,l){return (m<<8)+l;};