@bitpoolos/edge-bacnet 1.4.1 → 1.4.3
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 +43 -0
- package/README.md +2 -0
- package/bacnet_gateway.js +222 -194
- package/bacnet_read.html +122 -63
- package/bacnet_read.js +49 -6
- package/bacnet_server.js +77 -106
- package/bitpool_inject.html +173 -1
- package/bitpool_inject.js +47 -24
- package/package.json +1 -1
- package/resources/style.css +12 -1
- package/treeBuilder.js +53 -1
package/bitpool_inject.html
CHANGED
|
@@ -42,7 +42,124 @@
|
|
|
42
42
|
</div>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
<div class="form-row" style="display: flex; width: fit-content; flex-wrap: nowrap; flex-direction: row; padding-top: 10px; margin-left: auto; margin-right: auto;">
|
|
46
|
+
|
|
47
|
+
<div
|
|
48
|
+
id="node-input-object_properties_group"
|
|
49
|
+
style="display: flex; align-items: flex-start; flex-direction: column;">
|
|
50
|
+
<label
|
|
51
|
+
for="node-input-object_properties_group"
|
|
52
|
+
style="display: flex; align-items: center; white-space: nowrap; text-decoration: underline;"
|
|
53
|
+
>
|
|
54
|
+
Object Properties:
|
|
55
|
+
</label>
|
|
56
|
+
|
|
57
|
+
<div class="objectPropertiesLabel">
|
|
58
|
+
<label
|
|
59
|
+
for="node-input-object_property_simplePayload"
|
|
60
|
+
style="padding-left: 4px; width: auto; align-items: start;"
|
|
61
|
+
class="objectPropertiesLabel">
|
|
62
|
+
<i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_property_simplePayload"></span>
|
|
63
|
+
<input
|
|
64
|
+
style="margin-left: 5px;"
|
|
65
|
+
class=" objectProp"
|
|
66
|
+
type="checkbox"
|
|
67
|
+
id="node-input-object_property_simplePayload" />
|
|
68
|
+
<a style="white-space: nowrap; padding-left: 20px;">Simple Payload</a>
|
|
69
|
+
</label>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div class="objectPropertiesLabel">
|
|
73
|
+
<label
|
|
74
|
+
for="node-input-object_property_simpleWithStatus"
|
|
75
|
+
style="padding-left: 4px; width: auto; align-items: start;"
|
|
76
|
+
class="objectPropertiesLabel">
|
|
77
|
+
<i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_property_simpleWithStatus"></span>
|
|
78
|
+
<input
|
|
79
|
+
style="margin-left: 5px;"
|
|
80
|
+
class=" objectProp"
|
|
81
|
+
type="checkbox"
|
|
82
|
+
id="node-input-object_property_simpleWithStatus" />
|
|
83
|
+
<a style="white-space: nowrap; padding-left: 20px;">Simple With Status</a>
|
|
84
|
+
</label>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<div class="objectPropertiesLabel">
|
|
88
|
+
<label
|
|
89
|
+
for="node-input-object_property_fullObject"
|
|
90
|
+
style="padding-left: 4px; width: auto; align-items: start;"
|
|
91
|
+
class="objectPropertiesLabel">
|
|
92
|
+
<i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.object_property_fullObject"></span>
|
|
93
|
+
<input
|
|
94
|
+
style="margin-left: 5px;"
|
|
95
|
+
class=" objectProp"
|
|
96
|
+
type="checkbox"
|
|
97
|
+
id="node-input-object_property_fullObject" />
|
|
98
|
+
<a style="white-space: nowrap; padding-left: 20px;">Full Object</a>
|
|
99
|
+
</label>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
</div>
|
|
103
|
+
<div
|
|
104
|
+
id="node-input-msgType"
|
|
105
|
+
style="display: flex; align-items: flex-start; flex-direction: column; padding-left: 50px;">
|
|
106
|
+
<label for="node-input-msgType" style="text-decoration: underline;"> Message type: </label>
|
|
107
|
+
<!-- class= checkbox-round -->
|
|
108
|
+
<div style="display: flex; flex-direction: row; align-items: flex-start;">
|
|
109
|
+
<input
|
|
110
|
+
class="checkbox-round"
|
|
111
|
+
type="checkbox"
|
|
112
|
+
id="node-input-json"
|
|
113
|
+
style="width: 13px; margin-left: 5px;" /><label
|
|
114
|
+
for="node-input-json"
|
|
115
|
+
style="padding-left: 20px; width: fit-content;"
|
|
116
|
+
>Block per device</label
|
|
117
|
+
>
|
|
118
|
+
</div>
|
|
119
|
+
<div style="display: flex; flex-direction: row; align-items: flex-start;">
|
|
120
|
+
<input
|
|
121
|
+
class="checkbox-round"
|
|
122
|
+
type="checkbox"
|
|
123
|
+
id="node-input-mqtt"
|
|
124
|
+
style="width: 13px; margin-left: 5px;" /><label
|
|
125
|
+
for="node-input-mqtt"
|
|
126
|
+
style="padding-left: 20px; width: fit-content;"
|
|
127
|
+
>Individual msgs</label
|
|
128
|
+
>
|
|
129
|
+
</div>
|
|
130
|
+
<div style="display: flex; flex-direction: row; align-items: flex-start;">
|
|
131
|
+
<input
|
|
132
|
+
class="checkbox-round"
|
|
133
|
+
type="checkbox"
|
|
134
|
+
id="node-input-pointJson"
|
|
135
|
+
style="width: 13px; margin-left: 5px;" /><label
|
|
136
|
+
for="node-input-pointJson"
|
|
137
|
+
style="padding-left: 20px; width: fit-content;"
|
|
138
|
+
>Individual JSON</label
|
|
139
|
+
>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
<div class="injectHeading" style="margin-top: 20px;">
|
|
147
|
+
<a>Topic Properties</a>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<div class="objectPropertiesLabel" style="margin-top: 20px;">
|
|
151
|
+
<label
|
|
152
|
+
for="node-input-useDeviceName"
|
|
153
|
+
style="padding-left: 4px; width: auto; align-items: start;"
|
|
154
|
+
class="objectPropertiesLabel">
|
|
155
|
+
<i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.useDeviceName"></span>
|
|
156
|
+
<input
|
|
157
|
+
style="margin-left: 5px;"
|
|
158
|
+
class=" objectProp"
|
|
159
|
+
type="checkbox"
|
|
160
|
+
id="node-input-useDeviceName" />
|
|
161
|
+
<a style="white-space: nowrap; padding-left: 20px;">Use device name in topic</a>
|
|
162
|
+
</label>
|
|
46
163
|
</div>
|
|
47
164
|
|
|
48
165
|
<div class="injectHeading" style="margin-top: 20px;">
|
|
@@ -373,6 +490,13 @@
|
|
|
373
490
|
payloadType: { value: "date" },
|
|
374
491
|
doPoll: { value: true },
|
|
375
492
|
doDiscover: { value: false },
|
|
493
|
+
json: { value: false },
|
|
494
|
+
mqtt: { value: false },
|
|
495
|
+
pointJson: { value: true },
|
|
496
|
+
object_property_simplePayload: { value: false },
|
|
497
|
+
object_property_simpleWithStatus: { value: false },
|
|
498
|
+
object_property_fullObject: { value: true },
|
|
499
|
+
useDeviceName: { value: true },
|
|
376
500
|
},
|
|
377
501
|
icon: "bitpool.svg",
|
|
378
502
|
inputs: 0,
|
|
@@ -669,10 +793,28 @@
|
|
|
669
793
|
$("#inject-time-type-select").trigger("change");
|
|
670
794
|
$("#inject-time-interval-time-start").trigger("change");
|
|
671
795
|
|
|
796
|
+
document.getElementById("node-input-object_property_simplePayload").checked = node.object_property_simplePayload;
|
|
797
|
+
document.getElementById("node-input-object_property_simplePayload").onclick = handlePayloadCheckboxClick;
|
|
798
|
+
document.getElementById("node-input-object_property_simpleWithStatus").checked = node.object_property_simpleWithStatus;
|
|
799
|
+
document.getElementById("node-input-object_property_simpleWithStatus").onclick = handlePayloadCheckboxClick;
|
|
800
|
+
document.getElementById("node-input-object_property_fullObject").checked = node.object_property_fullObject;
|
|
801
|
+
document.getElementById("node-input-object_property_fullObject").onclick = handlePayloadCheckboxClick;
|
|
802
|
+
|
|
803
|
+
document.getElementById("node-input-useDeviceName").checked = node.useDeviceName;
|
|
804
|
+
|
|
672
805
|
|
|
673
806
|
document.getElementById("node-input-doDiscover").onclick = handleCheckboxClick;
|
|
674
807
|
document.getElementById("node-input-doPoll").onclick = handleCheckboxClick;
|
|
675
808
|
|
|
809
|
+
document.getElementById("node-input-json").checked = node.json;
|
|
810
|
+
document.getElementById("node-input-json").onclick = handleMsgTypeClick;
|
|
811
|
+
document.getElementById("node-input-mqtt").checked = node.mqtt;
|
|
812
|
+
document.getElementById("node-input-mqtt").onclick = handleMsgTypeClick;
|
|
813
|
+
document.getElementById("node-input-pointJson").checked = node.pointJson;
|
|
814
|
+
document.getElementById("node-input-pointJson").onclick = handleMsgTypeClick;
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
|
|
676
818
|
function handleCheckboxClick() {
|
|
677
819
|
if (this.id == "node-input-doDiscover") {
|
|
678
820
|
document.getElementById("node-input-doPoll").checked = false;
|
|
@@ -682,6 +824,36 @@
|
|
|
682
824
|
}
|
|
683
825
|
}
|
|
684
826
|
|
|
827
|
+
function handlePayloadCheckboxClick() {
|
|
828
|
+
if (this.id == "node-input-object_property_simplePayload") {
|
|
829
|
+
document.getElementById("node-input-object_property_fullObject").checked = false;
|
|
830
|
+
document.getElementById("node-input-object_property_simpleWithStatus").checked = false;
|
|
831
|
+
}
|
|
832
|
+
if (this.id == "node-input-object_property_simpleWithStatus") {
|
|
833
|
+
document.getElementById("node-input-object_property_fullObject").checked = false;
|
|
834
|
+
document.getElementById("node-input-object_property_simplePayload").checked = false;
|
|
835
|
+
}
|
|
836
|
+
if (this.id == "node-input-object_property_fullObject") {
|
|
837
|
+
document.getElementById("node-input-object_property_simplePayload").checked = false;
|
|
838
|
+
document.getElementById("node-input-object_property_simpleWithStatus").checked = false;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
function handleMsgTypeClick() {
|
|
843
|
+
if (this.id == "node-input-json") {
|
|
844
|
+
document.getElementById("node-input-mqtt").checked = false;
|
|
845
|
+
document.getElementById("node-input-pointJson").checked = false;
|
|
846
|
+
}
|
|
847
|
+
if (this.id == "node-input-mqtt") {
|
|
848
|
+
document.getElementById("node-input-json").checked = false;
|
|
849
|
+
document.getElementById("node-input-pointJson").checked = false;
|
|
850
|
+
}
|
|
851
|
+
if (this.id == "node-input-pointJson") {
|
|
852
|
+
document.getElementById("node-input-json").checked = false;
|
|
853
|
+
document.getElementById("node-input-mqtt").checked = false;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
|
|
685
857
|
},
|
|
686
858
|
oneditsave: function () {
|
|
687
859
|
var repeat = "";
|
package/bitpool_inject.js
CHANGED
|
@@ -19,28 +19,28 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
module.exports = function (RED) {
|
|
23
23
|
"use strict";
|
|
24
|
-
const {scheduleTask} = require("cronosjs");
|
|
24
|
+
const { scheduleTask } = require("cronosjs");
|
|
25
25
|
|
|
26
26
|
function BitpoolInjectNode(n) {
|
|
27
|
-
RED.nodes.createNode(this,n);
|
|
27
|
+
RED.nodes.createNode(this, n);
|
|
28
28
|
|
|
29
29
|
/* Handle legacy */
|
|
30
|
-
if(!Array.isArray(n.props)){
|
|
30
|
+
if (!Array.isArray(n.props)) {
|
|
31
31
|
n.props = [];
|
|
32
32
|
n.props.push({
|
|
33
|
-
p:'payload',
|
|
34
|
-
v:n.payload,
|
|
35
|
-
vt:n.payloadType
|
|
33
|
+
p: 'payload',
|
|
34
|
+
v: n.payload,
|
|
35
|
+
vt: n.payloadType
|
|
36
36
|
});
|
|
37
37
|
n.props.push({
|
|
38
|
-
p:'topic',
|
|
39
|
-
v:n.topic,
|
|
40
|
-
vt:'str'
|
|
38
|
+
p: 'topic',
|
|
39
|
+
v: n.topic,
|
|
40
|
+
vt: 'str'
|
|
41
41
|
});
|
|
42
42
|
} else {
|
|
43
|
-
for (var i=0,l=n.props.length; i<l; i++) {
|
|
43
|
+
for (var i = 0, l = n.props.length; i < l; i++) {
|
|
44
44
|
if (n.props[i].p === 'payload' && !n.props[i].hasOwnProperty('v')) {
|
|
45
45
|
n.props[i].v = n.payload;
|
|
46
46
|
n.props[i].vt = n.payloadType;
|
|
@@ -56,6 +56,17 @@
|
|
|
56
56
|
this.once = n.once;
|
|
57
57
|
this.doPoll = n.doPoll;
|
|
58
58
|
this.doDiscover = n.doDiscover;
|
|
59
|
+
|
|
60
|
+
this.object_property_simplePayload = n.object_property_simplePayload;
|
|
61
|
+
this.object_property_simpleWithStatus = n.object_property_simpleWithStatus;
|
|
62
|
+
this.object_property_fullObject = n.object_property_fullObject;
|
|
63
|
+
|
|
64
|
+
this.useDeviceName = n.useDeviceName;
|
|
65
|
+
|
|
66
|
+
this.json = n.json;
|
|
67
|
+
this.mqtt = n.mqtt;
|
|
68
|
+
this.pointJson = n.pointJson;
|
|
69
|
+
|
|
59
70
|
this.onceDelay = (n.onceDelay || 0.1) * 1000;
|
|
60
71
|
this.interval_id = null;
|
|
61
72
|
this.cronjob = null;
|
|
@@ -68,7 +79,7 @@
|
|
|
68
79
|
prop.exp = RED.util.prepareJSONataExpression(val, node);
|
|
69
80
|
}
|
|
70
81
|
catch (err) {
|
|
71
|
-
node.error(RED._("inject.errors.invalid-expr", {error:err.message}));
|
|
82
|
+
node.error(RED._("inject.errors.invalid-expr", { error: err.message }));
|
|
72
83
|
prop.exp = null;
|
|
73
84
|
}
|
|
74
85
|
}
|
|
@@ -83,27 +94,39 @@
|
|
|
83
94
|
if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
|
|
84
95
|
this.repeat = this.repeat * 1000;
|
|
85
96
|
this.debug(RED._("inject.repeat", this));
|
|
86
|
-
this.interval_id = setInterval(function() {
|
|
97
|
+
this.interval_id = setInterval(function () {
|
|
87
98
|
node.emit("input", {});
|
|
88
99
|
}, this.repeat);
|
|
89
100
|
} else if (this.crontab) {
|
|
90
101
|
this.debug(RED._("inject.crontab", this));
|
|
91
|
-
this.cronjob = scheduleTask(this.crontab,() => { node.emit("input", {})});
|
|
102
|
+
this.cronjob = scheduleTask(this.crontab, () => { node.emit("input", {}) });
|
|
92
103
|
}
|
|
93
104
|
};
|
|
94
105
|
|
|
95
106
|
if (this.once) {
|
|
96
|
-
this.onceTimeout = setTimeout(
|
|
97
|
-
node.emit("input",{});
|
|
107
|
+
this.onceTimeout = setTimeout(function () {
|
|
108
|
+
node.emit("input", {});
|
|
98
109
|
node.repeaterSetup();
|
|
99
110
|
}, this.onceDelay);
|
|
100
111
|
} else {
|
|
101
112
|
node.repeaterSetup();
|
|
102
113
|
}
|
|
103
114
|
|
|
104
|
-
this.on("input", function(msg, send, done) {
|
|
115
|
+
this.on("input", function (msg, send, done) {
|
|
105
116
|
msg.doDiscover = node.doDiscover;
|
|
106
117
|
msg.doPoll = node.doPoll;
|
|
118
|
+
|
|
119
|
+
msg.simplePayload = node.object_property_simplePayload;
|
|
120
|
+
msg.simpleWithStatus = node.object_property_simpleWithStatus;
|
|
121
|
+
msg.fullObject = node.object_property_fullObject;
|
|
122
|
+
|
|
123
|
+
msg.json = node.json;
|
|
124
|
+
msg.mqtt = node.mqtt;
|
|
125
|
+
msg.pointJson = node.pointJson;
|
|
126
|
+
|
|
127
|
+
msg.useDeviceName = node.useDeviceName;
|
|
128
|
+
|
|
129
|
+
|
|
107
130
|
var errors = [];
|
|
108
131
|
var props = this.props;
|
|
109
132
|
if (msg.__user_inject_props__ && Array.isArray(msg.__user_inject_props__)) {
|
|
@@ -124,14 +147,14 @@
|
|
|
124
147
|
var val = RED.util.evaluateJSONataExpression(exp, msg);
|
|
125
148
|
RED.util.setMessageProperty(msg, property, val, true);
|
|
126
149
|
}
|
|
127
|
-
catch
|
|
150
|
+
catch (err) {
|
|
128
151
|
errors.push(err.message);
|
|
129
152
|
}
|
|
130
153
|
}
|
|
131
154
|
return;
|
|
132
155
|
}
|
|
133
156
|
try {
|
|
134
|
-
RED.util.setMessageProperty(msg,property,RED.util.evaluateNodeProperty(value, valueType, this, msg),true);
|
|
157
|
+
RED.util.setMessageProperty(msg, property, RED.util.evaluateNodeProperty(value, valueType, this, msg), true);
|
|
135
158
|
} catch (err) {
|
|
136
159
|
errors.push(err.toString());
|
|
137
160
|
}
|
|
@@ -146,9 +169,9 @@
|
|
|
146
169
|
});
|
|
147
170
|
}
|
|
148
171
|
|
|
149
|
-
RED.nodes.registerType("Bitpool-Inject",BitpoolInjectNode);
|
|
172
|
+
RED.nodes.registerType("Bitpool-Inject", BitpoolInjectNode);
|
|
150
173
|
|
|
151
|
-
BitpoolInjectNode.prototype.close = function() {
|
|
174
|
+
BitpoolInjectNode.prototype.close = function () {
|
|
152
175
|
if (this.onceTimeout) {
|
|
153
176
|
clearTimeout(this.onceTimeout);
|
|
154
177
|
}
|
|
@@ -160,7 +183,7 @@
|
|
|
160
183
|
}
|
|
161
184
|
};
|
|
162
185
|
|
|
163
|
-
RED.httpAdmin.post("/inject/:id", RED.auth.needsPermission("inject.write"), function(req,res) {
|
|
186
|
+
RED.httpAdmin.post("/inject/:id", RED.auth.needsPermission("inject.write"), function (req, res) {
|
|
164
187
|
var node = RED.nodes.getNode(req.params.id);
|
|
165
188
|
if (node != null) {
|
|
166
189
|
try {
|
|
@@ -170,9 +193,9 @@
|
|
|
170
193
|
node.receive();
|
|
171
194
|
}
|
|
172
195
|
res.sendStatus(200);
|
|
173
|
-
} catch(err) {
|
|
196
|
+
} catch (err) {
|
|
174
197
|
res.sendStatus(500);
|
|
175
|
-
node.error(RED._("inject.failed",{error:err.toString()}));
|
|
198
|
+
node.error(RED._("inject.failed", { error: err.toString() }));
|
|
176
199
|
}
|
|
177
200
|
} else {
|
|
178
201
|
res.sendStatus(404);
|
package/package.json
CHANGED
package/resources/style.css
CHANGED
|
@@ -15,6 +15,16 @@
|
|
|
15
15
|
|
|
16
16
|
/* Read node styles */
|
|
17
17
|
|
|
18
|
+
.refreshReadListButton {
|
|
19
|
+
border: none;
|
|
20
|
+
border-radius: 40px;
|
|
21
|
+
height: 35px;
|
|
22
|
+
width: 35px;
|
|
23
|
+
& i {
|
|
24
|
+
color: #6c757d !important;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
18
28
|
.p-treenode-label {
|
|
19
29
|
color: black;
|
|
20
30
|
width: 100%;
|
|
@@ -150,6 +160,8 @@
|
|
|
150
160
|
float: right;
|
|
151
161
|
display: flex;
|
|
152
162
|
align-items: center;
|
|
163
|
+
padding: 5px;
|
|
164
|
+
font-weight: bold;
|
|
153
165
|
}
|
|
154
166
|
.removeAllDevicesButton:hover {
|
|
155
167
|
background-color: #d5d5d5;
|
|
@@ -247,7 +259,6 @@
|
|
|
247
259
|
z-index: 10;
|
|
248
260
|
}
|
|
249
261
|
|
|
250
|
-
|
|
251
262
|
.context-menu {
|
|
252
263
|
--mouse-x: 0;
|
|
253
264
|
--mouse-y: 0;
|
package/treeBuilder.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const { Store_Config } = require("./common");
|
|
2
|
+
const { BacnetDevice } = require("./bacnet_device");
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* The `treeBuilder` class is responsible for building and processing the network tree structure.
|
|
@@ -111,6 +112,42 @@ class treeBuilder {
|
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
114
|
|
|
115
|
+
addEmptyIpRootDevice(childDevice) {
|
|
116
|
+
|
|
117
|
+
const ipAddress = this.getDeviceIpAddress(childDevice);
|
|
118
|
+
|
|
119
|
+
let deviceIndex = this.deviceList.findIndex(ele => ele.address === ipAddress && ele.deviceId === null && ele.deviceName === ipAddress && ele.displayName === ipAddress);
|
|
120
|
+
|
|
121
|
+
if (deviceIndex === -1) {
|
|
122
|
+
let newDevice = {
|
|
123
|
+
address: ipAddress,
|
|
124
|
+
isMstp: false,
|
|
125
|
+
deviceId: null,
|
|
126
|
+
maxApdu: childDevice.getMaxApdu(),
|
|
127
|
+
segmentation: childDevice.getSegmentation(),
|
|
128
|
+
vendorId: childDevice.getVendorId(),
|
|
129
|
+
lastSeen: null,
|
|
130
|
+
deviceName: ipAddress,
|
|
131
|
+
pointsList: [],
|
|
132
|
+
pointListUpdateTs: null,
|
|
133
|
+
manualDiscoveryMode: false,
|
|
134
|
+
pointListRetryCount: 0,
|
|
135
|
+
priorityQueueIsActive: false,
|
|
136
|
+
priorityQueue: [],
|
|
137
|
+
lastPriorityQueueTS: null,
|
|
138
|
+
childDevices: [childDevice.getDeviceId()],
|
|
139
|
+
parentDeviceId: null,
|
|
140
|
+
displayName: ipAddress,
|
|
141
|
+
protocolServicesSupported: [],
|
|
142
|
+
isProtocolServicesSet: false,
|
|
143
|
+
isInitialQuery: true,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
let newBacnetDevice = new BacnetDevice(true, newDevice);
|
|
147
|
+
this.deviceList.push(newBacnetDevice);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
114
151
|
/**
|
|
115
152
|
* Process the points of a device and add them to the render list.
|
|
116
153
|
*
|
|
@@ -124,7 +161,7 @@ class treeBuilder {
|
|
|
124
161
|
*/
|
|
125
162
|
async processDevicePoints(device, deviceObject, deviceName, ipAddress, deviceId, index) {
|
|
126
163
|
// Initialize the list of children points
|
|
127
|
-
|
|
164
|
+
let children = [];
|
|
128
165
|
|
|
129
166
|
// Process each point in the device object
|
|
130
167
|
for (const pointName in deviceObject) {
|
|
@@ -171,6 +208,7 @@ class treeBuilder {
|
|
|
171
208
|
parentDeviceId: device.getDeviceId(),
|
|
172
209
|
showAdded: false,
|
|
173
210
|
bacnetType: point.meta.objectId.type,
|
|
211
|
+
bacnetInstance: point.meta.objectId.instance,
|
|
174
212
|
};
|
|
175
213
|
}
|
|
176
214
|
|
|
@@ -305,7 +343,21 @@ class treeBuilder {
|
|
|
305
343
|
} else {
|
|
306
344
|
mstpNetworkFolder.children[mstpDeviceIndex] = newDeviceEntry;
|
|
307
345
|
}
|
|
346
|
+
} else {
|
|
347
|
+
//no parent found in render list
|
|
348
|
+
|
|
349
|
+
if (parentDeviceId !== null) {
|
|
350
|
+
let parentDeviceListIndex = this.deviceList.findIndex(ele => ele.getDeviceId == parentDeviceId);
|
|
351
|
+
|
|
352
|
+
if (parentDeviceListIndex !== -1) {
|
|
353
|
+
let parentDevice = this.deviceList[parentDeviceListIndex];
|
|
354
|
+
this.addRootDeviceFolder(parentDevice, parentDevice.getDeviceName(), parentDeviceListIndex, parentDevice.getAddress(), parentDeviceId);
|
|
355
|
+
}
|
|
356
|
+
} else {
|
|
357
|
+
this.addEmptyIpRootDevice(device);
|
|
358
|
+
}
|
|
308
359
|
}
|
|
360
|
+
|
|
309
361
|
} else {
|
|
310
362
|
// Add the new device entry to the root of the render list
|
|
311
363
|
if (foundIndex === -1) {
|