@bitpoolos/edge-bacnet 1.6.5 → 1.6.7

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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.6.7] - 15-01-2026
4
+
5
+ Bug fix:
6
+
7
+ - Fix UI tree rendering issue with MSTP folders
8
+
9
+ Minor update:
10
+
11
+ - Styling
12
+ - Added properties to device points and minor change to device point polling
13
+
14
+ ## [1.6.6] - 20-11-2025
15
+
16
+ Minor update:
17
+
18
+ - Added all stored point properties as columns to "Export point list" CSV in read node Properties tab.
19
+ - Adjustment to point polling, setting stricter maxApdu sizes
20
+
3
21
  ## [1.6.5] - 09-10-2025
4
22
 
5
23
  Bug fix:
package/bacnet_client.js CHANGED
@@ -222,9 +222,31 @@ class BacnetClient extends EventEmitter {
222
222
  port: port,
223
223
  };
224
224
 
225
+ // Try to find the device to use device-specific options
226
+ let device = null;
227
+ if (type === 8) {
228
+ // Device object - instance is the device ID
229
+ device = that.deviceList.find(ele => ele.getDeviceId() === instance);
230
+ } else {
231
+ // For non-device objects, we can't determine the device from just address/instance
232
+ // This is a limitation of testFunction's current signature
233
+ }
234
+
235
+ // Use device-specific options if we found the device, otherwise use safer defaults
236
+ let readOptions;
237
+ if (device) {
238
+ readOptions = that.getDeviceSpecificOptions(device);
239
+ } else {
240
+ // Conservative defaults for unknown devices (assume small MSTP)
241
+ readOptions = {
242
+ maxSegments: 0, // No segmentation
243
+ maxApdu: 2 // 206 octets - safe for most MSTP devices
244
+ };
245
+ }
246
+
225
247
  const propertiesArray = [{ objectId: { type: type, instance: instance }, properties: [{ id: property }] }];
226
248
 
227
- that.client.readPropertyMultiple(addressObject, propertiesArray, that.readPropertyMultipleOptions, (err, value) => {
249
+ that.client.readPropertyMultiple(addressObject, propertiesArray, readOptions, (err, value) => {
228
250
  console.log("1 - readPropertyMultiple: ");
229
251
 
230
252
  console.log(value);
@@ -248,7 +270,7 @@ class BacnetClient extends EventEmitter {
248
270
  addressObject,
249
271
  { type: type, instance: instance },
250
272
  property,
251
- that.readPropertyMultipleOptions,
273
+ readOptions,
252
274
  (err, value) => {
253
275
  console.log("2 - readProperty: ");
254
276
 
@@ -316,12 +338,13 @@ class BacnetClient extends EventEmitter {
316
338
  address: device.getAddress(),
317
339
  port: device.getPort(),
318
340
  };
341
+ const readOptions = that.getDeviceSpecificOptions(device);
319
342
  return new Promise((resolve, reject) => {
320
343
  that.client.readProperty(
321
344
  addressObject,
322
345
  { type: baEnum.ObjectType.DEVICE, instance: device.getDeviceId() },
323
346
  baEnum.PropertyIdentifier.PROTOCOL_SERVICES_SUPPORTED,
324
- that.readPropertyMultipleOptions,
347
+ readOptions,
325
348
  (err, value) => {
326
349
  if (err) {
327
350
  reject(err);
@@ -339,7 +362,7 @@ class BacnetClient extends EventEmitter {
339
362
  let that = this;
340
363
  let address = device.getAddress().address;
341
364
  let deviceId = device.getDeviceId();
342
- let foundParentIndex = that.deviceList.findIndex((ele) => ele.getAddress() == address);
365
+ let foundParentIndex = that.deviceList.findIndex((ele) => that.getDeviceAddress(ele) == address && !ele.getIsMstpDevice());
343
366
  if (foundParentIndex !== -1) {
344
367
  that.deviceList[foundParentIndex].addChildDevice(deviceId);
345
368
  device.setParentDeviceId(that.deviceList[foundParentIndex].getDeviceId());
@@ -939,13 +962,46 @@ class BacnetClient extends EventEmitter {
939
962
 
940
963
  async updateManyPoints(device, points) {
941
964
  try {
942
- const results = await this._readObjectWithRequestArray(device, points, this.readPropertyMultipleOptions);
965
+ // Use device-specific options instead of global options
966
+ const deviceOptions = this.getDeviceSpecificOptions(device);
967
+ const results = await this._readObjectWithRequestArray(device, points, deviceOptions);
943
968
  return results;
944
969
  } catch (error) {
945
970
  throw error;
946
971
  }
947
972
  }
948
973
 
974
+ getDeviceSpecificOptions(device) {
975
+ let maxSegments = this.readPropertyMultipleOptions.maxSegments;
976
+ let maxApdu = this.readPropertyMultipleOptions.maxApdu;
977
+
978
+ // Adjust for devices with no segmentation support
979
+ if (device.getSegmentation() == 3) {
980
+ maxSegments = 0;
981
+ }
982
+
983
+ // Adjust maxApdu based on device capability
984
+ const deviceMaxApdu = device.getMaxApdu();
985
+ if (deviceMaxApdu <= 50) {
986
+ maxApdu = 0; // 50 octets
987
+ } else if (deviceMaxApdu <= 128) {
988
+ maxApdu = 1; // 128 octets
989
+ } else if (deviceMaxApdu <= 206) {
990
+ maxApdu = 2; // 206 octets
991
+ } else if (deviceMaxApdu <= 480) {
992
+ maxApdu = 3; // 480 octets
993
+ } else if (deviceMaxApdu <= 1024) {
994
+ maxApdu = 4; // 1024 octets
995
+ } else {
996
+ maxApdu = 5; // 1476 octets
997
+ }
998
+
999
+ return {
1000
+ maxSegments: maxSegments,
1001
+ maxApdu: maxApdu
1002
+ };
1003
+ }
1004
+
949
1005
  updatePointWithRetry(device, point, retryCount = 1) {
950
1006
  let that = this;
951
1007
  const tryUpdate = (retriesLeft) => {
@@ -997,21 +1053,8 @@ class BacnetClient extends EventEmitter {
997
1053
  port: device.getPort(),
998
1054
  };
999
1055
 
1000
- let maxSegments = that.readPropertyMultipleOptions.maxSegments;
1001
- let maxApdu = that.readPropertyMultipleOptions.maxApdu;
1002
-
1003
- if (device.getSegmentation() == 3) {
1004
- maxSegments = 0;
1005
- }
1006
-
1007
- if (device.getMaxApdu() == 480) {
1008
- maxApdu = 3;
1009
- }
1010
-
1011
- let settings = {
1012
- maxSegments: maxSegments,
1013
- maxApdu: maxApdu,
1014
- };
1056
+ // Use device-specific options
1057
+ const settings = that.getDeviceSpecificOptions(device);
1015
1058
 
1016
1059
  return new Promise((resolve, reject) => {
1017
1060
  that.client.readProperty(
@@ -1032,8 +1075,15 @@ class BacnetClient extends EventEmitter {
1032
1075
  }
1033
1076
 
1034
1077
  estimateMaxObjectSize(apduSize) {
1035
- if (apduSize < 500) {
1036
- return 20;
1078
+ // Be more conservative for very small MSTP devices
1079
+ if (apduSize <= 50) {
1080
+ return 1; // Only 1 object at a time for 50-byte devices
1081
+ } else if (apduSize <= 128) {
1082
+ return 3; // 3 objects for 128-byte devices
1083
+ } else if (apduSize <= 206) {
1084
+ return 5; // 5 objects for 206-byte devices
1085
+ } else if (apduSize < 500) {
1086
+ return 10; // Reduced from 20 for safety
1037
1087
  } else if (apduSize > 500 && apduSize < 1000) {
1038
1088
  //return Math.round(((apduSize - 30) / 7));
1039
1089
  return 50;
@@ -1254,12 +1304,13 @@ class BacnetClient extends EventEmitter {
1254
1304
  port: device.getPort(),
1255
1305
  };
1256
1306
  let deviceId = device.getDeviceId();
1307
+ const readOptions = that.getDeviceSpecificOptions(device);
1257
1308
 
1258
1309
  that.client.readProperty(
1259
1310
  addressObject,
1260
1311
  { type: baEnum.ObjectType.DEVICE, instance: deviceId },
1261
1312
  baEnum.PropertyIdentifier.OBJECT_NAME,
1262
- that.readPropertyMultipleOptions,
1313
+ readOptions,
1263
1314
  callback
1264
1315
  );
1265
1316
  }
@@ -1304,10 +1355,8 @@ class BacnetClient extends EventEmitter {
1304
1355
 
1305
1356
  _readObjectFull(device, type, instance) {
1306
1357
  const that = this;
1307
- const readOptions = {
1308
- maxSegments: that.readPropertyMultipleOptions.maxSegments,
1309
- maxApdu: that.readPropertyMultipleOptions.maxApdu,
1310
- };
1358
+ // Use device-specific options for reading all properties
1359
+ const readOptions = that.getDeviceSpecificOptions(device);
1311
1360
 
1312
1361
  const readIndividualPropsOptions = {
1313
1362
  maxSegments: 0,
@@ -1319,8 +1368,8 @@ class BacnetClient extends EventEmitter {
1319
1368
  port: device.getPort(),
1320
1369
  };
1321
1370
 
1322
- // Define all properties to be read
1323
- const allProperties = [
1371
+ // Define default properties for non-device objects
1372
+ const defaultProperties = [
1324
1373
  { id: baEnum.PropertyIdentifier.PRESENT_VALUE },
1325
1374
  { id: baEnum.PropertyIdentifier.DESCRIPTION },
1326
1375
  { id: baEnum.PropertyIdentifier.UNITS },
@@ -1335,8 +1384,66 @@ class BacnetClient extends EventEmitter {
1335
1384
  { id: baEnum.PropertyIdentifier.VENDOR_NAME },
1336
1385
  ];
1337
1386
 
1387
+ // Use device-specific properties for type 8, otherwise use default
1388
+ const propertiesToRead = type === 8 ? BacnetDevice.getDeviceObjectProperties() : defaultProperties;
1389
+
1390
+ // Function to read properties individually
1391
+ const readPropertiesIndividually = (resolve, reject) => {
1392
+ const promises = propertiesToRead.map(
1393
+ (property) =>
1394
+ new Promise((propertyResolve) => {
1395
+ that.client.readProperty(
1396
+ addressObject,
1397
+ { type: type, instance: instance },
1398
+ property.id,
1399
+ readIndividualPropsOptions,
1400
+ (err, value) => {
1401
+ if (err) {
1402
+ propertyResolve(null);
1403
+ } else {
1404
+ propertyResolve({
1405
+ id: property.id,
1406
+ index: value.property.index,
1407
+ value: value.values,
1408
+ });
1409
+ }
1410
+ }
1411
+ );
1412
+ })
1413
+ );
1414
+
1415
+ Promise.all(promises)
1416
+ .then((resultArray) => {
1417
+ // Filter out null results
1418
+ const validResults = resultArray.filter((result) => result !== null);
1419
+
1420
+ resolve({
1421
+ error: null,
1422
+ value: {
1423
+ values: [
1424
+ {
1425
+ objectId: {
1426
+ type: type,
1427
+ instance: instance,
1428
+ },
1429
+ values: validResults,
1430
+ },
1431
+ ],
1432
+ },
1433
+ });
1434
+ })
1435
+ .catch(reject);
1436
+ };
1437
+
1338
1438
  return new Promise((resolve, reject) => {
1339
- // Try to read all properties at once
1439
+ // For Device objects (type 8), skip ALL attempt - many MSTP devices don't support it
1440
+ // Go straight to reading individual properties for better reliability
1441
+ if (type === 8) {
1442
+ readPropertiesIndividually(resolve, reject);
1443
+ return;
1444
+ }
1445
+
1446
+ // For other object types, try to read all properties at once first
1340
1447
  that
1341
1448
  ._readObject(addressObject, type, instance, [{ id: baEnum.PropertyIdentifier.ALL }], readOptions)
1342
1449
  .then((result) => {
@@ -1345,70 +1452,20 @@ class BacnetClient extends EventEmitter {
1345
1452
  resolve(result);
1346
1453
  } else {
1347
1454
  // If not, proceed to read individual properties
1348
- readPropertiesIndividually();
1455
+ readPropertiesIndividually(resolve, reject);
1349
1456
  }
1350
1457
  })
1351
1458
  .catch(() => {
1352
1459
  // On error, proceed to read individual properties
1353
- readPropertiesIndividually();
1460
+ readPropertiesIndividually(resolve, reject);
1354
1461
  });
1355
-
1356
- // Function to read properties individually
1357
- const readPropertiesIndividually = () => {
1358
- const promises = allProperties.map(
1359
- (property, index) =>
1360
- new Promise((propertyResolve) => {
1361
- that.client.readProperty(
1362
- addressObject,
1363
- { type: type, instance: instance },
1364
- property.id,
1365
- readIndividualPropsOptions,
1366
- (err, value) => {
1367
- if (err) {
1368
- propertyResolve(null);
1369
- } else {
1370
- propertyResolve({
1371
- id: property.id,
1372
- index: value.property.index,
1373
- value: value.values,
1374
- });
1375
- }
1376
- }
1377
- );
1378
- })
1379
- );
1380
-
1381
- Promise.all(promises)
1382
- .then((resultArray) => {
1383
- // Filter out null results
1384
- const validResults = resultArray.filter((result) => result !== null);
1385
-
1386
- resolve({
1387
- error: null,
1388
- value: {
1389
- values: [
1390
- {
1391
- objectId: {
1392
- type: type,
1393
- instance: instance,
1394
- },
1395
- values: validResults,
1396
- },
1397
- ],
1398
- },
1399
- });
1400
- })
1401
- .catch(reject);
1402
- };
1403
1462
  });
1404
1463
  }
1405
1464
 
1406
1465
  _readObjectLite(device, type, instance) {
1407
1466
  const that = this;
1408
- const readOptions = {
1409
- maxSegments: that.readPropertyMultipleOptions.maxSegments,
1410
- maxApdu: that.readPropertyMultipleOptions.maxApdu,
1411
- };
1467
+ // Use device-specific options
1468
+ const readOptions = that.getDeviceSpecificOptions(device);
1412
1469
 
1413
1470
  const readIndividualPropsOptions = {
1414
1471
  maxSegments: 0,
@@ -1573,10 +1630,8 @@ class BacnetClient extends EventEmitter {
1573
1630
  scanDevice(device) {
1574
1631
  let that = this;
1575
1632
  return new Promise((resolve, reject) => {
1576
- const readOptions = {
1577
- maxSegments: that.readPropertyMultipleOptions.maxSegments,
1578
- maxApdu: that.readPropertyMultipleOptions.maxApdu,
1579
- };
1633
+ // Use device-specific options
1634
+ const readOptions = that.getDeviceSpecificOptions(device);
1580
1635
  this._readObjectList(device, readOptions, (err, result) => {
1581
1636
  if (!err) {
1582
1637
  try {
@@ -2057,10 +2112,23 @@ class BacnetClient extends EventEmitter {
2057
2112
  }
2058
2113
  break;
2059
2114
  case baEnum.PropertyIdentifier.VENDOR_NAME:
2060
- if (object.value) {
2061
- if (object.value[0].value && typeof object.value[0].value == "string") {
2062
- values[objectId].vendorName = object.value[0].value;
2063
- }
2115
+ if (object.value && object.value[0] && object.value[0].value && typeof object.value[0].value == "string") {
2116
+ values[objectId].vendorName = object.value[0].value;
2117
+ }
2118
+ break;
2119
+ case baEnum.PropertyIdentifier.MODEL_NAME:
2120
+ if (object.value && object.value[0] && object.value[0].value && typeof object.value[0].value == "string") {
2121
+ values[objectId].modelName = object.value[0].value;
2122
+ }
2123
+ break;
2124
+ case baEnum.PropertyIdentifier.FIRMWARE_REVISION:
2125
+ if (object.value && object.value[0] && object.value[0].value && typeof object.value[0].value == "string") {
2126
+ values[objectId].firmwareRevision = object.value[0].value;
2127
+ }
2128
+ break;
2129
+ case baEnum.PropertyIdentifier.APPLICATION_SOFTWARE_VERSION:
2130
+ if (object.value && object.value[0] && object.value[0].value && typeof object.value[0].value == "string") {
2131
+ values[objectId].applicationSoftwareVersion = object.value[0].value;
2064
2132
  }
2065
2133
  break;
2066
2134
  }
package/bacnet_device.js CHANGED
@@ -1,4 +1,31 @@
1
+ const bacnet = require("./resources/node-bacstack-ts/dist/index.js");
2
+ const baEnum = bacnet.enum;
3
+
4
+ // Device Object (type 8) properties - critical properties guaranteed per ASHRAE 135
5
+ // These are the minimum required properties that all BACnet devices must support
6
+ const DEVICE_OBJECT_PROPERTIES = [
7
+ { id: baEnum.PropertyIdentifier.OBJECT_IDENTIFIER },
8
+ { id: baEnum.PropertyIdentifier.OBJECT_NAME },
9
+ { id: baEnum.PropertyIdentifier.OBJECT_TYPE },
10
+ { id: baEnum.PropertyIdentifier.SYSTEM_STATUS },
11
+ { id: baEnum.PropertyIdentifier.VENDOR_NAME },
12
+ { id: baEnum.PropertyIdentifier.VENDOR_IDENTIFIER },
13
+ { id: baEnum.PropertyIdentifier.MODEL_NAME },
14
+ { id: baEnum.PropertyIdentifier.FIRMWARE_REVISION },
15
+ { id: baEnum.PropertyIdentifier.APPLICATION_SOFTWARE_VERSION },
16
+ { id: baEnum.PropertyIdentifier.DESCRIPTION },
17
+ ];
18
+
1
19
  class BacnetDevice {
20
+ /**
21
+ * Returns the standardized list of properties to read for Device objects (type 8).
22
+ * These are critical properties guaranteed to exist on all BACnet devices per ASHRAE 135.
23
+ * @returns {Array} Array of property identifier objects
24
+ */
25
+ static getDeviceObjectProperties() {
26
+ return DEVICE_OBJECT_PROPERTIES;
27
+ }
28
+
2
29
  constructor(fromImport, config) {
3
30
  let that = this;
4
31
 
package/bacnet_read.html CHANGED
@@ -433,8 +433,20 @@
433
433
  },
434
434
  exportPointListCsv() {
435
435
  let app = this;
436
- let csvContent = "ipAddress,deviceId,deviceName,pointName,objectType" + "\r\n";
436
+ let csvContent = "ipAddress,deviceId,deviceName,pointName,objectType,presentValue,description,units,objectName,displayName,systemStatus,modificationDate,programState,recordCount,hasPriorityArray,vendorName" + "\r\n";
437
437
  const keys = Object.keys(app.pointList);
438
+
439
+ // Helper function to safely get property value and escape for CSV
440
+ const getCsvValue = (value) => {
441
+ if (value === null || value === undefined) return "";
442
+ const stringValue = String(value);
443
+ // Escape double quotes and wrap in quotes if contains comma, newline, or double quote
444
+ if (stringValue.includes(',') || stringValue.includes('\n') || stringValue.includes('"')) {
445
+ return '"' + stringValue.replace(/"/g, '""') + '"';
446
+ }
447
+ return stringValue;
448
+ };
449
+
438
450
  for (key in keys) {
439
451
  const guid = keys[key];
440
452
  const ipAddress = guid.split("-")[0];
@@ -452,16 +464,39 @@
452
464
  const points = Object.keys(deviceObject);
453
465
  if (points.length > 0) {
454
466
  for (point in points) {
467
+ const pointData = deviceObject[points[point]] || {};
455
468
  csvContent +=
456
- ipAddress +
469
+ getCsvValue(ipAddress) +
470
+ "," +
471
+ getCsvValue(deviceId) +
472
+ "," +
473
+ getCsvValue(deviceName) +
474
+ "," +
475
+ getCsvValue(points[point]) +
476
+ "," +
477
+ getCsvValue(pointData.meta?.objectId?.type) +
457
478
  "," +
458
- deviceId +
479
+ getCsvValue(pointData.presentValue) +
459
480
  "," +
460
- deviceName +
481
+ getCsvValue(pointData.description) +
461
482
  "," +
462
- points[point] +
483
+ getCsvValue(pointData.units) +
463
484
  "," +
464
- deviceObject[points[point]].meta.objectId.type +
485
+ getCsvValue(pointData.objectName) +
486
+ "," +
487
+ getCsvValue(pointData.displayName) +
488
+ "," +
489
+ getCsvValue(pointData.systemStatus) +
490
+ "," +
491
+ getCsvValue(pointData.modificationDate) +
492
+ "," +
493
+ getCsvValue(pointData.programState) +
494
+ "," +
495
+ getCsvValue(pointData.recordCount) +
496
+ "," +
497
+ getCsvValue(pointData.hasPriorityArray) +
498
+ "," +
499
+ getCsvValue(pointData.vendorName) +
465
500
  "\r\n";
466
501
 
467
502
  if (parseInt(point) == points.length - 1 && parseInt(key) == keys.length - 1) {
@@ -687,14 +722,14 @@
687
722
  let app = this;
688
723
  let device = app.getDeviceFromDeviceList(slotProps.node.ipAddr, slotProps.node.deviceId);
689
724
  if (device) {
690
- app.nodeService.purgeDevice(device).then(function (result) {});
725
+ app.nodeService.purgeDevice(device).then(function (result) { });
691
726
  }
692
727
  },
693
728
  updatePointsForDevice(slotProps) {
694
729
  let app = this;
695
730
  let device = app.getDeviceFromDeviceList(slotProps.node.ipAddr, slotProps.node.deviceId);
696
731
  if (device) {
697
- app.nodeService.updatePointsForDevice(device).then(function (result) {});
732
+ app.nodeService.updatePointsForDevice(device).then(function (result) { });
698
733
  }
699
734
  },
700
735
  updatePoint(slotProps) {
@@ -705,7 +740,7 @@
705
740
  });
706
741
  const deviceKey = `${app.getDeviceAddress(device.address)}-${device.deviceId}`;
707
742
  if (device) {
708
- app.nodeService.updatePoint(deviceKey, pointKey).then(function (result) {});
743
+ app.nodeService.updatePoint(deviceKey, pointKey).then(function (result) { });
709
744
  }
710
745
  },
711
746
  setDeviceName() {
@@ -1708,4 +1743,4 @@
1708
1743
  <li><a href="https://wiki.bitpool.com/">wiki.bitpool.com</a> - find more documentation.</li>
1709
1744
  <li><a href="https://bacnet.org/">BACnet</a> - find more about the protocol.</li>
1710
1745
  </ul>
1711
- </script>
1746
+ </script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitpoolos/edge-bacnet",
3
- "version": "1.6.5",
3
+ "version": "1.6.7",
4
4
  "description": "A bacnet gateway for node-red",
5
5
  "dependencies": {
6
6
  "@plus4nodered/ts-node-bacnet": "^1.0.0-beta.2",
@@ -26,13 +26,15 @@
26
26
  }
27
27
  },
28
28
  "keywords": [
29
+ "BACnet",
29
30
  "node-red",
30
31
  "bitpool",
31
32
  "bitpoolos",
32
33
  "edge",
33
34
  "big data",
34
35
  "iot",
35
- "BACnet"
36
+ "building automation",
37
+ "bms"
36
38
  ],
37
39
  "engines": {
38
40
  "node": ">=12.0.0"
@@ -319,8 +319,13 @@
319
319
  margin-left: 10px;
320
320
  background-color: #00aeef;
321
321
  color: #ffffff;
322
- border-radius: 45%;
323
- font-size: 12px;
322
+ border-radius: 4px;
323
+ font-size: 11px;
324
+ font-weight: 500;
325
+ padding: 2px 6px;
326
+ display: inline-block;
327
+ vertical-align: middle;
328
+ line-height: 1.2;
324
329
  }
325
330
 
326
331
  .pointAddedToRead {
package/treeBuilder.js CHANGED
@@ -355,6 +355,12 @@ class treeBuilder {
355
355
  this.addPointProperty(pointProperties, "Modification Date", point.modificationDate);
356
356
  this.addPointProperty(pointProperties, "Program State", point.programState);
357
357
  this.addPointProperty(pointProperties, "Record Count", point.recordCount);
358
+
359
+ // Add device-specific properties (type 8)
360
+ this.addPointProperty(pointProperties, "Vendor Name", point.vendorName);
361
+ this.addPointProperty(pointProperties, "Model Name", point.modelName);
362
+ this.addPointProperty(pointProperties, "Firmware Revision", point.firmwareRevision);
363
+ this.addPointProperty(pointProperties, "Application Software Version", point.applicationSoftwareVersion);
358
364
 
359
365
  // Return the array of point properties
360
366
  return pointProperties;