@bitpoolos/edge-bacnet 1.1.1 → 1.1.4

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/bacnet_client.js CHANGED
@@ -96,6 +96,7 @@ class BacnetClient extends EventEmitter {
96
96
 
97
97
  setTimeout(() => {
98
98
  that.queryDevices();
99
+ that.sanitizeDeviceList();
99
100
  }, "5000")
100
101
 
101
102
  } catch(e) {
@@ -132,7 +133,6 @@ class BacnetClient extends EventEmitter {
132
133
  newBacnetDevice.setLastSeen(Date.now());
133
134
  that.updateDeviceName(newBacnetDevice);
134
135
  that.deviceList.push(newBacnetDevice);
135
-
136
136
  } else if(foundIndex !== -1) {
137
137
  that.deviceList[foundIndex].updateDeviceConfig(device);
138
138
  that.deviceList[foundIndex].setLastSeen(Date.now());
@@ -189,7 +189,6 @@ class BacnetClient extends EventEmitter {
189
189
  .acquire()
190
190
  .then(function(release) {
191
191
  try {
192
-
193
192
  that.getDevicePointList(device).then(function() {
194
193
  that.buildJsonObject(device).then(function() {
195
194
  release();
@@ -208,7 +207,6 @@ class BacnetClient extends EventEmitter {
208
207
  });
209
208
  release();
210
209
  });
211
-
212
210
  } catch(e) {
213
211
  that.logOut("Error while querying devices: ", e);
214
212
  release();
@@ -220,30 +218,38 @@ class BacnetClient extends EventEmitter {
220
218
 
221
219
  sanitizeDeviceList() {
222
220
  let that = this;
221
+
222
+ //1 hour in seconds
223
+ let timeoutThreshold = 3600;
224
+
225
+ that.renderList.forEach(function(item, index) {
226
+ if(((Date.now() - item.lastSeen) / 1000) > timeoutThreshold) {
227
+ //render item hasnt responded to whoIs for over an hour
223
228
 
224
- that.deviceList.forEach(function(device, index) {
225
- if(((Date.now() - device.getLastSeen()) / 1000) > 3600) {
226
- //device hasnt responded to whoIs for over an hour
229
+ let deviceIndex = that.deviceList.findIndex(ele => ele.deviceId == item.deviceId);
230
+ let device = that.deviceList[deviceIndex];
231
+
232
+ let ipAddr = typeof device.getAddress() == "object" ? device.getAddress().address : device.getAddress();
233
+ let deviceKey = ipAddr + "-" + device.getDeviceId();
227
234
 
228
- let deviceKey = (typeof device.getAddress() == "object") ? device.getAddress().address + "-" + device.getDeviceId() : device.getAddress() + "-" + device.getDeviceId();
229
235
  delete that.networkTree[deviceKey];
230
236
 
231
- if(that.renderList){
232
- let foundIndex = that.renderList.findIndex(ele => ele.ipAddr == device.getAddress() && ele.deviceId == device.getDeviceId());
233
- if(foundIndex !== -1) {
234
- that.renderList.splice(foundIndex, 1);
235
- }
237
+ if(((Date.now() - device.getLastSeen()) / 1000) > timeoutThreshold) {
238
+ that.deviceList.splice(deviceIndex, 1);
236
239
  }
237
240
 
238
- that.deviceList.splice(index, 1);
241
+ that.renderList.splice(index, 1);
239
242
  }
240
243
  });
244
+
241
245
  }
242
246
 
243
247
  updateDeviceName(device) {
244
248
  let that = this;
245
249
  that._getDeviceName(device.getAddress(), device.getDeviceId()).then(function(deviceName) {
246
- device.setDeviceName(deviceName);
250
+ if(typeof deviceName == "string") {
251
+ device.setDeviceName(deviceName);
252
+ }
247
253
  });
248
254
  }
249
255
 
@@ -322,20 +328,22 @@ class BacnetClient extends EventEmitter {
322
328
  let bacnetResults = {};
323
329
  devicesToRead.forEach(function(key, index) {
324
330
  let device = that.deviceList.find(ele => `${that.getDeviceAddress(ele)}-${ele.getDeviceId()}` == key);
325
- let deviceName = device.getDeviceName();
326
- let deviceKey = (typeof device.getAddress() == "object") ? device.getAddress().address + "-" + device.getDeviceId() : device.getAddress() + "-" + device.getDeviceId();
327
- let deviceObject = that.networkTree[deviceKey];
328
- if(!bacnetResults[deviceName]) bacnetResults[deviceName] = {};
329
- if(deviceObject) {
330
- for(const pointName in readConfig.pointsToRead[key]) {
331
- let bac_obj = that.getObjectType(readConfig.pointsToRead[key][pointName].objectID.type);
332
- let objectId = pointName + "_" + bac_obj + '_' + readConfig.pointsToRead[key][pointName].objectID.instance;
333
- let point = deviceObject[objectId];
334
- bacnetResults[deviceName][pointName] = point;
331
+ if(device) {
332
+ let deviceName = device.getDeviceName();
333
+ let deviceKey = (typeof device.getAddress() == "object") ? device.getAddress().address + "-" + device.getDeviceId() : device.getAddress() + "-" + device.getDeviceId();
334
+ let deviceObject = that.networkTree[deviceKey];
335
+ if(!bacnetResults[deviceName]) bacnetResults[deviceName] = {};
336
+ if(deviceObject) {
337
+ for(const pointName in readConfig.pointsToRead[key]) {
338
+ let bac_obj = that.getObjectType(readConfig.pointsToRead[key][pointName].meta.objectId.type);
339
+ let objectId = pointName + "_" + bac_obj + '_' + readConfig.pointsToRead[key][pointName].meta.objectId.instance;
340
+ let point = deviceObject[objectId];
341
+ bacnetResults[deviceName][pointName] = point;
342
+ }
335
343
  }
336
344
  }
337
345
 
338
- if(index == devicesToRead.length - 1) that.emit('values', bacnetResults, outputType, objectPropertyType);
346
+ if(index == devicesToRead.length - 1 && Object.keys(readConfig.pointsToRead).length > 0) that.emit('values', bacnetResults, outputType, objectPropertyType);
339
347
  });
340
348
  } catch(e) {
341
349
  that.logOut("Issue doing read, see error: ", e);
@@ -353,111 +361,6 @@ class BacnetClient extends EventEmitter {
353
361
  }
354
362
  }
355
363
 
356
- readDeviceAndEmitJSON(readPromiseArray, device, outputType, propertiesToRead, objectPropertyType, msgId) {
357
- let that = this;
358
- let deviceName = device.getDeviceName();
359
-
360
- let bacnetResults = {
361
- [deviceName]: []
362
- };
363
-
364
- try{
365
- Promise.all(readPromiseArray).then((result) => {
366
- let values = {};
367
-
368
- // remove errors and map to result element
369
- let successfulResults = result.filter(element => !element.error).map(element => element.value);
370
- successfulResults.forEach(element => {
371
- try {
372
- element.values.forEach(function(point){
373
- point.values.forEach(function(object) {
374
- let toReadProperty = propertiesToRead.findIndex(ele => ele.id == object.id);
375
- let objectName = that._findValueById(point.values, baEnum.PropertyIdentifier.OBJECT_NAME);
376
- //checks for error code json structure, returned for invalid bacnet requests
377
- if(!object.value.value && toReadProperty !== -1 && objectName !== "") {
378
- var currobjectId = point.objectId.type
379
- let bac_obj = that.getObjectType(currobjectId);
380
- let objectId;
381
- objectId = objectName;
382
-
383
- //init json object
384
- if(!values[objectId]) values[objectId] = {};
385
-
386
- switch(object.id) {
387
- case baEnum.PropertyIdentifier.PRESENT_VALUE:
388
- if(object.value[0] &&
389
- object.value[0].value !== "undefined" &&
390
- object.value[0].value !== null &&
391
- typeof object.value[0].value == "number") {
392
- values[objectId].presentValue = roundDecimalPlaces(object.value[0].value, that.roundDecimal);
393
- } else if(object.value[0] &&
394
- object.value[0].value !== "undefined" &&
395
- object.value[0].value !== null &&
396
- typeof object.value[0].value == "string") {
397
- values[objectId].presentValue = object.value[0].value;
398
- }
399
- break;
400
- case baEnum.PropertyIdentifier.DESCRIPTION:
401
- if(object.value[0]) values[objectId].description = object.value[0].value;
402
- break;
403
- case baEnum.PropertyIdentifier.STATUS_FLAGS:
404
- if(object.value[0] && object.value[0].value) values[objectId].statusFlags = that.getStatusFlags(object);
405
- break;
406
- case baEnum.PropertyIdentifier.RELIABILITY:
407
- if(object.value[0]) values[objectId].reliability = that.getPROP_RELIABILITY(object.value[0].value);
408
- break;
409
- case baEnum.PropertyIdentifier.OUT_OF_SERVICE:
410
- if(object.value[0]) values[objectId].outOfService = object.value[0].value;
411
- break;
412
- case baEnum.PropertyIdentifier.UNITS:
413
- if(object.value[0] && object.value[0].value) values[objectId].units = getUnit(object.value[0].value);
414
- break;
415
- case baEnum.PropertyIdentifier.OBJECT_NAME:
416
- if(object.value[0] && object.value[0].value) values[objectId].objectName = object.value[0].value;
417
- break;
418
- case baEnum.PropertyIdentifier.SYSTEM_STATUS:
419
- if(object.value[0]){
420
- values[objectId].systemStatus = that.getPROP_SYSTEM_STATUS(object.value[0].value);
421
- }
422
- break;
423
- case baEnum.PropertyIdentifier.MODIFICATION_DATE:
424
- if(object.value[0]) {
425
- values[objectId].modificationDate = object.value[0].value;
426
- }
427
- break;
428
- case baEnum.PropertyIdentifier.PROGRAM_STATE:
429
- if(object.value[0]){
430
- values[objectId].programState = that.getPROP_PROGRAM_STATE(object.value[0].value);
431
- }
432
- break;
433
- case baEnum.PropertyIdentifier.RECORD_COUNT:
434
- if(object.value[0] ) {
435
- values[objectId].recordCount = object.value[0].value;
436
- }
437
- break;
438
- }
439
- }
440
- });
441
- });
442
- bacnetResults[deviceName] = values;
443
-
444
- } catch(e) {
445
- that.logOut("issue resolving bacnet payload, see error: ", e);
446
- }
447
- });
448
- if(Object.keys(bacnetResults[deviceName]).length !== 0) {
449
- that.emit('values', bacnetResults, outputType, objectPropertyType);
450
- }
451
-
452
- }).catch(function (error) {
453
- logger.log('error', `Error while fetching values: ${error}`);
454
- });
455
-
456
- } catch(e){
457
- that.logOut("Issue reading from device, see error: ", e);
458
- }
459
- }
460
-
461
364
  _getDeviceName(address, deviceId) {
462
365
  let that = this;
463
366
  return new Promise((resolve, reject) => {
@@ -929,7 +832,7 @@ class BacnetClient extends EventEmitter {
929
832
  let isMstpDevice = deviceInfo.getIsMstpDevice();
930
833
  let manualDiscoveryMode = deviceInfo.getManualDiscoveryMode();
931
834
 
932
- if(deviceObject) {
835
+ if(deviceObject && typeof deviceName !== "object") {
933
836
  let children = [];
934
837
  let pointIndex = 0;
935
838
 
@@ -982,7 +885,7 @@ class BacnetClient extends EventEmitter {
982
885
  children.push({"key": `${index}-${pointIndex}`, "label": displayName, "data": displayName, "pointName": pointName, "icon": that.getPointIcon(values.meta.objectId.type), "children": pointProperties, "type": "point", "parentDevice": deviceName, "showAdded": false, "bacnetType": values.meta.objectId.type})
983
886
  pointIndex++;
984
887
  }
985
- let foundIndex = that.renderList.findIndex(ele => ele.key == index && ele.deviceId == deviceId);
888
+ let foundIndex = that.renderList.findIndex(ele => ele.deviceId == deviceId && ele.ipAddr == ipAddr);
986
889
  if(foundIndex !== -1) {
987
890
  that.renderList[foundIndex] = {"key": index, "label": deviceName, "data": deviceName, "icon": that.getDeviceIcon(isMstpDevice, manualDiscoveryMode), "children": children.sort(that.sortPoints), "type": "device", "lastSeen": deviceInfo.getLastSeen(), "showAdded": false, "ipAddr": ipAddr, "deviceId": deviceId, "isMstpDevice": isMstpDevice};
988
891
  } else if(foundIndex == -1) {
@@ -996,7 +899,7 @@ class BacnetClient extends EventEmitter {
996
899
  resolve({renderList: that.renderList, deviceList: that.deviceList, pointList: that.networkTree, pollFrequency: that.discover_polling_schedule});
997
900
  }
998
901
  }
999
-
902
+
1000
903
  release();
1001
904
  });
1002
905
  });
@@ -1074,94 +977,91 @@ class BacnetClient extends EventEmitter {
1074
977
  let objectName = that._findValueById(pointProperty.values, baEnum.PropertyIdentifier.OBJECT_NAME);
1075
978
  let objectType = that._findValueById(pointProperty.values, baEnum.PropertyIdentifier.OBJECT_TYPE);
1076
979
  let objectId;
1077
- if(objectName !== null) {
980
+ if(objectName !== null && typeof objectName == "string") {
1078
981
  objectId = objectName + "_" + bac_obj + '_' + pointProperty.objectId.instance;
1079
- } else {
1080
- objectId = bac_obj + '_' + pointProperty.objectId.instance;
1081
- }
1082
- try {
1083
- pointProperty.values.forEach(function(object, objectIndex) {
1084
- //checks for error code json structure, returned for invalid bacnet requests
1085
- //if(!object.value.value && !object.value[0].value.errorClass && !object.value.errorClass) {
1086
- if(object && object.value && !object.value.errorClass) {
1087
-
1088
-
1089
- if(!values[objectId]) values[objectId] = {};
1090
- values[objectId].meta = {
1091
- objectId: pointProperty.objectId
1092
- };
1093
-
1094
- switch(object.id) {
1095
- case baEnum.PropertyIdentifier.PRESENT_VALUE:
1096
- if(object.value[0] && object.value[0].value !== "undefined" && object.value[0].value !== null) {
1097
- //check for binary object type
1098
- if(objectType == 3 || objectType == 4 || objectType == 5) {
1099
- if(object.value[0].value == 0) {
1100
- values[objectId].presentValue = false;
1101
- } else if(object.value[0].value == 1) {
1102
- values[objectId].presentValue = true;
982
+
983
+ try {
984
+ pointProperty.values.forEach(function(object, objectIndex) {
985
+ //checks for error code json structure, returned for invalid bacnet requests
986
+ if(object && object.value && !object.value.errorClass) {
987
+
988
+ if(!values[objectId]) values[objectId] = {};
989
+ values[objectId].meta = {
990
+ objectId: pointProperty.objectId
991
+ };
992
+
993
+ switch(object.id) {
994
+ case baEnum.PropertyIdentifier.PRESENT_VALUE:
995
+ if(object.value[0] && object.value[0].value !== "undefined" && object.value[0].value !== null) {
996
+ //check for binary object type
997
+ if(objectType == 3 || objectType == 4 || objectType == 5) {
998
+ if(object.value[0].value == 0) {
999
+ values[objectId].presentValue = false;
1000
+ } else if(object.value[0].value == 1) {
1001
+ values[objectId].presentValue = true;
1002
+ }
1003
+ } else if(objectType == 40) {
1004
+ //character string
1005
+ values[objectId].presentValue = object.value[0].value;
1006
+ } else {
1007
+ values[objectId].presentValue = roundDecimalPlaces(object.value[0].value, 2);
1103
1008
  }
1104
- } else if(objectType == 40) {
1105
- //character string
1106
- values[objectId].presentValue = object.value[0].value;
1107
- } else {
1108
- values[objectId].presentValue = roundDecimalPlaces(object.value[0].value, 2);
1009
+ }
1010
+ values[objectId].meta.arrayIndex = object.index;
1011
+ break;
1012
+ case baEnum.PropertyIdentifier.DESCRIPTION:
1013
+ if(object.value[0]) values[objectId].description = object.value[0].value;
1014
+ break;
1015
+ case baEnum.PropertyIdentifier.UNITS:
1016
+ if(object.value[0] && object.value[0].value) values[objectId].units = getUnit(object.value[0].value);
1017
+ break;
1018
+ case baEnum.PropertyIdentifier.OBJECT_NAME:
1019
+ if(object.value[0] && object.value[0].value) values[objectId].objectName = object.value[0].value;
1020
+ break;
1021
+ case baEnum.PropertyIdentifier.OBJECT_TYPE:
1022
+ if(object.value[0] && object.value[0].value) values[objectId].objectType = object.value[0].value;
1023
+ break;
1024
+ case baEnum.PropertyIdentifier.OBJECT_IDENTIFIER:
1025
+ if(object.value[0] && object.value[0].value) values[objectId].objectID = object.value[0].value;
1026
+ break;
1027
+ case baEnum.PropertyIdentifier.PROPERTY_LIST:
1028
+ if(object.value) values[objectId].propertyList = that.mapPropsToArray(object.value);
1029
+ break;
1030
+
1031
+ case baEnum.PropertyIdentifier.SYSTEM_STATUS:
1032
+ if(object.value[0]){
1033
+ values[objectId].systemStatus = that.getPROP_SYSTEM_STATUS(object.value[0].value);
1034
+ }
1035
+ break;
1036
+
1037
+ case baEnum.PropertyIdentifier.MODIFICATION_DATE:
1038
+ if(object.value[0]) {
1039
+ values[objectId].modificationDate = object.value[0].value;
1109
1040
  }
1110
- }
1111
- values[objectId].meta.arrayIndex = object.index;
1112
- break;
1113
- case baEnum.PropertyIdentifier.DESCRIPTION:
1114
- if(object.value[0]) values[objectId].description = object.value[0].value;
1115
- break;
1116
- case baEnum.PropertyIdentifier.UNITS:
1117
- if(object.value[0] && object.value[0].value) values[objectId].units = getUnit(object.value[0].value);
1118
- break;
1119
- case baEnum.PropertyIdentifier.OBJECT_NAME:
1120
- if(object.value[0] && object.value[0].value) values[objectId].objectName = object.value[0].value;
1121
- break;
1122
- case baEnum.PropertyIdentifier.OBJECT_TYPE:
1123
- if(object.value[0] && object.value[0].value) values[objectId].objectType = object.value[0].value;
1124
- break;
1125
- case baEnum.PropertyIdentifier.OBJECT_IDENTIFIER:
1126
- if(object.value[0] && object.value[0].value) values[objectId].objectID = object.value[0].value;
1127
- break;
1128
- case baEnum.PropertyIdentifier.PROPERTY_LIST:
1129
- if(object.value) values[objectId].propertyList = that.mapPropsToArray(object.value);
1130
- break;
1041
+ break;
1131
1042
 
1132
- case baEnum.PropertyIdentifier.SYSTEM_STATUS:
1133
- if(object.value[0]){
1134
- values[objectId].systemStatus = that.getPROP_SYSTEM_STATUS(object.value[0].value);
1135
- }
1136
- break;
1137
-
1138
- case baEnum.PropertyIdentifier.MODIFICATION_DATE:
1139
- if(object.value[0]) {
1140
- values[objectId].modificationDate = object.value[0].value;
1141
- }
1142
- break;
1143
-
1144
- case baEnum.PropertyIdentifier.PROGRAM_STATE:
1145
- if(object.value[0]){
1146
- values[objectId].programState = that.getPROP_PROGRAM_STATE(object.value[0].value);
1147
- }
1148
- break;
1149
-
1150
- case baEnum.PropertyIdentifier.RECORD_COUNT:
1151
- if(object.value[0] ) {
1152
- values[objectId].recordCount = object.value[0].value;
1153
- }
1154
- break;
1043
+ case baEnum.PropertyIdentifier.PROGRAM_STATE:
1044
+ if(object.value[0]){
1045
+ values[objectId].programState = that.getPROP_PROGRAM_STATE(object.value[0].value);
1046
+ }
1047
+ break;
1048
+
1049
+ case baEnum.PropertyIdentifier.RECORD_COUNT:
1050
+ if(object.value[0] ) {
1051
+ values[objectId].recordCount = object.value[0].value;
1052
+ }
1053
+ break;
1054
+ }
1155
1055
  }
1156
- }
1157
- if(pointPropertyIndex == successfulResult.values.length - 1 && objectIndex == pointProperty.values.length - 1 && i == fullObjects.length - 1) {
1158
- that.networkTree[deviceKey] = values;
1159
- resolve(that.networkTree);
1160
- }
1161
- });
1162
- } catch(e) {
1163
- that.logOut("issue resolving bacnet payload, see error: ", e);
1164
- reject(e);
1056
+ if(pointPropertyIndex == successfulResult.values.length - 1 && objectIndex == pointProperty.values.length - 1 && i == fullObjects.length - 1) {
1057
+ that.networkTree[deviceKey] = values;
1058
+ resolve(that.networkTree);
1059
+ }
1060
+ });
1061
+ } catch(e) {
1062
+ that.logOut("issue resolving bacnet payload, see error: ", e);
1063
+ reject(e);
1064
+ }
1165
1065
  }
1166
1066
  });
1167
1067
  } else {
@@ -474,10 +474,13 @@
474
474
 
475
475
  <h3><strong>Examples</strong></h3>
476
476
  <p>For example flows, please use the examples section for this node. These examples can be found at: Node-red hamburger menu on top right -> Import -> Examples -> @bitpoolos/edge-bacnet</p>
477
- <p>To find screen shot examples of settings and flows, please go to our wiki <a href="https://wiki.bitpool.com/en/edge/apps/bitpool-edge/nr-bacnet">here</a></p>
477
+ <p>To find captured examples of settings and flows, please go to our wiki <a href="https://wiki.bitpool.com/en/edge/apps/bitpool-edge/nr-bacnet">here</a></p>
478
478
 
479
479
 
480
480
  <h3>Resources:</h3>
481
+
482
+ <p><a href="https://youtu.be/4K7mVxfvfbc">Video Walk-through </a></p>
483
+
481
484
  <h4><strong>Online Docs:</strong></h4>
482
485
  <ul type="1">
483
486
  <li><a href="https://www.bitpool.com/">bitpool.com</a> - check us out here.</li>
package/bacnet_gateway.js CHANGED
@@ -304,23 +304,26 @@ module.exports = function (RED) {
304
304
  if(device !== "_msgid") {
305
305
  let points = values[device];
306
306
  for(var point in points) {
307
- let pointProps = Object.keys(points[point]);
308
- pointProps.forEach(function(prop) {
309
- let msg = {};
310
- if(prop == "presentValue") {
311
- if(node.nodeName !== "gateway" &&
312
- node.nodeName !== "" &&
313
- node.nodeName !== "null" &&
314
- node.nodeName !== "undefined" &&
315
- typeof node.nodeName == "string") {
316
- msg.topic = `${node.nodeName}/${device}/${point}`;
317
- } else {
318
- msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${point}`;
307
+ if(points[point]){
308
+ let pointProps = Object.keys(points[point]);
309
+ pointProps.forEach(function(prop) {
310
+ let msg = {};
311
+ if(prop == "presentValue") {
312
+ if(node.nodeName !== "gateway" &&
313
+ node.nodeName !== "" &&
314
+ node.nodeName !== "null" &&
315
+ node.nodeName !== "undefined" &&
316
+ typeof node.nodeName == "string") {
317
+ msg.topic = `${node.nodeName}/${device}/${point}`;
318
+ } else {
319
+ msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${point}`;
320
+ }
321
+ msg.payload = points[point][prop];
322
+ node.send(msg);
319
323
  }
320
- msg.payload = points[point][prop];
321
- node.send(msg);
322
- }
323
- });
324
+ });
325
+
326
+ }
324
327
  }
325
328
  }
326
329
  });
@@ -333,23 +336,25 @@ module.exports = function (RED) {
333
336
  if(device !== "_msgid") {
334
337
  let points = values[device];
335
338
  for(var point in points) {
336
- let pointProps = Object.keys(points[point]);
337
- pointProps.forEach(function(prop) {
338
- let msg = {};
339
- if(prop !== "objectName") {
340
- if(node.nodeName !== "gateway" &&
341
- node.nodeName !== "" &&
342
- node.nodeName !== "null" &&
343
- node.nodeName !== "undefined" &&
344
- typeof node.nodeName == "string") {
345
- msg.topic = `${node.nodeName}/${device}/${point}/${prop}`;
346
- } else {
347
- msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${point}/${prop}`;
339
+ if(points[point]){
340
+ let pointProps = Object.keys(points[point]);
341
+ pointProps.forEach(function(prop) {
342
+ let msg = {};
343
+ if(prop !== "objectName") {
344
+ if(node.nodeName !== "gateway" &&
345
+ node.nodeName !== "" &&
346
+ node.nodeName !== "null" &&
347
+ node.nodeName !== "undefined" &&
348
+ typeof node.nodeName == "string") {
349
+ msg.topic = `${node.nodeName}/${device}/${point}/${prop}`;
350
+ } else {
351
+ msg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${point}/${prop}`;
352
+ }
353
+ msg.payload = points[point][prop];
354
+ node.send(msg);
348
355
  }
349
- msg.payload = points[point][prop];
350
- node.send(msg);
351
- }
352
- });
356
+ });
357
+ }
353
358
  }
354
359
  }
355
360
  });
@@ -358,22 +363,37 @@ module.exports = function (RED) {
358
363
  sendSimpleJson = function(values) {
359
364
  let devices = Object.keys(values);
360
365
  devices.forEach(function(device) {
366
+ let msgg = {};
361
367
  if(device !== "_msgid") {
362
368
  let value = {
363
369
  [device]: {}
364
370
  };
365
371
  let points = values[device];
372
+
366
373
  for(var point in points) {
367
- let pointProps = Object.keys(points[point]);
368
- pointProps.forEach(function(prop) {
369
- if(prop == "presentValue") {
370
- value[device][point] = {
371
- "presentValue": points[point][prop]
372
- };
373
- }
374
- });
374
+ if(points[point]){
375
+ let pointProps = Object.keys(points[point]);
376
+ pointProps.forEach(function(prop) {
377
+ if(prop == "presentValue") {
378
+ value[device][point] = {
379
+ "presentValue": points[point][prop]
380
+ };
381
+ }
382
+ });
383
+ }
384
+
385
+ }
386
+ if(node.nodeName !== "gateway" &&
387
+ node.nodeName !== "" &&
388
+ node.nodeName !== "null" &&
389
+ node.nodeName !== "undefined" &&
390
+ typeof node.nodeName == "string") {
391
+ msgg.topic = `${node.nodeName}/${device}`;
392
+ } else {
393
+ msgg.topic = `BITPOOL_BACNET_GATEWAY/${device}`;
375
394
  }
376
- node.send(value);
395
+ msgg.payload = value[device];
396
+ node.send(msgg);
377
397
  }
378
398
  });
379
399
  };
package/bacnet_read.html CHANGED
@@ -210,7 +210,7 @@
210
210
  //force a deploy state
211
211
  node.hiddenDeployToggle = !node.prevHiddenToggleState;
212
212
 
213
- } catch(e){
213
+ } catch(e) {
214
214
  console.log("removeAllClicked error: ", e);
215
215
  }
216
216
 
@@ -849,7 +849,17 @@
849
849
 
850
850
  </ol>
851
851
 
852
+ <h3><strong>Examples</strong></h3>
853
+ <p>For example flows, please use the examples section for this node. These examples can be found at: Node-red hamburger menu on top right -> Import -> Examples -> @bitpoolos/edge-bacnet</p>
854
+ <p>To find captured examples of settings and flows, please go to our wiki <a href="https://wiki.bitpool.com/en/edge/apps/bitpool-edge/nr-bacnet">here</a></p>
855
+
856
+
857
+
858
+
852
859
  <h3>Resources:</h3>
860
+
861
+ <p><a href="https://youtu.be/4K7mVxfvfbc">Video Walk-through </a></p>
862
+
853
863
  <h4><strong>Online Docs:</strong></h4>
854
864
  <ul type="1">
855
865
  <li><a href="https://www.bitpool.com/">bitpool.com</a> - check us out here.</li>
package/bacnet_write.html CHANGED
@@ -634,7 +634,13 @@
634
634
 
635
635
  </ol>
636
636
 
637
+ <h3><strong>Examples</strong></h3>
638
+ <p>For example flows, please use the examples section for this node. These examples can be found at: Node-red hamburger menu on top right -> Import -> Examples -> @bitpoolos/edge-bacnet</p>
639
+ <p>To find captured examples of settings and flows, please go to our wiki <a href="https://wiki.bitpool.com/en/edge/apps/bitpool-edge/nr-bacnet">here</a></p>
640
+
641
+
637
642
  <h3>Resources:</h3>
643
+ <p><a href="https://youtu.be/4K7mVxfvfbc">Video Walk-through </a></p>
638
644
  <h4><strong>Online Docs:</strong></h4>
639
645
  <ul type="1">
640
646
  <li><a href="https://www.bitpool.com/">bitpool.com</a> - check us out here.</li>
@@ -792,7 +792,13 @@
792
792
 
793
793
  </ol>
794
794
 
795
+ <h3><strong>Examples</strong></h3>
796
+ <p>For example flows, please use the examples section for this node. These examples can be found at: Node-red hamburger menu on top right -> Import -> Examples -> @bitpoolos/edge-bacnet</p>
797
+ <p>To find captured examples of settings and flows, please go to our wiki <a href="https://wiki.bitpool.com/en/edge/apps/bitpool-edge/nr-bacnet">here</a></p>
798
+
799
+
795
800
  <h3>Resources:</h3>
801
+ <p><a href="https://youtu.be/4K7mVxfvfbc">Video Walk-through </a></p>
796
802
  <h4><strong>Online Docs:</strong></h4>
797
803
  <ul type="1">
798
804
  <li><a href="https://www.bitpool.com/">bitpool.com</a> - check us out here.</li>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitpoolos/edge-bacnet",
3
- "version": "1.1.1",
3
+ "version": "1.1.4",
4
4
  "description": "A bacnet gateway for node-red",
5
5
  "dependencies": {
6
6
  "async-mutex": "^0.4.0",
@@ -18,8 +18,6 @@
18
18
  "Bacnet-Gateway": "bacnet_gateway.js",
19
19
  "Bacnet-Discovery": "bacnet_read.js",
20
20
  "Bacnet-Write": "bacnet_write.js",
21
- "Bitpool-Bacnet-Device": "bacnet_device.js",
22
- "Bitpool-Bacnet-Object": "bacnet_object.js",
23
21
  "Bitpool-Inject": "bitpool_inject.js"
24
22
  }
25
23
  },
@@ -1,131 +0,0 @@
1
- <!--
2
- MIT License Copyright 2021, 2022 - Bitpool Pty Ltd
3
- -->
4
-
5
- <script type="text/javascript">
6
- RED.nodes.registerType('Bitpool-Bacnet-Object',{
7
- category: 'config',
8
- color: '#00aeef',
9
- defaults: {
10
- name: {value:""},
11
- object_type_ai: {value: true},
12
- object_type_ao: {value: false},
13
- object_type_av: {value: false},
14
- object_type_bi: {value: false},
15
- object_type_bo: {value: false},
16
- object_type_bv: {value: false},
17
- object_type_mi: {value: false},
18
- object_type_mo: {value: false},
19
- object_type_mv: {value: false},
20
- object_property_presentVal: {value: true},
21
- object_property_objDescription: {value: false},
22
- object_property_statusFlag: {value: false},
23
- object_property_reliability: {value: false},
24
- object_property_outOfService: {value: false},
25
- object_property_units: {value: false},
26
- instance_start: {value: "", required: true},
27
- instance_end: {value: "", required: true}
28
- },
29
- inputs:1,
30
- outputs:1,
31
- icon: "icon.png",
32
- label: function() {
33
- return this.name||"Bitpool-Bacnet-Object";
34
- },
35
- oneditprepare: function() {
36
- }
37
- });
38
-
39
- </script>
40
-
41
- <script type="text/html" data-template-name="Bitpool-Bacnet-Object">
42
- <div class="form-row">
43
- <label for="node-config-input-name"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.name"></span> Name</label>
44
- <input type="text" id="node-config-input-name" placeholder="Config Name" style="margin-left: 45px; width: 350px;">
45
- </div>
46
-
47
- <div class="form-row" style="display: inline-flex; width: fit-content; align-items: center;">
48
- <label for="node-config-input-instance" ><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.instance"></span>Instance Range</label>
49
- <div id="node-config-input-instance">
50
- <label for="node-config-input-instance_start" style="flex-basis: content; width: 75px; padding-left: 45px;"> Start</label>
51
- <input type="text" id="node-config-input-instance_start" placeholder="101" style="width: 55px;">
52
-
53
- <label for="node-config-input-instance_end" style="flex-basis: content; width: 30px;"> End</label>
54
- <input type="text" id="node-config-input-instance_end" placeholder="102" style="width: 55px;">
55
-
56
- </div>
57
-
58
- </div>
59
-
60
- <br>
61
-
62
- <div class="form-row" style="display: inline-flex; width: fit-content; flex-wrap: nowrap;">
63
- <label for="node-config-input-object_type_group"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.object_type_group"></span> Object Type</label>
64
- <div id="node-config-input-object_type_group" style="display: flex; padding-left: 45px;">
65
- <label for="node-config-input-object_type_ai" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_type_ai"></span>AI
66
- <input type="checkbox" id="node-config-input-object_type_ai">
67
- </label>
68
-
69
- <label for="node-config-input-object_type_ao" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_type_ao"></span>AO
70
- <input type="checkbox" id="node-config-input-object_type_ao">
71
- </label>
72
-
73
- <label for="node-config-input-object_type_av" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_type_av"></span>AV
74
- <input type="checkbox" id="node-config-input-object_type_av">
75
- </label>
76
-
77
- <label for="node-config-input-object_type_bi" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_type_bi"></span>BI
78
- <input type="checkbox" id="node-config-input-object_type_bi">
79
- </label>
80
-
81
- <label for="node-config-input-object_type_bo" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_type_bo"></span>BO
82
- <input type="checkbox" id="node-config-input-object_type_bo">
83
- </label>
84
-
85
- <label for="node-config-input-object_type_bv" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_type_bv"></span>BV
86
- <input type="checkbox" id="node-config-input-object_type_bv">
87
- </label>
88
-
89
- <label for="node-config-input-object_type_mi" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_type_mi"></span>MI
90
- <input type="checkbox" id="node-config-input-object_type_mi">
91
- </label>
92
- <label for="node-config-input-object_type_mo" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_type_mo"></span>MO
93
- <input type="checkbox" id="node-config-input-object_type_mo">
94
- </label>
95
- <label for="node-config-input-object_type_mv" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_type_mv"></span>MV
96
- <input type="checkbox" id="node-config-input-object_type_mv">
97
- </label>
98
- </div>
99
- </div>
100
-
101
- <br>
102
-
103
- <div class="form-row" style="display: inline-flex; width: fit-content; flex-wrap: nowrap;">
104
- <label for="node-config-input-object_properties_group"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.object_properties_group"></span> Object Properties</label>
105
- <div id="node-config-input-object_properties_group" style="display: flex; padding-left: 45px;">
106
- <label for="node-config-input-object_property_presentVal" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_property_presentVal"></span>Present Value
107
- <input type="checkbox" id="node-config-input-object_property_presentVal">
108
- </label>
109
-
110
- <label for="node-config-input-object_property_objDescription" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_property_objDescription"></span>Description
111
- <input type="checkbox" id="node-config-input-object_property_objDescription">
112
- </label>
113
-
114
- <label for="node-config-input-object_property_statusFlag" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_property_statusFlag"></span>Status Flags
115
- <input type="checkbox" id="node-config-input-object_property_statusFlag">
116
- </label>
117
-
118
- <label for="node-config-input-object_property_reliability" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_property_reliability"></span>Reliability
119
- <input type="checkbox" id="node-config-input-object_property_reliability">
120
- </label>
121
-
122
- <label for="node-config-input-object_property_outOfService" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_property_outOfService"></span>Out of Service
123
- <input type="checkbox" id="node-config-input-object_property_outOfService">
124
- </label>
125
-
126
- <label for="node-config-input-object_property_units" style="flex-basis: content; padding-right: 20px;"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_property_units"></span>Units
127
- <input type="checkbox" id="node-config-input-object_property_units">
128
- </label>
129
- </div>
130
- </div>
131
- </script>
package/bacnet_object.js DELETED
@@ -1,121 +0,0 @@
1
- /*
2
- MIT License Copyright 2021, 2022 - Bitpool Pty Ltd
3
- */
4
-
5
- module.exports = function (RED) {
6
- const baEnum = require('./resources/node-bacnet/index.js').enum;
7
- function BitpoolBacnetObject (config) {
8
- RED.nodes.createNode(this, config)
9
-
10
- this.object_type_ai = config.object_type_ai;
11
- this.object_type_ao = config.object_type_ao;
12
- this.object_type_av = config.object_type_av;
13
- this.object_type_bi = config.object_type_bi;
14
- this.object_type_bo = config.object_type_bo;
15
- this.object_type_bv = config.object_type_bv;
16
-
17
- this.object_type_mi = config.object_type_mi;
18
- this.object_type_mo = config.object_type_mo;
19
- this.object_type_mv = config.object_type_mv;
20
-
21
- this.object_type = getObjectTypes(this);
22
-
23
- this.object_property_presentVal = config.object_property_presentVal;
24
- this.object_property_objDescription = config.object_property_objDescription;
25
- this.object_property_statusFlag = config.object_property_statusFlag;
26
- this.object_property_reliability = config.object_property_reliability;
27
- this.object_property_outOfService = config.object_property_outOfService;
28
- this.object_property_units = config.object_property_units;
29
- this.object_props = getObjectProps(this);
30
-
31
- this.instance_start = config.instance_start;
32
- this.instance_end = config.instance_end;
33
-
34
- this.instance = getInstanceRange(this);
35
-
36
- function getObjectTypes(node) {
37
- var typeArr = [];
38
- if(node.object_type_ai == true){
39
- typeArr.push("0");
40
- }
41
- if(node.object_type_ao == true){
42
- typeArr.push("1");
43
- }
44
- if(node.object_type_av == true){
45
- typeArr.push("2");
46
- }
47
- if(node.object_type_bi == true){
48
- typeArr.push("3");
49
- }
50
- if(node.object_type_bo == true){
51
- typeArr.push("4");
52
- }
53
- if(node.object_type_bv == true){
54
- typeArr.push("5");
55
- }
56
- if(node.object_type_mi == true){
57
- typeArr.push("13");
58
- }
59
- if(node.object_type_mo == true){
60
- typeArr.push("14");
61
- }
62
- if(node.object_type_mv == true){
63
- typeArr.push("19");
64
- }
65
-
66
- return typeArr.join();
67
- };
68
-
69
- function getObjectProps(node){
70
- var propArr = [];
71
- if(node.object_property_presentVal == true){
72
- propArr.push({ id: baEnum.PropertyIds.PROP_PRESENT_VALUE });
73
- }
74
- if(node.object_property_objDescription == true){
75
- propArr.push({ id: baEnum.PropertyIds.PROP_DESCRIPTION });
76
- }
77
- if(node.object_property_statusFlag == true){
78
- propArr.push({ id: baEnum.PropertyIds.PROP_STATUS_FLAGS });
79
- }
80
- if(node.object_property_reliability == true){
81
- propArr.push({ id: baEnum.PropertyIds.PROP_RELIABILITY });
82
- }
83
- if(node.object_property_outOfService == true){
84
- propArr.push({ id: baEnum.PropertyIds.PROP_OUT_OF_SERVICE });
85
- }
86
- if(node.object_property_units == true) {
87
- propArr.push({ id: baEnum.PropertyIds.PROP_UNITS });
88
- }
89
-
90
- //add object name for every request as its used in formatting
91
- propArr.push({ id: baEnum.PropertyIds.PROP_OBJECT_NAME});
92
-
93
- return propArr;
94
- };
95
-
96
- function getInstanceRange(node){
97
- let start = node.instance_start;
98
- let end = node.instance_end;
99
-
100
- if(start == end) {
101
- return start;
102
- }
103
-
104
- if(start !== end && start < end) {
105
- return start + " - " + end;
106
- }
107
-
108
- if(start && !end) {
109
- return start;
110
- }
111
-
112
- if(start > end){
113
- return end + " - " + start;
114
- }
115
- };
116
-
117
- };
118
-
119
-
120
- RED.nodes.registerType('Bitpool-Bacnet-Object', BitpoolBacnetObject)
121
- }