@bitpoolos/edge-bacnet 1.3.2 → 1.4.1
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 +41 -0
- package/bacnet_client.js +27 -33
- package/bacnet_gateway.js +140 -21
- package/bacnet_read.html +61 -60
- package/bacnet_read.js +2 -0
- package/bacnet_server.js +146 -18
- 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,4 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
|
+
## [1.4.1] - 09-07-2024
|
|
3
|
+
|
|
4
|
+
### Summary
|
|
5
|
+
|
|
6
|
+
Bug fixes
|
|
7
|
+
- incorrect variable used in doRead try catch
|
|
8
|
+
- setmaxlisteners on bacnet server event parent class
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## [1.4.0] - 05-07-2024
|
|
12
|
+
|
|
13
|
+
### Summary
|
|
14
|
+
|
|
15
|
+
Fixed read list export for sites with large point counts.
|
|
16
|
+
|
|
17
|
+
Removed auto tree reload on read node UI. UI tree must be manually reloaded now.
|
|
18
|
+
|
|
19
|
+
Fixed export to CSV bug.
|
|
20
|
+
|
|
21
|
+
Fixed state array text not found bug
|
|
22
|
+
|
|
23
|
+
Removed unecessary debug.
|
|
24
|
+
|
|
25
|
+
Updated required json saved to node JSON file.
|
|
26
|
+
|
|
27
|
+
Added github pull requests
|
|
28
|
+
- Added create object and delete object to bacnet server
|
|
29
|
+
- Added write property to bacnet server
|
|
30
|
+
|
|
31
|
+
Added Simple With Status read property type.
|
|
32
|
+
- This type sends a msg.payload that consists of {presentValue, timestamp, status}
|
|
33
|
+
- Status is currently online and offline
|
|
34
|
+
|
|
35
|
+
Changed inject node to only 1 selectable type of inject (Discover or Poll)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## [1.3.2] - 18-06-2024
|
|
39
|
+
|
|
40
|
+
### Summary
|
|
41
|
+
|
|
42
|
+
Bug fix for API request URL paths. Updated for using node-red host setting.
|
|
2
43
|
|
|
3
44
|
## [1.3.1] - 06-06-2024
|
|
4
45
|
|
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][request.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
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
pointList: [],
|
|
19
19
|
pointsToRead: { value: {} },
|
|
20
20
|
readDevices: { value: [] },
|
|
21
|
-
devicesToRead: [],
|
|
22
21
|
object_property_simplePayload: { value: false },
|
|
22
|
+
object_property_simpleWithStatus: { value: false },
|
|
23
23
|
object_property_fullObject: { value: true },
|
|
24
24
|
},
|
|
25
25
|
inputs: 1,
|
|
@@ -96,9 +96,6 @@
|
|
|
96
96
|
mounted() {
|
|
97
97
|
let app = this;
|
|
98
98
|
this.getData(true);
|
|
99
|
-
if (!node.reloadTimer) {
|
|
100
|
-
node.reloadTimer = setInterval(() => app.getData(false), 7000);
|
|
101
|
-
}
|
|
102
99
|
|
|
103
100
|
$("#readlist-file-upload").on("change", function (event) {
|
|
104
101
|
const input = event.target.files[0];
|
|
@@ -408,29 +405,31 @@
|
|
|
408
405
|
return ele.address == ipAddress && ele.deviceId == deviceId;
|
|
409
406
|
}
|
|
410
407
|
});
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
408
|
+
if (device) {
|
|
409
|
+
const deviceName = device.deviceName;
|
|
410
|
+
const points = Object.keys(deviceObject);
|
|
411
|
+
for (point in points) {
|
|
412
|
+
csvContent +=
|
|
413
|
+
ipAddress +
|
|
414
|
+
"," +
|
|
415
|
+
deviceId +
|
|
416
|
+
"," +
|
|
417
|
+
deviceName +
|
|
418
|
+
"," +
|
|
419
|
+
points[point] +
|
|
420
|
+
"," +
|
|
421
|
+
deviceObject[points[point]].meta.objectId.type +
|
|
422
|
+
"\r\n";
|
|
423
|
+
|
|
424
|
+
if (parseInt(point) == points.length - 1 && parseInt(key) == keys.length - 1) {
|
|
425
|
+
// last iteration
|
|
426
|
+
var encodedUri = encodeURI(csvContent);
|
|
427
|
+
var link = document.createElement("a");
|
|
428
|
+
link.setAttribute("href", encodedUri);
|
|
429
|
+
link.setAttribute("download", "pointslist.csv");
|
|
430
|
+
document.body.appendChild(link);
|
|
431
|
+
link.click();
|
|
432
|
+
}
|
|
434
433
|
}
|
|
435
434
|
}
|
|
436
435
|
}
|
|
@@ -661,28 +660,22 @@
|
|
|
661
660
|
}
|
|
662
661
|
|
|
663
662
|
const devicePoints = Object.keys(device);
|
|
664
|
-
let pointIndex = 0;
|
|
665
|
-
doPoints(pointIndex);
|
|
666
663
|
|
|
667
|
-
|
|
664
|
+
for (let pointIndex = 0; pointIndex <= devicePoints.length; pointIndex++) {
|
|
668
665
|
let pointName = devicePoints[pointIndex];
|
|
669
666
|
let pointObject = device[pointName];
|
|
670
667
|
|
|
671
668
|
//formatting json payload, still in progress
|
|
672
669
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
670
|
+
if (pointObject) {
|
|
671
|
+
exportJson[key][pointName] = {
|
|
672
|
+
meta: pointObject.meta,
|
|
673
|
+
objectName: pointObject.objectName,
|
|
674
|
+
displayName: pointObject.displayName,
|
|
675
|
+
};
|
|
676
|
+
}
|
|
680
677
|
|
|
681
|
-
if (pointIndex
|
|
682
|
-
//more points to read for device
|
|
683
|
-
pointIndex++;
|
|
684
|
-
doPoints(pointIndex);
|
|
685
|
-
} else if (pointIndex == devicePoints.length - 1) {
|
|
678
|
+
if (pointIndex == devicePoints.length - 1) {
|
|
686
679
|
//all points have been iterated
|
|
687
680
|
|
|
688
681
|
if (deviceIndex < devicesToExport.length - 1) {
|
|
@@ -873,6 +866,8 @@
|
|
|
873
866
|
|
|
874
867
|
document.getElementById("node-input-object_property_simplePayload").checked = node.object_property_simplePayload;
|
|
875
868
|
document.getElementById("node-input-object_property_simplePayload").onclick = handleCheckboxClick;
|
|
869
|
+
document.getElementById("node-input-object_property_simpleWithStatus").checked = node.object_property_simpleWithStatus;
|
|
870
|
+
document.getElementById("node-input-object_property_simpleWithStatus").onclick = handleCheckboxClick;
|
|
876
871
|
document.getElementById("node-input-object_property_fullObject").checked = node.object_property_fullObject;
|
|
877
872
|
document.getElementById("node-input-object_property_fullObject").onclick = handleCheckboxClick;
|
|
878
873
|
|
|
@@ -894,14 +889,16 @@
|
|
|
894
889
|
|
|
895
890
|
function handleCheckboxClick() {
|
|
896
891
|
if (this.id == "node-input-object_property_simplePayload") {
|
|
897
|
-
document.getElementById("node-input-object_property_fullObject").checked =
|
|
898
|
-
|
|
899
|
-
|
|
892
|
+
document.getElementById("node-input-object_property_fullObject").checked = false;
|
|
893
|
+
document.getElementById("node-input-object_property_simpleWithStatus").checked = false;
|
|
894
|
+
}
|
|
895
|
+
if (this.id == "node-input-object_property_simpleWithStatus") {
|
|
896
|
+
document.getElementById("node-input-object_property_fullObject").checked = false;
|
|
897
|
+
document.getElementById("node-input-object_property_simplePayload").checked = false;
|
|
900
898
|
}
|
|
901
899
|
if (this.id == "node-input-object_property_fullObject") {
|
|
902
|
-
document.getElementById("node-input-object_property_simplePayload").checked =
|
|
903
|
-
|
|
904
|
-
).checked;
|
|
900
|
+
document.getElementById("node-input-object_property_simplePayload").checked = false;
|
|
901
|
+
document.getElementById("node-input-object_property_simpleWithStatus").checked = false;
|
|
905
902
|
}
|
|
906
903
|
}
|
|
907
904
|
|
|
@@ -948,25 +945,13 @@
|
|
|
948
945
|
},
|
|
949
946
|
oneditsave: function () {
|
|
950
947
|
let node = this;
|
|
951
|
-
if (node.vm.$data.devices) node.devices = node.vm.$data.devices;
|
|
952
948
|
if (node.vm.$data.readDevices) node.readDevices = node.vm.$data.readDevices;
|
|
953
949
|
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
950
|
},
|
|
960
951
|
oneditcancel: function () {
|
|
961
952
|
let node = this;
|
|
962
|
-
if (node.vm.$data.devices) node.devices = node.vm.$data.devices;
|
|
963
953
|
if (node.vm.$data.readDevices) node.readDevices = node.vm.$data.readDevices;
|
|
964
954
|
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
955
|
},
|
|
971
956
|
});
|
|
972
957
|
</script>
|
|
@@ -1264,6 +1249,21 @@
|
|
|
1264
1249
|
</label>
|
|
1265
1250
|
</div>
|
|
1266
1251
|
|
|
1252
|
+
<div class="objectPropertiesLabel">
|
|
1253
|
+
<label
|
|
1254
|
+
for="node-input-object_property_simpleWithStatus"
|
|
1255
|
+
style="padding-left: 4px; width: auto; align-items: start;"
|
|
1256
|
+
class="objectPropertiesLabel">
|
|
1257
|
+
<i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_property_simpleWithStatus"></span>
|
|
1258
|
+
<input
|
|
1259
|
+
style="margin-left: 5px;"
|
|
1260
|
+
class=" objectProp"
|
|
1261
|
+
type="checkbox"
|
|
1262
|
+
id="node-input-object_property_simpleWithStatus" />
|
|
1263
|
+
<a style="white-space: nowrap; padding-left: 20px;">Simple With Status</a>
|
|
1264
|
+
</label>
|
|
1265
|
+
</div>
|
|
1266
|
+
|
|
1267
1267
|
<div class="objectPropertiesLabel">
|
|
1268
1268
|
<label
|
|
1269
1269
|
for="node-input-object_property_fullObject"
|
|
@@ -1278,6 +1278,7 @@
|
|
|
1278
1278
|
<a style="white-space: nowrap; padding-left: 20px;">Full Object</a>
|
|
1279
1279
|
</label>
|
|
1280
1280
|
</div>
|
|
1281
|
+
|
|
1281
1282
|
</div>
|
|
1282
1283
|
</div>
|
|
1283
1284
|
|
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: {
|