@bitpoolos/edge-bacnet 1.3.2 → 1.4.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/CHANGELOG.md +33 -0
- package/bacnet_client.js +27 -33
- package/bacnet_gateway.js +140 -21
- package/bacnet_read.html +61 -59
- package/bacnet_read.js +2 -0
- package/bacnet_server.js +143 -17
- package/bitpool_inject.html +492 -462
- package/common.js +0 -29
- package/package.json +1 -1
- package/treeBuilder.js +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.4.0] - 05-07-2024
|
|
4
|
+
|
|
5
|
+
### Summary
|
|
6
|
+
|
|
7
|
+
Fixed read list export for sites with large point counts.
|
|
8
|
+
|
|
9
|
+
Removed auto tree reload on read node UI. UI tree must be manually reloaded now.
|
|
10
|
+
|
|
11
|
+
Fixed export to CSV bug.
|
|
12
|
+
|
|
13
|
+
Fixed state array text not found bug
|
|
14
|
+
|
|
15
|
+
Removed unecessary debug.
|
|
16
|
+
|
|
17
|
+
Updated required json saved to node JSON file.
|
|
18
|
+
|
|
19
|
+
Added github pull requests
|
|
20
|
+
- Added create object and delete object to bacnet server
|
|
21
|
+
- Added write property to bacnet server
|
|
22
|
+
|
|
23
|
+
Added Simple With Status read property type.
|
|
24
|
+
- This type sends a msg.payload that consists of {presentValue, timestamp, status}
|
|
25
|
+
- Status is currently online and offline
|
|
26
|
+
|
|
27
|
+
Changed inject node to only 1 selectable type of inject (Discover or Poll)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## [1.3.2] - 18-06-2024
|
|
31
|
+
|
|
32
|
+
### Summary
|
|
33
|
+
|
|
34
|
+
Bug fix for API request URL paths. Updated for using node-red host setting.
|
|
35
|
+
|
|
3
36
|
## [1.3.1] - 06-06-2024
|
|
4
37
|
|
|
5
38
|
### Summary
|
package/bacnet_client.js
CHANGED
|
@@ -322,31 +322,13 @@ class BacnetClient extends EventEmitter {
|
|
|
322
322
|
|
|
323
323
|
updatePointsForDevice(deviceObject) {
|
|
324
324
|
let that = this;
|
|
325
|
-
return new Promise((resolve, reject) => {
|
|
325
|
+
return new Promise(async (resolve, reject) => {
|
|
326
326
|
try {
|
|
327
327
|
let device = that.deviceList.find((ele) => ele.getDeviceId() == deviceObject.deviceId);
|
|
328
|
-
that.updateDeviceName(device);
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
//test
|
|
332
|
-
|
|
333
|
-
that.getProtocolSupported(device).then(function (result) {
|
|
334
|
-
console.log("updatePointsForDevice getProtocolSupported ", result.values[0].originalBitString);
|
|
335
|
-
console.log(result.values[0]);
|
|
336
|
-
console.log(result);
|
|
337
|
-
console.log(result.values[0]);
|
|
338
|
-
let decodedValues = decodeBitArray(8, result.values[0].originalBitString.value);
|
|
339
|
-
device.setProtocolServicesSupported(decodedValues);
|
|
340
|
-
}).catch(function (error) {
|
|
341
|
-
that.logOut("getProtocolSupported error: ", error);
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
//test
|
|
345
|
-
|
|
328
|
+
await that.updateDeviceName(device);
|
|
346
329
|
|
|
347
330
|
if (device.getIsProtocolServicesSet() == false) {
|
|
348
331
|
that.getProtocolSupported(device).then(function (result) {
|
|
349
|
-
console.log("updatePointsForDevice getProtocolSupported ", result.values[0].originalBitString);
|
|
350
332
|
let decodedValues = decodeBitArray(8, result.values[0].originalBitString.value);
|
|
351
333
|
device.setProtocolServicesSupported(decodedValues);
|
|
352
334
|
}).catch(function (error) {
|
|
@@ -685,14 +667,17 @@ class BacnetClient extends EventEmitter {
|
|
|
685
667
|
// Process points for the current device
|
|
686
668
|
const pointsToRead = readConfig.pointsToRead[key];
|
|
687
669
|
const pointNames = Object.keys(pointsToRead);
|
|
688
|
-
|
|
670
|
+
let totalPoints = pointNames.length;
|
|
689
671
|
let requestArray = [];
|
|
690
672
|
let processedPoints = 0; // Counter for processed points
|
|
691
673
|
|
|
692
674
|
// Process each point for the device in batches
|
|
693
675
|
for (let i = 0; i < pointNames.length; i++) {
|
|
694
676
|
const pointName = pointNames[i];
|
|
695
|
-
if (pointName === "deviceName")
|
|
677
|
+
if (pointName === "deviceName") {
|
|
678
|
+
totalPoints = totalPoints - 1;
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
696
681
|
|
|
697
682
|
const pointConfig = pointsToRead[pointName];
|
|
698
683
|
const objectId = that.getObjectId(pointName, pointConfig, that);
|
|
@@ -760,10 +745,12 @@ class BacnetClient extends EventEmitter {
|
|
|
760
745
|
if (isNumber(val)) {
|
|
761
746
|
pointRef.presentValue = roundDecimalPlaces(val, roundDecimal);
|
|
762
747
|
if (pointRef.meta.objectId.type == 19 || pointRef.meta.objectId.type == 13 || pointRef.meta.objectId.type == 14) {
|
|
763
|
-
if (
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
748
|
+
if (pointRef.stateTextArray && typeof pointRef.stateTextArray[0].value !== "object") {
|
|
749
|
+
if (val != 0) {
|
|
750
|
+
pointRef.presentValue = pointRef.stateTextArray[val - 1].value;
|
|
751
|
+
} else {
|
|
752
|
+
pointRef.presentValue = pointRef.stateTextArray[val].value;
|
|
753
|
+
}
|
|
767
754
|
}
|
|
768
755
|
}
|
|
769
756
|
} else {
|
|
@@ -772,12 +759,23 @@ class BacnetClient extends EventEmitter {
|
|
|
772
759
|
}
|
|
773
760
|
}
|
|
774
761
|
|
|
762
|
+
pointRef.timestamp = Date.now();
|
|
763
|
+
pointRef.status = "online";
|
|
764
|
+
|
|
775
765
|
// Store the point data in results
|
|
776
766
|
bacnetResults[deviceName][pointNameRef] = pointRef;
|
|
777
767
|
}
|
|
778
768
|
});
|
|
779
769
|
} catch (err) {
|
|
780
770
|
that.logOut("Error processing batch:", err);
|
|
771
|
+
|
|
772
|
+
requestArray.forEach(request => {
|
|
773
|
+
let pointRef = request.pointRef;
|
|
774
|
+
pointRef.status = "offline";
|
|
775
|
+
|
|
776
|
+
bacnetResults[deviceName][cacheRef.pointName] = pointRef;
|
|
777
|
+
});
|
|
778
|
+
|
|
781
779
|
}
|
|
782
780
|
}
|
|
783
781
|
|
|
@@ -798,6 +796,9 @@ class BacnetClient extends EventEmitter {
|
|
|
798
796
|
bacnetResults[deviceName][pointName] = pointRef;
|
|
799
797
|
} catch (err) {
|
|
800
798
|
that.logOut(`Error updating point ${pointName}:`, err);
|
|
799
|
+
|
|
800
|
+
pointRef.status = "offline";
|
|
801
|
+
bacnetResults[deviceName][pointName] = pointRef;
|
|
801
802
|
}
|
|
802
803
|
}
|
|
803
804
|
}
|
|
@@ -1501,8 +1502,6 @@ class BacnetClient extends EventEmitter {
|
|
|
1501
1502
|
|
|
1502
1503
|
treeWorker.cacheData();
|
|
1503
1504
|
|
|
1504
|
-
//const missingDevices = await that.getDevicesNotRenderedYet();
|
|
1505
|
-
|
|
1506
1505
|
for (let i = 0; i < that.deviceList.length; i++) {
|
|
1507
1506
|
let device = that.deviceList[i];
|
|
1508
1507
|
await treeWorker.processDevice(device, i);
|
|
@@ -1736,9 +1735,6 @@ class BacnetClient extends EventEmitter {
|
|
|
1736
1735
|
case baEnum.PropertyIdentifier.OBJECT_TYPE:
|
|
1737
1736
|
if (object.value[0] && object.value[0].value) values[objectId].objectType = object.value[0].value;
|
|
1738
1737
|
break;
|
|
1739
|
-
case baEnum.PropertyIdentifier.OBJECT_IDENTIFIER:
|
|
1740
|
-
if (object.value[0] && object.value[0].value) values[objectId].objectID = object.value[0].value;
|
|
1741
|
-
break;
|
|
1742
1738
|
case baEnum.PropertyIdentifier.PROPERTY_LIST:
|
|
1743
1739
|
if (object.value) values[objectId].propertyList = that.mapPropsToArray(object.value);
|
|
1744
1740
|
break;
|
|
@@ -1752,13 +1748,11 @@ class BacnetClient extends EventEmitter {
|
|
|
1752
1748
|
values[objectId].modificationDate = object.value[0].value;
|
|
1753
1749
|
}
|
|
1754
1750
|
break;
|
|
1755
|
-
|
|
1756
1751
|
case baEnum.PropertyIdentifier.PROGRAM_STATE:
|
|
1757
1752
|
if (object.value[0]) {
|
|
1758
1753
|
values[objectId].programState = that.getPROP_PROGRAM_STATE(object.value[0].value);
|
|
1759
1754
|
}
|
|
1760
1755
|
break;
|
|
1761
|
-
|
|
1762
1756
|
case baEnum.PropertyIdentifier.RECORD_COUNT:
|
|
1763
1757
|
if (object.value[0]) {
|
|
1764
1758
|
values[objectId].recordCount = object.value[0].value;
|
package/bacnet_gateway.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
module.exports = function (RED) {
|
|
6
6
|
const { BacnetClient } = require("./bacnet_client");
|
|
7
7
|
const { BacnetClientConfig, getIpAddress } = require("./common");
|
|
8
|
-
const { exec } = require("child_process");
|
|
9
8
|
const { BacnetServer } = require("./bacnet_server.js");
|
|
10
9
|
|
|
11
10
|
function BitpoolBacnetGatewayDevice(config) {
|
|
@@ -109,21 +108,27 @@ module.exports = function (RED) {
|
|
|
109
108
|
}, 3000);
|
|
110
109
|
}
|
|
111
110
|
if (outputType.json && !outputType.mqtt) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
//json
|
|
112
|
+
if (objectPropertyType.simpleWithStatus && !objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
113
|
+
//simpleWithStatus
|
|
114
|
+
sendSimpleWithStatus(values, readNodeName, true);
|
|
115
|
+
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload && !objectPropertyType.simpleWithStatus) {
|
|
116
|
+
//fullObject
|
|
116
117
|
sendJsonAsMqtt(values, readNodeName);
|
|
117
|
-
} else if (!objectPropertyType.fullObject && objectPropertyType.
|
|
118
|
+
} else if (objectPropertyType.simplePayload && !objectPropertyType.fullObject && !objectPropertyType.simpleWithStatus) {
|
|
119
|
+
//simplePayload
|
|
118
120
|
sendSimpleJson(values, readNodeName);
|
|
119
121
|
}
|
|
120
122
|
} else if (!outputType.json && outputType.mqtt) {
|
|
121
|
-
|
|
123
|
+
//mqtt
|
|
124
|
+
if (objectPropertyType.simpleWithStatus && !objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
125
|
+
//simpleWithStatus
|
|
126
|
+
sendSimpleWithStatus(values, readNodeName, false);
|
|
127
|
+
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload && !objectPropertyType.simpleWithStatus) {
|
|
128
|
+
//fullObject
|
|
122
129
|
sendAsMqtt(values, readNodeName);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
sendAsMqtt(values, readNodeName);
|
|
126
|
-
} else if (!objectPropertyType.fullObject && objectPropertyType.simplePayload) {
|
|
130
|
+
} else if (objectPropertyType.simplePayload && !objectPropertyType.fullObject && !objectPropertyType.simpleWithStatus) {
|
|
131
|
+
//simplePayload
|
|
127
132
|
sendSimpleMqtt(values, readNodeName);
|
|
128
133
|
}
|
|
129
134
|
}
|
|
@@ -159,6 +164,23 @@ module.exports = function (RED) {
|
|
|
159
164
|
}
|
|
160
165
|
}
|
|
161
166
|
|
|
167
|
+
node.bacnetServer.on("writeProperty", (topic, newValue) => {
|
|
168
|
+
let formattedTopic = topic;
|
|
169
|
+
if (
|
|
170
|
+
node.nodeName !== "gateway" &&
|
|
171
|
+
node.nodeName !== "" &&
|
|
172
|
+
node.nodeName !== "null" &&
|
|
173
|
+
node.nodeName !== "undefined" &&
|
|
174
|
+
typeof node.nodeName == "string"
|
|
175
|
+
) {
|
|
176
|
+
formattedTopic = `${node.nodeName}/BITPOOL_EDGE_BACNET_GATEWAY/BACNET_SERVER/${topic}`;
|
|
177
|
+
} else {
|
|
178
|
+
formattedTopic = `BITPOOL_EDGE_BACNET_GATEWAY/BACNET_SERVER/${topic}`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
node.send({ payload: newValue, topic: formattedTopic });
|
|
182
|
+
});
|
|
183
|
+
|
|
162
184
|
node.on("input", function (msg) {
|
|
163
185
|
if (msg.topic && msg.payload !== null) {
|
|
164
186
|
if (node.bacnetServer) {
|
|
@@ -420,21 +442,27 @@ module.exports = function (RED) {
|
|
|
420
442
|
}, 3000);
|
|
421
443
|
}
|
|
422
444
|
if (outputType.json && !outputType.mqtt) {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
445
|
+
//json
|
|
446
|
+
if (objectPropertyType.simpleWithStatus && !objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
447
|
+
//simpleWithStatus
|
|
448
|
+
sendSimpleWithStatus(values, readNodeName, true);
|
|
449
|
+
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload && !objectPropertyType.simpleWithStatus) {
|
|
450
|
+
//fullObject
|
|
427
451
|
sendJsonAsMqtt(values, readNodeName);
|
|
428
|
-
} else if (!objectPropertyType.fullObject && objectPropertyType.
|
|
452
|
+
} else if (objectPropertyType.simplePayload && !objectPropertyType.fullObject && !objectPropertyType.simpleWithStatus) {
|
|
453
|
+
//simplePayload
|
|
429
454
|
sendSimpleJson(values, readNodeName);
|
|
430
455
|
}
|
|
431
456
|
} else if (!outputType.json && outputType.mqtt) {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
457
|
+
//mqtt
|
|
458
|
+
if (objectPropertyType.simpleWithStatus && !objectPropertyType.fullObject && !objectPropertyType.simplePayload) {
|
|
459
|
+
//simpleWithStatus
|
|
460
|
+
sendSimpleWithStatus(values, readNodeName, false);
|
|
461
|
+
} else if (objectPropertyType.fullObject && !objectPropertyType.simplePayload && !objectPropertyType.simpleWithStatus) {
|
|
462
|
+
//fullObject
|
|
436
463
|
sendAsMqtt(values, readNodeName);
|
|
437
|
-
} else if (!objectPropertyType.fullObject && objectPropertyType.
|
|
464
|
+
} else if (objectPropertyType.simplePayload && !objectPropertyType.fullObject && !objectPropertyType.simpleWithStatus) {
|
|
465
|
+
//simplePayload
|
|
438
466
|
sendSimpleMqtt(values, readNodeName);
|
|
439
467
|
}
|
|
440
468
|
}
|
|
@@ -466,6 +494,97 @@ module.exports = function (RED) {
|
|
|
466
494
|
return pointName;
|
|
467
495
|
}
|
|
468
496
|
|
|
497
|
+
sendSimpleWithStatus = function (values, readNodeName, isJson) {
|
|
498
|
+
let devices = Object.keys(values);
|
|
499
|
+
devices.forEach(function (device) {
|
|
500
|
+
if (device !== "_msgid") {
|
|
501
|
+
let points = values[device];
|
|
502
|
+
let structuredObject = {};
|
|
503
|
+
let msgg = {};
|
|
504
|
+
for (let point in points) {
|
|
505
|
+
if (points[point] && "presentValue" in points[point]) {
|
|
506
|
+
let pointName = getPointName(points[point], point);
|
|
507
|
+
if (
|
|
508
|
+
node.nodeName !== "gateway" &&
|
|
509
|
+
node.nodeName !== "" &&
|
|
510
|
+
node.nodeName !== "null" &&
|
|
511
|
+
node.nodeName !== "undefined" &&
|
|
512
|
+
typeof node.nodeName == "string"
|
|
513
|
+
) {
|
|
514
|
+
if (readNodeName !== '' &&
|
|
515
|
+
readNodeName !== null &&
|
|
516
|
+
readNodeName !== undefined
|
|
517
|
+
) {
|
|
518
|
+
msgg.topic = `${node.nodeName}/${readNodeName}/${device}/${pointName}`;
|
|
519
|
+
} else {
|
|
520
|
+
msgg.topic = `${node.nodeName}/${device}/${pointName}`;
|
|
521
|
+
}
|
|
522
|
+
} else {
|
|
523
|
+
if (readNodeName !== '' &&
|
|
524
|
+
readNodeName !== null &&
|
|
525
|
+
readNodeName !== undefined
|
|
526
|
+
) {
|
|
527
|
+
msgg.topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}/${pointName}`;
|
|
528
|
+
} else {
|
|
529
|
+
msgg.topic = `BITPOOL_BACNET_GATEWAY/${device}/${pointName}`;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
let payload = {
|
|
533
|
+
presentValue: points[point]["presentValue"],
|
|
534
|
+
timestamp: points[point]["timestamp"],
|
|
535
|
+
status: points[point]["status"]
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
if (isJson) {
|
|
539
|
+
//json payload
|
|
540
|
+
structuredObject[point] = payload;
|
|
541
|
+
} else {
|
|
542
|
+
//mqtt payload
|
|
543
|
+
msgg.payload = payload;
|
|
544
|
+
node.send(msgg);
|
|
545
|
+
msgg = {};
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (isJson) {
|
|
551
|
+
//json payload
|
|
552
|
+
let topic = "";
|
|
553
|
+
if (
|
|
554
|
+
node.nodeName !== "gateway" &&
|
|
555
|
+
node.nodeName !== "" &&
|
|
556
|
+
node.nodeName !== "null" &&
|
|
557
|
+
node.nodeName !== "undefined" &&
|
|
558
|
+
typeof node.nodeName == "string"
|
|
559
|
+
) {
|
|
560
|
+
if (readNodeName !== '' &&
|
|
561
|
+
readNodeName !== null &&
|
|
562
|
+
readNodeName !== undefined
|
|
563
|
+
) {
|
|
564
|
+
topic = `${node.nodeName}/${readNodeName}/${device}`;
|
|
565
|
+
} else {
|
|
566
|
+
topic = `${node.nodeName}/${device}`;
|
|
567
|
+
}
|
|
568
|
+
} else {
|
|
569
|
+
if (readNodeName !== '' &&
|
|
570
|
+
readNodeName !== null &&
|
|
571
|
+
readNodeName !== undefined
|
|
572
|
+
) {
|
|
573
|
+
topic = `BITPOOL_BACNET_GATEWAY/${readNodeName}/${device}`;
|
|
574
|
+
} else {
|
|
575
|
+
topic = `BITPOOL_BACNET_GATEWAY/${device}`;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
msgg.topic = topic;
|
|
580
|
+
msgg.payload = structuredObject;
|
|
581
|
+
node.send(msgg);
|
|
582
|
+
msgg = {};
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
|
|
469
588
|
sendSimpleMqtt = function (values, readNodeName) {
|
|
470
589
|
let devices = Object.keys(values);
|
|
471
590
|
devices.forEach(function (device) {
|
package/bacnet_read.html
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
readDevices: { value: [] },
|
|
21
21
|
devicesToRead: [],
|
|
22
22
|
object_property_simplePayload: { value: false },
|
|
23
|
+
object_property_simpleWithStatus: { value: false },
|
|
23
24
|
object_property_fullObject: { value: true },
|
|
24
25
|
},
|
|
25
26
|
inputs: 1,
|
|
@@ -96,9 +97,6 @@
|
|
|
96
97
|
mounted() {
|
|
97
98
|
let app = this;
|
|
98
99
|
this.getData(true);
|
|
99
|
-
if (!node.reloadTimer) {
|
|
100
|
-
node.reloadTimer = setInterval(() => app.getData(false), 7000);
|
|
101
|
-
}
|
|
102
100
|
|
|
103
101
|
$("#readlist-file-upload").on("change", function (event) {
|
|
104
102
|
const input = event.target.files[0];
|
|
@@ -408,29 +406,31 @@
|
|
|
408
406
|
return ele.address == ipAddress && ele.deviceId == deviceId;
|
|
409
407
|
}
|
|
410
408
|
});
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
409
|
+
if (device) {
|
|
410
|
+
const deviceName = device.deviceName;
|
|
411
|
+
const points = Object.keys(deviceObject);
|
|
412
|
+
for (point in points) {
|
|
413
|
+
csvContent +=
|
|
414
|
+
ipAddress +
|
|
415
|
+
"," +
|
|
416
|
+
deviceId +
|
|
417
|
+
"," +
|
|
418
|
+
deviceName +
|
|
419
|
+
"," +
|
|
420
|
+
points[point] +
|
|
421
|
+
"," +
|
|
422
|
+
deviceObject[points[point]].meta.objectId.type +
|
|
423
|
+
"\r\n";
|
|
424
|
+
|
|
425
|
+
if (parseInt(point) == points.length - 1 && parseInt(key) == keys.length - 1) {
|
|
426
|
+
// last iteration
|
|
427
|
+
var encodedUri = encodeURI(csvContent);
|
|
428
|
+
var link = document.createElement("a");
|
|
429
|
+
link.setAttribute("href", encodedUri);
|
|
430
|
+
link.setAttribute("download", "pointslist.csv");
|
|
431
|
+
document.body.appendChild(link);
|
|
432
|
+
link.click();
|
|
433
|
+
}
|
|
434
434
|
}
|
|
435
435
|
}
|
|
436
436
|
}
|
|
@@ -661,28 +661,22 @@
|
|
|
661
661
|
}
|
|
662
662
|
|
|
663
663
|
const devicePoints = Object.keys(device);
|
|
664
|
-
let pointIndex = 0;
|
|
665
|
-
doPoints(pointIndex);
|
|
666
664
|
|
|
667
|
-
|
|
665
|
+
for (let pointIndex = 0; pointIndex <= devicePoints.length; pointIndex++) {
|
|
668
666
|
let pointName = devicePoints[pointIndex];
|
|
669
667
|
let pointObject = device[pointName];
|
|
670
668
|
|
|
671
669
|
//formatting json payload, still in progress
|
|
672
670
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
671
|
+
if (pointObject) {
|
|
672
|
+
exportJson[key][pointName] = {
|
|
673
|
+
meta: pointObject.meta,
|
|
674
|
+
objectName: pointObject.objectName,
|
|
675
|
+
displayName: pointObject.displayName,
|
|
676
|
+
};
|
|
677
|
+
}
|
|
680
678
|
|
|
681
|
-
if (pointIndex
|
|
682
|
-
//more points to read for device
|
|
683
|
-
pointIndex++;
|
|
684
|
-
doPoints(pointIndex);
|
|
685
|
-
} else if (pointIndex == devicePoints.length - 1) {
|
|
679
|
+
if (pointIndex == devicePoints.length - 1) {
|
|
686
680
|
//all points have been iterated
|
|
687
681
|
|
|
688
682
|
if (deviceIndex < devicesToExport.length - 1) {
|
|
@@ -873,6 +867,8 @@
|
|
|
873
867
|
|
|
874
868
|
document.getElementById("node-input-object_property_simplePayload").checked = node.object_property_simplePayload;
|
|
875
869
|
document.getElementById("node-input-object_property_simplePayload").onclick = handleCheckboxClick;
|
|
870
|
+
document.getElementById("node-input-object_property_simpleWithStatus").checked = node.object_property_simpleWithStatus;
|
|
871
|
+
document.getElementById("node-input-object_property_simpleWithStatus").onclick = handleCheckboxClick;
|
|
876
872
|
document.getElementById("node-input-object_property_fullObject").checked = node.object_property_fullObject;
|
|
877
873
|
document.getElementById("node-input-object_property_fullObject").onclick = handleCheckboxClick;
|
|
878
874
|
|
|
@@ -894,14 +890,16 @@
|
|
|
894
890
|
|
|
895
891
|
function handleCheckboxClick() {
|
|
896
892
|
if (this.id == "node-input-object_property_simplePayload") {
|
|
897
|
-
document.getElementById("node-input-object_property_fullObject").checked =
|
|
898
|
-
|
|
899
|
-
|
|
893
|
+
document.getElementById("node-input-object_property_fullObject").checked = false;
|
|
894
|
+
document.getElementById("node-input-object_property_simpleWithStatus").checked = false;
|
|
895
|
+
}
|
|
896
|
+
if (this.id == "node-input-object_property_simpleWithStatus") {
|
|
897
|
+
document.getElementById("node-input-object_property_fullObject").checked = false;
|
|
898
|
+
document.getElementById("node-input-object_property_simplePayload").checked = false;
|
|
900
899
|
}
|
|
901
900
|
if (this.id == "node-input-object_property_fullObject") {
|
|
902
|
-
document.getElementById("node-input-object_property_simplePayload").checked =
|
|
903
|
-
|
|
904
|
-
).checked;
|
|
901
|
+
document.getElementById("node-input-object_property_simplePayload").checked = false;
|
|
902
|
+
document.getElementById("node-input-object_property_simpleWithStatus").checked = false;
|
|
905
903
|
}
|
|
906
904
|
}
|
|
907
905
|
|
|
@@ -948,25 +946,13 @@
|
|
|
948
946
|
},
|
|
949
947
|
oneditsave: function () {
|
|
950
948
|
let node = this;
|
|
951
|
-
if (node.vm.$data.devices) node.devices = node.vm.$data.devices;
|
|
952
949
|
if (node.vm.$data.readDevices) node.readDevices = node.vm.$data.readDevices;
|
|
953
950
|
if (node.vm.$data.pointsToRead) node.pointsToRead = node.vm.$data.pointsToRead;
|
|
954
|
-
//clear reload data function
|
|
955
|
-
if (node.reloadTimer) {
|
|
956
|
-
clearInterval(node.reloadTimer);
|
|
957
|
-
node.reloadTimer = null;
|
|
958
|
-
}
|
|
959
951
|
},
|
|
960
952
|
oneditcancel: function () {
|
|
961
953
|
let node = this;
|
|
962
|
-
if (node.vm.$data.devices) node.devices = node.vm.$data.devices;
|
|
963
954
|
if (node.vm.$data.readDevices) node.readDevices = node.vm.$data.readDevices;
|
|
964
955
|
if (node.vm.$data.pointsToRead) node.pointsToRead = node.vm.$data.pointsToRead;
|
|
965
|
-
//clear reload data function
|
|
966
|
-
if (node.reloadTimer) {
|
|
967
|
-
clearInterval(node.reloadTimer);
|
|
968
|
-
node.reloadTimer = null;
|
|
969
|
-
}
|
|
970
956
|
},
|
|
971
957
|
});
|
|
972
958
|
</script>
|
|
@@ -1264,6 +1250,21 @@
|
|
|
1264
1250
|
</label>
|
|
1265
1251
|
</div>
|
|
1266
1252
|
|
|
1253
|
+
<div class="objectPropertiesLabel">
|
|
1254
|
+
<label
|
|
1255
|
+
for="node-input-object_property_simpleWithStatus"
|
|
1256
|
+
style="padding-left: 4px; width: auto; align-items: start;"
|
|
1257
|
+
class="objectPropertiesLabel">
|
|
1258
|
+
<i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_property_simpleWithStatus"></span>
|
|
1259
|
+
<input
|
|
1260
|
+
style="margin-left: 5px;"
|
|
1261
|
+
class=" objectProp"
|
|
1262
|
+
type="checkbox"
|
|
1263
|
+
id="node-input-object_property_simpleWithStatus" />
|
|
1264
|
+
<a style="white-space: nowrap; padding-left: 20px;">Simple With Status</a>
|
|
1265
|
+
</label>
|
|
1266
|
+
</div>
|
|
1267
|
+
|
|
1267
1268
|
<div class="objectPropertiesLabel">
|
|
1268
1269
|
<label
|
|
1269
1270
|
for="node-input-object_property_fullObject"
|
|
@@ -1278,6 +1279,7 @@
|
|
|
1278
1279
|
<a style="white-space: nowrap; padding-left: 20px;">Full Object</a>
|
|
1279
1280
|
</label>
|
|
1280
1281
|
</div>
|
|
1282
|
+
|
|
1281
1283
|
</div>
|
|
1282
1284
|
</div>
|
|
1283
1285
|
|
package/bacnet_read.js
CHANGED
|
@@ -22,6 +22,7 @@ module.exports = function (RED) {
|
|
|
22
22
|
this.nodeName = config.name;
|
|
23
23
|
|
|
24
24
|
this.object_property_simplePayload = config.object_property_simplePayload;
|
|
25
|
+
this.object_property_simpleWithStatus = config.object_property_simpleWithStatus;
|
|
25
26
|
this.object_property_fullObject = config.object_property_fullObject;
|
|
26
27
|
|
|
27
28
|
|
|
@@ -62,6 +63,7 @@ module.exports = function (RED) {
|
|
|
62
63
|
options: readConfig,
|
|
63
64
|
objectPropertyType: {
|
|
64
65
|
simplePayload: node.object_property_simplePayload,
|
|
66
|
+
simpleWithStatus: node.object_property_simpleWithStatus,
|
|
65
67
|
fullObject: node.object_property_fullObject
|
|
66
68
|
},
|
|
67
69
|
outputType: {
|