@bitpoolos/edge-bacnet 1.2.4 → 1.2.6

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.
@@ -8,634 +8,861 @@
8
8
  <link href="resources/@bitpoolos/edge-bacnet/primeicons.css" rel="stylesheet" />
9
9
 
10
10
  <script>
11
- //custom script loader to ensure dependencies load every time
12
- (function () {
13
- LoadScripts();
14
-
15
- function LoadScripts(async) {
16
- if (async === undefined) {
17
- async = false;
18
- }
19
- var scripts = [];
20
- var _scripts = [
21
- 'resources/@bitpoolos/edge-bacnet/vue.global.prod.js',
22
- 'resources/@bitpoolos/edge-bacnet/core.min.js',
23
- 'resources/@bitpoolos/edge-bacnet/confirmdialog.min.js',
24
- 'resources/@bitpoolos/edge-bacnet/confirmationservice.min.js'
25
- ];
26
-
27
- if (async) {
28
- LoadScriptsAsync(_scripts, scripts)
29
- } else {
30
- LoadScriptsSync(_scripts, scripts)
31
- }
32
- }
11
+ //custom script loader to ensure dependencies load every time
12
+ (function () {
13
+ LoadScripts();
14
+
15
+ function LoadScripts(async) {
16
+ if (async === undefined) {
17
+ async = false;
18
+ }
19
+ var scripts = [];
20
+ var _scripts = [
21
+ "resources/@bitpoolos/edge-bacnet/vue.global.prod.js",
22
+ "resources/@bitpoolos/edge-bacnet/core.min.js",
23
+ "resources/@bitpoolos/edge-bacnet/confirmdialog.min.js",
24
+ "resources/@bitpoolos/edge-bacnet/confirmationservice.min.js",
25
+ ];
26
+
27
+ if (async) {
28
+ LoadScriptsAsync(_scripts, scripts);
29
+ } else {
30
+ LoadScriptsSync(_scripts, scripts);
31
+ }
32
+ }
33
33
 
34
- // what you are looking for :
35
- function LoadScriptsSync(_scripts, scripts) {
36
-
37
- var x = 0;
38
- var loopArray = function (_scripts, scripts) {
39
- // call itself
40
- loadScript(_scripts[x], scripts[x], function () {
41
- // set x to next item
42
- x++;
43
- // any more items in array?
44
- if (x < _scripts.length) {
45
- loopArray(_scripts, scripts);
46
- }
47
- });
48
- }
34
+ // what you are looking for :
35
+ function LoadScriptsSync(_scripts, scripts) {
36
+ var x = 0;
37
+ var loopArray = function (_scripts, scripts) {
38
+ // call itself
39
+ loadScript(_scripts[x], scripts[x], function () {
40
+ // set x to next item
41
+ x++;
42
+ // any more items in array?
43
+ if (x < _scripts.length) {
49
44
  loopArray(_scripts, scripts);
50
- }
51
-
52
- // async load as in your code
53
- function LoadScriptsAsync(_scripts, scripts) {
54
- for (var i = 0; i < _scripts.length; i++) {
55
- loadScript(_scripts[i], scripts[i], function () { });
56
- }
57
- }
45
+ }
46
+ });
47
+ };
48
+ loopArray(_scripts, scripts);
49
+ }
58
50
 
59
- // load script function with callback to handle synchronicity
60
- function loadScript(src, script, callback) {
51
+ // async load as in your code
52
+ function LoadScriptsAsync(_scripts, scripts) {
53
+ for (var i = 0; i < _scripts.length; i++) {
54
+ loadScript(_scripts[i], scripts[i], function () {});
55
+ }
56
+ }
61
57
 
62
- script = document.createElement('script');
63
- script.onerror = function () {
64
- // handling error when loading script
65
- console.log('Error - could not load BACnet node HTML dependencies')
66
- }
67
- script.onload = function () {
68
- callback();
69
- }
70
- script.src = src;
71
- document.getElementsByTagName('head')[0].appendChild(script);
72
- }
73
- })();
58
+ // load script function with callback to handle synchronicity
59
+ function loadScript(src, script, callback) {
60
+ script = document.createElement("script");
61
+ script.onerror = function () {
62
+ // handling error when loading script
63
+ console.log("Error - could not load BACnet node HTML dependencies");
64
+ };
65
+ script.onload = function () {
66
+ callback();
67
+ };
68
+ script.src = src;
69
+ document.getElementsByTagName("head")[0].appendChild(script);
70
+ }
71
+ })();
74
72
  </script>
75
73
 
76
74
  <script type="text/javascript">
77
- class NodeService {
78
- getNetworkData() {
79
- return fetch('/bitpool-bacnet-data/getNetworkTree').then(res => res.json());
80
- };
81
- rebuildDataModel() {
82
- return fetch('/bitpool-bacnet-data/rebuildDataModel').then(res => res.json());
83
- };
84
- clearBacnetServerPoints() {
85
- return fetch('/bitpool-bacnet-data/clearBacnetServerPoints').then(res => res.json());
86
- };
87
- };
88
- RED.nodes.registerType('Bacnet-Gateway', {
89
- category: 'Bitpool BACnet',
90
- color: '#00aeef',
91
- defaults: {
92
- name: {value: ""},
93
- local_device_address: {value: "", required: true},
94
- apduTimeout: {value: 6000},
95
- roundDecimal: {value: 2},
96
- local_device_port: {value: 47808, required: true},
97
- apduSize: {value: "5", required: true},
98
- maxSegments: {value: "0x50", required: true},
99
- retries: {value: "5", required: true},
100
- broadCastAddr: {value: "255.255.255.255", required: true},
101
- toLogIam: {value: true},
102
- discover_polling_schedule: {value: ""},
103
- discover_polling_schedule_value: {value: "1", required: true},
104
- discover_polling_schedule_options: {value: "Minutes", required: true},
105
- device_id_range_enabled: {value: false},
106
- device_id_range_start: {value: 0},
107
- device_id_range_end: {value: 4194303},
108
- deviceId: {value: 817001, required: true},
109
- manual_instance_range_enabled: {value: false},
110
- manual_instance_range_start: {value: 0},
111
- manual_instance_range_end: {value: 10000},
112
- logErrorToConsole: {value: false},
113
- serverEnabled: {value: false},
114
- device_read_schedule: {value: ""},
115
- device_read_schedule_value: {value: "1", required: true},
116
- device_read_schedule_options: {value: "Minutes", required: true}
75
+ class NodeService {
76
+ getNetworkData() {
77
+ return fetch("/bitpool-bacnet-data/getNetworkTree").then((res) => res.json());
78
+ }
79
+ rebuildDataModel() {
80
+ return fetch("/bitpool-bacnet-data/rebuildDataModel").then((res) => res.json());
81
+ }
82
+ clearBacnetServerPoints() {
83
+ return fetch("/bitpool-bacnet-data/clearBacnetServerPoints").then((res) => res.json());
84
+ }
85
+ getBacnetServerPoints() {
86
+ return fetch('/bitpool-bacnet-data/getBacnetServerPoints').then(res => res.json());
87
+ }
88
+ }
89
+ RED.nodes.registerType("Bacnet-Gateway", {
90
+ category: "Bitpool BACnet",
91
+ color: "#00aeef",
92
+ defaults: {
93
+ name: { value: "" },
94
+ local_device_address: { value: "", required: true },
95
+ apduTimeout: { value: 6000 },
96
+ roundDecimal: { value: 2 },
97
+ local_device_port: { value: 47808, required: true },
98
+ apduSize: { value: "5", required: true },
99
+ maxSegments: { value: "0x50", required: true },
100
+ retries: { value: "5", required: true },
101
+ broadCastAddr: { value: "255.255.255.255", required: true },
102
+ toLogIam: { value: false },
103
+ discover_polling_schedule: { value: "60" },
104
+ discover_polling_schedule_value: { value: "1", required: true },
105
+ discover_polling_schedule_options: { value: "Minutes", required: true },
106
+ deviceId: { value: 817001, required: true },
107
+ manual_instance_range_enabled: { value: false },
108
+ manual_instance_range_start: { value: 0 },
109
+ manual_instance_range_end: { value: 10000 },
110
+ logErrorToConsole: { value: false },
111
+ serverEnabled: { value: false },
112
+ device_read_schedule: { value: "60" },
113
+ device_read_schedule_value: { value: "1", required: true },
114
+ device_read_schedule_options: { value: "Minutes", required: true },
115
+ deviceRangeRegisters: { value: [] },
116
+ },
117
+ networkInterfaces: [],
118
+ inputs: 1,
119
+ outputs: 1,
120
+ icon: "bitpool.svg",
121
+ label: function () {
122
+ return this.name || "gateway";
123
+ },
124
+ paletteLabel: function () {
125
+ return "gateway";
126
+ },
127
+ oneditprepare: function () {
128
+ let node = this;
129
+
130
+ let tabs = RED.tabs.create({
131
+ id: "node-input-read-tabs",
132
+ onchange: function (tab) {
133
+ $("#node-input-tabs-content").children().hide();
134
+ $("#" + tab.id).show();
117
135
  },
118
- networkInterfaces: [],
119
- inputs: 1,
120
- outputs: 1,
121
- icon: "bitpool.svg",
122
- label: function () {
123
- return this.name || "gateway";
136
+ });
137
+
138
+ tabs.addTab({
139
+ id: "read-properties-tab",
140
+ label: "Gateway",
141
+ });
142
+
143
+ tabs.addTab({
144
+ id: "read-discover-tab",
145
+ label: "Discovery",
146
+ });
147
+
148
+ tabs.addTab({
149
+ id: "read-server-tab",
150
+ label: "Server",
151
+ });
152
+
153
+ if (node.networkInterfaces && node.networkInterfaces.length > 0) {
154
+ let nicSelector = document.getElementById("node-input-local_device_address");
155
+ node.networkInterfaces.forEach(function (option) {
156
+ nicSelector.options[nicSelector.options.length] = option;
157
+ });
158
+ nicSelector.value = node.local_device_address;
159
+ }
160
+
161
+ function queryAdapters() {
162
+ let nicSelector = document.getElementById("node-input-local_device_address");
163
+ $.ajax({
164
+ url: "/bitpool-bacnet-data/getNetworkInterfaces",
165
+ success: function (data) {
166
+ let keys = Object.keys(data);
167
+
168
+ for (const key in keys) {
169
+ let nicName = keys[key];
170
+ let ipAddr = data[keys[key]][0];
171
+ let text = nicName + " : " + ipAddr;
172
+ if (!node.networkInterfaces) node.networkInterfaces = [];
173
+ let found = node.networkInterfaces.findIndex((ele) => ele.text == text && ele.value == ipAddr);
174
+ if (found == -1) {
175
+ let newOption = new Option(text, ipAddr);
176
+ nicSelector.options[nicSelector.options.length] = newOption;
177
+ node.networkInterfaces.push(newOption);
178
+ }
179
+ }
180
+ nicSelector.value = node.local_device_address;
181
+ },
182
+ timeout: 10000,
183
+ });
184
+ }
185
+
186
+ queryAdapters();
187
+
188
+ function setManualInstanceRangeState(state) {
189
+ let deviceIdRangeStart = $("#node-input-manual_instance_range_start");
190
+ let deviceIdRangeEnd = $("#node-input-manual_instance_range_end");
191
+ if (state == true) {
192
+ deviceIdRangeStart.removeAttr("readonly");
193
+ deviceIdRangeEnd.removeAttr("readonly");
194
+ } else if (state == false) {
195
+ deviceIdRangeStart.attr("readonly", true);
196
+ deviceIdRangeEnd.attr("readonly", true);
197
+ }
198
+ }
199
+
200
+ setManualInstanceRangeState(node.manual_instance_range_enabled);
201
+
202
+ $("#node-input-manual_instance_range_enabled").change(function (e) {
203
+ setManualInstanceRangeState(this.checked);
204
+ });
205
+
206
+ if (node.vm1 == undefined) {
207
+ const confirmDialog = document.createElement("p-confirm-dialog");
208
+ document.getElementById("serverParent").appendChild(confirmDialog);
209
+ //document.getElementById("clearServerContainer").appendChild(confirmDialog);
210
+
211
+ }
212
+
213
+ const { createApp, ref, onMounted } = Vue;
214
+ const ConfirmDialog = primevue.confirmdialog;
215
+ const ConfirmationService = primevue.confirmationservice;
216
+ const ListBox = primevue.listbox;
217
+
218
+ //prime vue app
219
+ const App = {
220
+ data() {
221
+ return {
222
+ nodeService: ref(new NodeService()),
223
+ serverObjects: ref([]),
224
+ selectedServerObject: ref()
225
+ };
124
226
  },
125
- paletteLabel: function () {
126
- return "gateway";
227
+ mounted() {
228
+ this.getServerObjects();
127
229
  },
128
- oneditprepare: function () {
129
- let node = this;
130
-
131
- let tabs = RED.tabs.create(
132
- {
133
- id: "node-input-read-tabs",
134
- onchange: function (tab) {
135
- $("#node-input-tabs-content").children().hide()
136
- $("#" + tab.id).show()
137
- }
230
+ methods: {
231
+ confirmAll(event) {
232
+ let app = this;
233
+ this.$confirm.require({
234
+ message: "Do you want to clear all the BACnet server points? This action is not reversible",
235
+ header: "Delete Confirmation",
236
+ icon: "pi pi-info-circle",
237
+ acceptClass: "p-button-danger",
238
+ accept: () => {
239
+ //handle accept
240
+ this.nodeService.clearBacnetServerPoints().then(function() {
241
+ app.getServerObjects();
138
242
  });
139
-
140
- tabs.addTab(
141
- {
142
- id: "read-properties-tab",
143
- label: "Gateway"
144
- });
145
-
146
- tabs.addTab(
147
- {
148
- id: "read-discover-tab",
149
- label: "Discovery"
150
- });
151
-
152
- tabs.addTab(
153
- {
154
- id: "read-server-tab",
155
- label: "Server"
156
- });
157
-
158
- if (node.networkInterfaces && node.networkInterfaces.length > 0) {
159
- let nicSelector = document.getElementById("node-input-local_device_address");
160
- node.networkInterfaces.forEach(function (option) {
161
- nicSelector.options[nicSelector.options.length] = option;
162
- });
163
- nicSelector.value = node.local_device_address
164
- }
165
-
166
- function queryAdapters() {
167
- let nicSelector = document.getElementById("node-input-local_device_address");
168
- $.ajax({
169
- url: '/bitpool-bacnet-data/getNetworkInterfaces',
170
- success: function (data) {
171
- let keys = Object.keys(data);
172
-
173
- for (const key in keys) {
174
- let nicName = keys[key];
175
- let ipAddr = data[keys[key]][0];
176
- let text = nicName + ' : ' + ipAddr;
177
- if (!node.networkInterfaces) node.networkInterfaces = [];
178
- let found = node.networkInterfaces.findIndex(ele => ele.text == text && ele.value == ipAddr);
179
- if (found == -1) {
180
- let newOption = new Option(text, ipAddr);
181
- nicSelector.options[nicSelector.options.length] = newOption;
182
- node.networkInterfaces.push(newOption);
183
- }
184
- }
185
- nicSelector.value = node.local_device_address;
186
- },
187
- timeout: 10000
188
- });
189
- }
190
-
191
- queryAdapters();
192
-
193
- function setDeviceIdRangeState(state) {
194
- let deviceIdRangeStart = $("#node-input-device_id_range_start");
195
- let deviceIdRangeEnd = $("#node-input-device_id_range_end");
196
- if(state == true) {
197
- deviceIdRangeStart.removeAttr("readonly");
198
- deviceIdRangeEnd.removeAttr("readonly");
199
- } else if(state == false) {
200
- deviceIdRangeStart.attr("readonly", true);
201
- deviceIdRangeEnd.attr("readonly", true);
202
- }
203
- }
204
-
205
- setDeviceIdRangeState(node.device_id_range_enabled);
206
-
207
- $("#node-input-device_id_range_enabled").change(function(e) {
208
- setDeviceIdRangeState(this.checked);
209
- });
210
-
211
- function setManualInstanceRangeState(state) {
212
- let deviceIdRangeStart = $("#node-input-manual_instance_range_start");
213
- let deviceIdRangeEnd = $("#node-input-manual_instance_range_end");
214
- if(state == true) {
215
- deviceIdRangeStart.removeAttr("readonly");
216
- deviceIdRangeEnd.removeAttr("readonly");
217
- } else if(state == false) {
218
- deviceIdRangeStart.attr("readonly", true);
219
- deviceIdRangeEnd.attr("readonly", true);
220
- }
221
- }
222
-
223
- setManualInstanceRangeState(node.manual_instance_range_enabled);
224
-
225
- $("#node-input-manual_instance_range_enabled").change(function(e) {
226
- setManualInstanceRangeState(this.checked);
243
+ },
244
+ reject: () => {
245
+ //handle reject
246
+ },
227
247
  });
228
-
229
- if(node.vm == undefined) {
230
- const confirmDialog = document.createElement('p-confirm-dialog');
231
- document.getElementById("clearServerContainer").appendChild(confirmDialog);
232
- }
233
-
234
- const {createApp, ref, onMounted} = Vue;
235
- const ConfirmDialog = primevue.confirmdialog;
236
- const ConfirmationService = primevue.confirmationservice;
237
-
238
- //prime vue app
239
- const App = {
240
- data() {
241
- return {
242
- nodeService: ref(new NodeService())
243
- }
244
- },
245
- methods: {
246
- confirm(event) {
247
- this.$confirm.require({
248
- message: 'Do you want to clear all the BACnet server points? This action is not reversible',
249
- header: 'Delete Confirmation',
250
- icon: 'pi pi-info-circle',
251
- acceptClass: 'p-button-danger',
252
- accept: () => {
253
- //handle accept
254
- this.nodeService.clearBacnetServerPoints();
255
- },
256
- reject: () => {
257
- //handle reject
258
- }
259
- });
260
- }
261
- },
262
- components: {
263
- "p-button": primevue.button,
264
- "p-confirm-dialog": primevue.confirmdialog,
265
- "p-confirm-popup": primevue.confirmpopup
266
- }
267
- };
268
-
269
- let vueapp = createApp(App);
270
- vueapp.use(primevue.config.default);
271
- vueapp.use(primevue.confirmpopup);
272
- vueapp.use(primevue.confirmationservice);
273
- node.vm1 = vueapp.mount("#clearServerContainer");
274
-
275
- $("#file-upload").on("change", function(event) {
276
- const input = event.target.files[0];
277
- const reader = new FileReader();
278
-
279
- reader.onload = function (e) {
280
- const text = e.target.result;
281
-
282
- let jsonPayload = JSON.parse(text);
283
-
248
+ },
249
+ confirm(json) {
250
+ this.$confirm.require({
251
+ message: 'Do you want to clear this BACnet server point? This action is not reversible',
252
+ header: 'Delete Confirmation',
253
+ icon: 'pi pi-info-circle',
254
+ acceptClass: 'p-button-danger',
255
+ accept: () => {
256
+ //handle accept
257
+ let app = this;
284
258
  $.ajax({
285
259
  type: "POST",
286
- url: '/bitpool-bacnet-data/updateDeviceList',
260
+ url: '/bitpool-bacnet-data/clearBacnetServerPoint',
287
261
  dataType: 'json',
288
262
  contentType: 'application/json',
289
- data: JSON.stringify(jsonPayload),
263
+ data: JSON.stringify(json),
290
264
  success: function (result) {
265
+ app.getServerObjects();
291
266
  },
292
267
  timeout: 10000
293
268
  });
294
-
295
- };
296
-
297
- reader.readAsText(input);
269
+ },
270
+ reject: () => {
271
+ //handle reject
272
+ }
298
273
  });
274
+ },
275
+ getServerObjects() {
276
+ let app = this;
277
+ this.nodeService.getBacnetServerPoints().then(function (result) {
278
+ app.serverObjects = result;
279
+ })
280
+ },
281
+ formatObjectName(name) {
282
+ //return shortened point name if longer than 50 characters
283
+ if(name.length > 45) {
284
+ return name.slice(0, 45).concat("...");
285
+ }
286
+ return name;
287
+ }
288
+ },
289
+ components: {
290
+ "p-button": primevue.button,
291
+ "p-confirm-dialog": primevue.confirmdialog,
292
+ "p-confirm-popup": primevue.confirmpopup,
293
+ },
294
+ };
295
+
296
+ let vueapp = createApp(App);
297
+ vueapp.use(primevue.config.default);
298
+ vueapp.use(primevue.confirmpopup);
299
+ vueapp.use(primevue.confirmationservice);
300
+ node.vm1 = vueapp.mount("#serverParent");
301
+
302
+ $("#file-upload").on("change", function (event) {
303
+ const input = event.target.files[0];
304
+ const reader = new FileReader();
305
+
306
+ reader.onload = function (e) {
307
+ const text = e.target.result;
308
+
309
+ let jsonPayload = JSON.parse(text);
310
+
311
+ $.ajax({
312
+ type: "POST",
313
+ url: "/bitpool-bacnet-data/updateDeviceList",
314
+ dataType: "json",
315
+ contentType: "application/json",
316
+ data: JSON.stringify(jsonPayload),
317
+ success: function (result) {},
318
+ timeout: 10000,
319
+ });
320
+ };
299
321
 
300
- $("#file-export").click(function(params) {
301
- $.ajax({
302
- url: '/bitpool-bacnet-data/getDeviceList',
303
- success: function (deviceList) {
304
- let data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(deviceList));
305
- let aEle = document.getElementById("exportJSON");
306
- aEle.setAttribute("href", "data:" + data);
307
- aEle.setAttribute("download", "bitpool-bacnet-devices.json");
308
- aEle.click();
309
- },
310
- timeout: 10000
322
+ reader.readAsText(input);
323
+ });
324
+
325
+ $("#file-export").click(function (params) {
326
+ $.ajax({
327
+ url: "/bitpool-bacnet-data/getDeviceList",
328
+ success: function (deviceList) {
329
+ let data = "text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(deviceList));
330
+ let aEle = document.getElementById("exportJSON");
331
+ aEle.setAttribute("href", "data:" + data);
332
+ aEle.setAttribute("download", "bitpool-bacnet-devices.json");
333
+ aEle.click();
334
+ },
335
+ timeout: 10000,
336
+ });
337
+ });
338
+
339
+ //device scan range matrix
340
+ $("#node-input-deviceIdRangeMatrix-container")
341
+ .css("min-width", "350px")
342
+ .editableList({
343
+ addItem: function (row, index, data) {
344
+ row.css({ overflow: "none", whiteSpace: "nowrap" });
345
+ let rowData = {};
346
+ if (data && typeof data.enabled == "boolean" && typeof data.start == "string" && typeof data.end == "string") {
347
+ if (data.enabled === true) {
348
+ rowData.enabled = "checked";
349
+ } else if (data.enabled === false) {
350
+ rowData.enabled = "";
351
+ }
352
+ rowData.start = data.start;
353
+ rowData.end = data.end;
354
+ } else {
355
+ rowData.enabled = "";
356
+ rowData.start = "";
357
+ rowData.end = "";
358
+ }
359
+
360
+ let fragment = document.createDocumentFragment();
361
+ let htmlRow = `
362
+ <div class="form-row deviceIdRangeEntry" id="node-input-device_id_range">
363
+ <label for="node-input-device_id_range_entry"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.device_id_range_entry"></span>Enabled</label>
364
+ <input type="checkbox" id="node-input-device_id_range_entry_enabled" style="width: auto;" ${rowData.enabled} />
365
+ <a style="padding-left: 60px;">Start: </a><input type="number" id="node-input-device_id_range_entry_start" style="width: 125px;" min="0" max="4194303" value="${rowData.start}" />
366
+ <a style="padding-left: 35px;">End: </a><input type="number" id="node-input-device_id_range_entry_end" style="width: 125px;" min="1" max="4194303" value="${rowData.end}" />
367
+ </div>`;
368
+
369
+ $(htmlRow).appendTo(fragment);
370
+ row[0].appendChild(fragment);
371
+ document.getElementById("node-input-reg-block-count").innerHTML = $(
372
+ "#node-input-deviceIdRangeMatrix-container"
373
+ ).editableList("length");
374
+ },
375
+ removeItem: function (data) {
376
+ document.getElementById("node-input-reg-block-count").innerHTML = $(
377
+ "#node-input-deviceIdRangeMatrix-container"
378
+ ).editableList("length");
379
+ },
380
+ removable: true,
381
+ scrollOnAdd: false,
382
+ header: $("<div style='display:flex; padding:10px 10px 0px 5px; column-gap: 10px'>").append(
383
+ $.parseHTML(
384
+ "<div><p>Count:</p></div><div style='color: gray'><label id='node-input-reg-block-count'>0</label> <span style='padding-left: 85px;'>Device ID Range(s)</span> </div>"
385
+ )
386
+ ),
387
+ buttons: [
388
+ {
389
+ label: "json",
390
+ icon: "fa fa-share",
391
+ title: "Export tags as JSON to browser",
392
+ click: function (evt) {
393
+ var deviceRangeRegisters = $("#node-input-deviceIdRangeMatrix-container").editableList("items");
394
+ var mapItems = [];
395
+ deviceRangeRegisters.each(function (i) {
396
+ var registerMap = $(this);
397
+ var mapItem = {
398
+ enabled: registerMap.find("#node-input-device_id_range_entry_enabled").val(),
399
+ start: registerMap.find("#node-input-device_id_range_entry_start").val(),
400
+ end: registerMap.find("#node-input-device_id_range_entry_end").val(),
401
+ };
402
+ mapItems.push(mapItem);
311
403
  });
312
- });
313
- },
314
- oneditsave: function (test) {
315
- let node = this;
316
-
317
- document.getElementById("node-input-discover_polling_schedule").value = getTimePeriodInSeconds(
318
- document.getElementById("node-input-discover_polling_schedule_value").value,
319
- document.getElementById("node-input-discover_polling_schedule_options").value
320
- );
321
-
322
- document.getElementById("node-input-device_read_schedule").value = getTimePeriodInSeconds(
323
- document.getElementById("node-input-device_read_schedule_value").value,
324
- document.getElementById("node-input-device_read_schedule_options").value
325
- );
326
- }
327
- });
328
-
329
- function getTimePeriodInSeconds(value, interval) {
330
- switch (interval) {
331
- case "Seconds":
332
- return value;
333
- break;
334
- case "Minutes":
335
- return value * 60;
336
- break;
337
- case "Hours":
338
- return value * 3600;
339
- break;
340
- case "Days":
341
- return value * 86400;
342
- break;
343
- default:
344
- // code block
404
+ var oMyBlob = new Blob(
405
+ [
406
+ JSON.stringify(mapItems, null, 0)
407
+ .replaceAll(/\[{/gi, "[\n{")
408
+ .replaceAll(/}\]/gi, "}\n]")
409
+ .replaceAll(/},/gi, "},\n")
410
+ .replaceAll(/{/gi, " {"),
411
+ ],
412
+ { type: "text/json" }
413
+ );
414
+ window.open(URL.createObjectURL(oMyBlob));
415
+ },
416
+ },
417
+ {
418
+ label: "delete",
419
+ icon: "fa-regular fa-trash-can",
420
+ title: "Delete all registers",
421
+ click: function (evt) {
422
+ $("#node-input-deviceIdRangeMatrix-container").editableList("empty");
423
+ document.getElementById("node-input-reg-block-count").innerHTML = 0;
424
+ },
425
+ },
426
+ ],
427
+ });
428
+
429
+ if (node.deviceRangeRegisters.length > 0) {
430
+ for (var i = 0; i < node.deviceRangeRegisters.length; i++) {
431
+ $("#node-input-deviceIdRangeMatrix-container").editableList("addItem", node.deviceRangeRegisters[i]);
345
432
  }
433
+ } else {
434
+ $("#node-input-deviceIdRangeMatrix-container").editableList("addItem", {
435
+ enabled: true,
436
+ start: "0",
437
+ end: "4194303",
438
+ });
439
+ }
440
+
441
+ document.getElementById("node-input-reg-block-count").innerHTML = node.deviceRangeRegisters.length;
442
+ },
443
+ oneditsave: function () {
444
+ let node = this;
445
+
446
+ document.getElementById("node-input-discover_polling_schedule").value = getTimePeriodInSeconds(
447
+ document.getElementById("node-input-discover_polling_schedule_value").value,
448
+ document.getElementById("node-input-discover_polling_schedule_options").value
449
+ );
450
+
451
+ document.getElementById("node-input-device_read_schedule").value = getTimePeriodInSeconds(
452
+ document.getElementById("node-input-device_read_schedule_value").value,
453
+ document.getElementById("node-input-device_read_schedule_options").value
454
+ );
455
+
456
+ node.deviceRangeRegisters = [];
457
+ let deviceRanges = $("#node-input-deviceIdRangeMatrix-container").editableList("items");
458
+ deviceRanges.each(function (i) {
459
+ let map = $(this);
460
+ let mapItem = {
461
+ enabled: map.find("#node-input-device_id_range_entry_enabled").is(":checked"),
462
+ start: map.find("#node-input-device_id_range_entry_start").val(),
463
+ end: map.find("#node-input-device_id_range_entry_end").val(),
464
+ };
465
+ node.deviceRangeRegisters.push(mapItem);
466
+ });
467
+ },
468
+ });
469
+
470
+ function getTimePeriodInSeconds(value, interval) {
471
+ switch (interval) {
472
+ case "Seconds":
473
+ return value;
474
+ break;
475
+ case "Minutes":
476
+ return value * 60;
477
+ break;
478
+ case "Hours":
479
+ return value * 3600;
480
+ break;
481
+ case "Days":
482
+ return value * 86400;
483
+ break;
484
+ default:
485
+ // code block
346
486
  }
347
-
487
+ }
348
488
  </script>
349
489
 
350
490
  <script type="text/html" data-template-name="Bacnet-Gateway">
351
- <style>
352
- .deviceButton {
353
- width: -webkit-fill-available;
354
- background: space;
355
- background-color: transparent !important;
356
- color: inherit;
357
- border: none;
358
- display: flex;
359
- align-items: center;
360
- padding-top: 20px;
361
- }
362
- .point {
363
- padding-left: 50px
364
- }
365
- .pointButton {
366
- color: inherit;
367
- border: none;
368
- display: flex;
369
- align-items: center;
370
- }
371
- .networkTreeContent {
372
- margin-top: 20px;
373
- margin-left: 50px;
374
- }
375
- .p-confirm-dialog-accept > .p-button-label, .bacnetServerRebuildSchedule_clearButton > .p-button-label {
376
- color: white;
377
- }
378
- .red-ui-editor label {
379
- font-size: 12px;
380
- }
381
- .bacnetServerRebuildSchedule_clearButton {
382
- box-shadow: 0 0 0 0.2rem #edacac !important;
383
- width: 200px;
384
- border-radius: 3px;
385
- margin-left: 140px !important;
386
- }
387
- .clear_server_span {
388
- width: 0px;
389
- }
390
- .read_server_parent_div {
391
- display: flex;
392
- align-items: center;
393
- justify-content: space-around;
394
- }
395
- button {
396
- height: 34px;
397
- border-radius: 5px !important;
398
- }
399
- .inputStyle {
400
- color: var(--red-ui-workspace-button-color-hover) !important;
401
- background: var(--red-ui-workspace-button-background-hover);
402
- border: 1px solid var(--red-ui-secondary-border-color);
403
- border-radius: 5px !important;
404
- }
405
- input[type="file"] {
406
- display: none !important;
407
- }
408
- .custom-file-upload {
409
- border: 1px solid var(--red-ui-secondary-border-color);
410
- border-radius: 5px !important;
411
- padding: 6px 12px;
412
- cursor: pointer;
413
- }
414
- .uploadButton {
415
- margin-bottom: 5px !important;
416
- margin-left: 30px !important;
417
- }
418
-
419
- </style>
420
-
421
- <div class='form-row node-input-read-tabs-row'>
422
- <ul style='min-width:600px;margin-bottom:20px' id='node-input-read-tabs'></ul>
491
+ <style>
492
+ .deviceButton {
493
+ width: -webkit-fill-available;
494
+ background: space;
495
+ background-color: transparent !important;
496
+ color: inherit;
497
+ border: none;
498
+ display: flex;
499
+ align-items: center;
500
+ padding-top: 20px;
501
+ }
502
+ .point {
503
+ padding-left: 50px;
504
+ }
505
+ .pointButton {
506
+ color: inherit;
507
+ border: none;
508
+ display: flex;
509
+ align-items: center;
510
+ }
511
+ .networkTreeContent {
512
+ margin-top: 20px;
513
+ margin-left: 50px;
514
+ }
515
+ .p-confirm-dialog-accept > .p-button-label,
516
+ .bacnetServerRebuildSchedule_clearButton > .p-button-label {
517
+ color: white;
518
+ }
519
+ .red-ui-editor label {
520
+ font-size: 12px;
521
+ }
522
+ .bacnetServerRebuildSchedule_clearButton {
523
+ box-shadow: 0 0 0 0.2rem #edacac !important;
524
+ width: 200px;
525
+ border-radius: 3px;
526
+ margin-left: 140px !important;
527
+ }
528
+ .clearServerContainer {
529
+ position: absolute;
530
+ top: 55px;
531
+ margin-left: 280px;
532
+ }
533
+ .bacnetServerPoint_clearButton {
534
+ box-shadow: 0 0 0 0.2rem #edacac !important;
535
+ width: 200px;
536
+ border-radius: 3px;
537
+ margin-left: 420px !important;
538
+ margin-top: -75px !important;
539
+ }
540
+ .bacnetServerPoint_clearButton > .p-button-label {
541
+ color: white;
542
+ }
543
+ .clear_server_span {
544
+ width: 0px;
545
+ }
546
+ .read_server_parent_div {
547
+ display: flex;
548
+ align-items: flex-start;
549
+ justify-content: space-around;
550
+ flex-direction: column;
551
+ }
552
+ button {
553
+ height: 34px;
554
+ border-radius: 5px !important;
555
+ }
556
+ .inputStyle {
557
+ color: var(--red-ui-workspace-button-color-hover) !important;
558
+ background: var(--red-ui-workspace-button-background-hover);
559
+ border: 1px solid var(--red-ui-secondary-border-color);
560
+ border-radius: 5px !important;
561
+ }
562
+ input[type="file"] {
563
+ display: none !important;
564
+ }
565
+ .custom-file-upload {
566
+ border: 1px solid var(--red-ui-secondary-border-color);
567
+ border-radius: 5px !important;
568
+ padding: 6px 12px;
569
+ cursor: pointer;
570
+ }
571
+ .uploadButton {
572
+ margin-bottom: 5px !important;
573
+ margin-left: 30px !important;
574
+ }
575
+ .point_name {
576
+ font-weight: bold;
577
+ }
578
+ </style>
579
+
580
+ <div class="form-row node-input-read-tabs-row">
581
+ <ul style="min-width:600px;margin-bottom:20px" id="node-input-read-tabs"></ul>
582
+ </div>
583
+
584
+ <div id="node-input-tabs-content">
585
+ <div id="read-properties-tab" style="display:none">
586
+ <div class="form-row">
587
+ <label for="node-input-name"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.name"></span> Name</label>
588
+ <input type="text" id="node-input-name" placeholder="Name" />
589
+ </div>
590
+
591
+ <div class="form-row node-input-read-tabs-row">
592
+ <ul style="min-width:600px;margin-bottom:20px" id="node-input-read-tabs"></ul>
593
+ </div>
594
+
595
+ <div class="form-row" id="networkInterfaceDiv">
596
+ <label for="node-input-local_device_address"
597
+ ><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.local_device_address"></span> Network
598
+ Interface</label
599
+ >
600
+ <select id="node-input-local_device_address" style="width: 70%;"></select>
601
+ </div>
602
+
603
+ <div class="form-row">
604
+ <label for="node-input-broadCastAddr"
605
+ ><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.broadCastAddr"></span> Broadcast Address
606
+ </label>
607
+ <input type="text" id="node-input-broadCastAddr" placeholder="255.255.255.255" />
608
+ </div>
609
+
610
+ <div class="form-row">
611
+ <label for="node-input-local_device_port"
612
+ ><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.local_device_port"></span> Local Device Port</label
613
+ >
614
+ <input type="text" id="node-input-local_device_port" placeholder="47808" />
615
+ </div>
616
+
617
+ <div class="form-row">
618
+ <label for="node-input-deviceId"
619
+ ><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.deviceId"></span> Device ID
620
+ </label>
621
+ <input type="text" id="node-input-deviceId" placeholder="817001" />
622
+ </div>
623
+
624
+ <div class="form-row node-input-deviceIdRangeMatrix-container-row">
625
+ <ol id="node-input-deviceIdRangeMatrix-container" style="width: 600px;"></ol>
626
+ </div>
627
+ </div>
628
+
629
+ <div id="read-discover-tab" style="display:none">
630
+ <div class="form-row">
631
+ <label for="node-input-apduTimeout"
632
+ ><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.apduTimeout"></span>Apdu Timeout</label
633
+ >
634
+ <input type="text" id="node-input-apduTimeout" placeholder="10000" />
635
+ </div>
636
+
637
+ <div class="form-row">
638
+ <label for="node-input-apduSize"
639
+ ><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.apduSize"></span>Max Apdu Size</label
640
+ >
641
+ <select id="node-input-apduSize">
642
+ <option value="0">0</option>
643
+ <option value="1">1</option>
644
+ <option value="2">2</option>
645
+ <option value="3">3</option>
646
+ <option value="4">4</option>
647
+ <option value="5">5</option>
648
+ </select>
649
+ </div>
650
+
651
+ <div class="form-row">
652
+ <label for="node-input-maxSegments"
653
+ ><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.maxSegments"></span>Max Segments</label
654
+ >
655
+ <select id="node-input-maxSegments">
656
+ <option value="0">0</option>
657
+ <option value="0x10">0x10</option>
658
+ <option value="0x20">0x20</option>
659
+ <option value="0x30">0x30</option>
660
+ <option value="0x40">0x40</option>
661
+ <option value="0x50">0x50</option>
662
+ <option value="0x60">0x60</option>
663
+ <option value="0x70">0x70</option>
664
+ </select>
665
+ </div>
666
+
667
+ <div class="form-row">
668
+ <label for="node-input-retries"
669
+ ><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.retries"></span>Number of Retries</label
670
+ >
671
+ <select id="node-input-retries">
672
+ <option value="0">0</option>
673
+ <option value="1">1</option>
674
+ <option value="2">2</option>
675
+ <option value="3">3</option>
676
+ <option value="4">4</option>
677
+ <option value="5">5</option>
678
+ <option value="6">6</option>
679
+ <option value="7">7</option>
680
+ <option value="8">8</option>
681
+ <option value="9">9</option>
682
+ <option value="10">10</option>
683
+ </select>
684
+ </div>
685
+
686
+ <div class="form-row" style="align-items: center; display: flex;">
687
+ <label for="node-input-discover_polling_schedule_value"
688
+ ><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.bacnet_polling_schedule"></span>Device Discover
689
+ Frequency</label
690
+ >
691
+ <p style="margin-right: 5px; margin-bottom: 0px; padding-left: 7px;">Every</p>
692
+ <input type="text" id="node-input-discover_polling_schedule" style="display: none;" />
693
+ <input
694
+ type="text"
695
+ id="node-input-discover_polling_schedule_value"
696
+ placeholder="5"
697
+ style="width: 70px; margin-right: 5px;" />
698
+ <select name="timePeriod" id="node-input-discover_polling_schedule_options" style="width: 120px; margin-right: 5px;">
699
+ <option value="Seconds">Seconds</option>
700
+ <option value="Minutes">Minutes</option>
701
+ <option value="Hours">Hours</option>
702
+ <option value="Days">Days</option>
703
+ </select>
704
+ </div>
705
+
706
+ <div class="form-row deviceIdRange">
707
+ <label for="node-input-device_id_range"
708
+ ><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.device_id_range"></span>Point Discovery Range
709
+ </label>
710
+ <input type="checkbox" id="node-input-manual_instance_range_enabled" style="width: auto;" />
711
+ <a style="padding-left: 60px;">Start: </a
712
+ ><input type="number" id="node-input-manual_instance_range_start" style="width: 125px;" min="0" max="100000" />
713
+ <a style="padding-left: 35px;">End: </a
714
+ ><input type="number" id="node-input-manual_instance_range_end" style="width: 125px;" min="1" max="100000" />
715
+ </div>
716
+
717
+ <div class="form-row" style="align-items: center; display: flex;">
718
+ <label for="node-input-device_read_schedule_value"
719
+ ><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.device_read_schedule"></span>Object Discover
720
+ Frequency</label
721
+ >
722
+ <p style="margin-right: 5px; margin-bottom: 0px; padding-left: 7px;">Every</p>
723
+ <input type="text" id="node-input-device_read_schedule" style="display: none;" />
724
+ <input
725
+ type="text"
726
+ id="node-input-device_read_schedule_value"
727
+ placeholder="5"
728
+ style="width: 70px; margin-right: 5px;" />
729
+ <select name="timePeriod" id="node-input-device_read_schedule_options" style="width: 120px; margin-right: 5px;">
730
+ <option value="Seconds">Seconds</option>
731
+ <option value="Minutes">Minutes</option>
732
+ <option value="Hours">Hours</option>
733
+ <option value="Days">Days</option>
734
+ </select>
735
+ </div>
736
+
737
+ <div class="form-row">
738
+ <label for="node-input-toLog"> Log found device: </label>
739
+ <input type="checkbox" id="node-input-toLogIam" style="width: auto;" />
740
+ </div>
741
+
742
+ <div class="form-row">
743
+ <label for="node-input-logErrorToConsole"> Log BACnet errors to console: </label>
744
+ <input type="checkbox" id="node-input-logErrorToConsole" style="width: auto;" />
745
+ </div>
746
+
747
+ <div class="form-row" id="importDeviceList">
748
+ <label> Device List: </label>
749
+ <label for="file-upload" class="custom-file-upload">
750
+ <i class="fa fa-cloud-upload" id="fileLabel"></i> <a id="fileLabelText" style="padding-left: 10px;">Import</a>
751
+ </label>
752
+ <input type="file" id="file-upload" accept="application/JSON" class="inputStyle" style="width: 258px;" />
753
+ <label for="file-export" class="custom-file-upload" style="margin-left: 30px;">
754
+ <i class="fa fa-cloud-download" id="fileLabel"></i> <a id="fileLabelText" style="padding-left: 10px;">Export</a>
755
+ </label>
756
+ <input id="file-export" class="inputStyle" style="width: 258px; display: none;" />
757
+ <a id="exportJSON" style="display: none"></a>
758
+ </div>
759
+ </div>
760
+
761
+ <div id="read-server-tab" style="display:none">
762
+
763
+ <div class="form-row">
764
+ <label for="node-input-serverEnabled"> Enabled: </label>
765
+ <input type="checkbox" id="node-input-serverEnabled" style="width: auto;" />
766
+ </div>
767
+
768
+ <div class="read_server_parent_div" id="serverParent">
769
+
770
+ <div class="form-row clearServerContainer" id="clearServerContainer" style="align-items: center; display: flex;">
771
+ <p-button
772
+ class="bacnetServerRebuildSchedule_clearButton p-button-danger"
773
+ @click="confirmAll($event)"
774
+ label="Reinitialize Server">
775
+ </p-button>
423
776
  </div>
424
777
 
425
- <div id='node-input-tabs-content'>
426
- <div id='read-properties-tab' style='display:none'>
427
- <div class="form-row">
428
- <label for="node-input-name"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.name"></span> Name</label>
429
- <input type="text" id="node-input-name" placeholder="Name">
430
- </div>
431
-
432
- <div class='form-row node-input-read-tabs-row'>
433
- <ul style='min-width:600px;margin-bottom:20px' id='node-input-read-tabs'></ul>
434
- </div>
435
-
436
- <div class="form-row" id="networkInterfaceDiv">
437
- <label for="node-input-local_device_address"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.local_device_address"></span> Network Interface</label>
438
- <select id="node-input-local_device_address" style="width: 70%;" >
439
- </select>
440
- </div>
441
-
442
- <div class="form-row">
443
- <label for="node-input-broadCastAddr"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.broadCastAddr"></span> Broadcast Address </label>
444
- <input type="text" id="node-input-broadCastAddr" placeholder="255.255.255.255">
445
- </div>
446
-
447
- <div class="form-row">
448
- <label for="node-input-local_device_port"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.local_device_port"></span> Local Device Port</label>
449
- <input type="text" id="node-input-local_device_port" placeholder="47808">
450
- </div>
451
-
452
- <div class="form-row">
453
- <label for="node-input-deviceId"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.deviceId"></span> Device ID </label>
454
- <input type="text" id="node-input-deviceId" placeholder="817001">
455
- </div>
456
-
457
- <div class="form-row deviceIdRange">
458
- <label for="node-input-device_id_range"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.device_id_range"></span> Device ID Range </label>
459
- <input type="checkbox" id="node-input-device_id_range_enabled" style="width: auto;"/>
460
- <a style="padding-left: 60px;">Start: </a><input type="number" id="node-input-device_id_range_start" style="width: 125px;" min="0" max="4194303"/>
461
- <a style="padding-left: 35px;">End: </a><input type="number" id="node-input-device_id_range_end" style="width: 125px;" min="1" max="4194303"/>
462
- </div>
463
- </div>
464
-
465
- <div id='read-discover-tab' style='display:none'>
466
- <div class="form-row">
467
- <label for="node-input-apduTimeout"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.apduTimeout"></span>Apdu Timeout</label>
468
- <input type="text" id="node-input-apduTimeout" placeholder="10000">
469
- </div>
470
-
471
- <div class="form-row">
472
- <label for="node-input-apduSize"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.apduSize"></span>Max Apdu Size</label>
473
- <select id="node-input-apduSize">
474
- <option value="0">0</option>
475
- <option value="1">1</option>
476
- <option value="2">2</option>
477
- <option value="3">3</option>
478
- <option value="4">4</option>
479
- <option value="5">5</option>
480
- </select>
481
- </div>
482
-
483
- <div class="form-row">
484
- <label for="node-input-maxSegments"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.maxSegments"></span>Max Segments</label>
485
- <select id="node-input-maxSegments">
486
- <option value="0">0</option>
487
- <option value="0x10">0x10</option>
488
- <option value="0x20">0x20</option>
489
- <option value="0x30">0x30</option>
490
- <option value="0x40">0x40</option>
491
- <option value="0x50">0x50</option>
492
- <option value="0x60">0x60</option>
493
- <option value="0x70">0x70</option>
494
- </select>
495
- </div>
496
-
497
- <div class="form-row">
498
- <label for="node-input-retries"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.retries"></span>Number of Retries</label>
499
- <select id="node-input-retries">
500
- <option value="0">0</option>
501
- <option value="1">1</option>
502
- <option value="2">2</option>
503
- <option value="3">3</option>
504
- <option value="4">4</option>
505
- <option value="5">5</option>
506
- <option value="6">6</option>
507
- <option value="7">7</option>
508
- <option value="8">8</option>
509
- <option value="9">9</option>
510
- <option value="10">10</option>
511
- </select>
512
- </div>
513
-
514
- <div class="form-row" style="align-items: center; display: flex;">
515
- <label for="node-input-discover_polling_schedule_value"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.bacnet_polling_schedule"></span>Device Discover Frequency</label>
516
- <p style="margin-right: 5px; margin-bottom: 0px; padding-left: 7px;">Every</p>
517
- <input type="text" id="node-input-discover_polling_schedule" style="display: none;">
518
- <input type="text" id="node-input-discover_polling_schedule_value" placeholder="5" style="width: 70px; margin-right: 5px;">
519
- <select name="timePeriod" id="node-input-discover_polling_schedule_options" style="width: 120px; margin-right: 5px;">
520
- <option value="Seconds">Seconds</option>
521
- <option value="Minutes">Minutes</option>
522
- <option value="Hours">Hours</option>
523
- <option value="Days">Days</option>
524
- </select>
525
- </div>
526
-
527
- <div class="form-row deviceIdRange">
528
- <label for="node-input-device_id_range"><i class="icon-tag"></i><span data-i18n="bitpool-bacnet.label.device_id_range"></span>Point Discovery Range </label>
529
- <input type="checkbox" id="node-input-manual_instance_range_enabled" style="width: auto;"/>
530
- <a style="padding-left: 60px;">Start: </a><input type="number" id="node-input-manual_instance_range_start" style="width: 125px;" min="0" max="100000"/>
531
- <a style="padding-left: 35px;">End: </a><input type="number" id="node-input-manual_instance_range_end" style="width: 125px;" min="1" max="100000"/>
532
- </div>
533
-
534
- <div class="form-row" style="align-items: center; display: flex;">
535
- <label for="node-input-device_read_schedule_value"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.device_read_schedule"></span>Object Discover Frequency</label>
536
- <p style="margin-right: 5px; margin-bottom: 0px; padding-left: 7px;">Every</p>
537
- <input type="text" id="node-input-device_read_schedule" style="display: none;">
538
- <input type="text" id="node-input-device_read_schedule_value" placeholder="5" style="width: 70px; margin-right: 5px;">
539
- <select name="timePeriod" id="node-input-device_read_schedule_options" style="width: 120px; margin-right: 5px;">
540
- <option value="Seconds">Seconds</option>
541
- <option value="Minutes">Minutes</option>
542
- <option value="Hours">Hours</option>
543
- <option value="Days">Days</option>
544
- </select>
545
- </div>
546
-
547
- <div class="form-row">
548
- <label for="node-input-toLog">
549
- Log found device:
550
- </label>
551
- <input type="checkbox" id="node-input-toLogIam" style="width: auto;"/>
552
- </div>
553
-
554
- <div class="form-row">
555
- <label for="node-input-logErrorToConsole">
556
- Log BACnet errors to console:
557
- </label>
558
- <input type="checkbox" id="node-input-logErrorToConsole" style="width: auto;"/>
559
- </div>
560
-
561
- <div class="form-row" id="importDeviceList">
562
- <label>
563
- Device List:
564
- </label>
565
- <label for="file-upload" class="custom-file-upload">
566
- <i class="fa fa-cloud-upload" id="fileLabel"></i> <a id="fileLabelText" style="padding-left: 10px;">Import</a>
567
- </label>
568
- <input type="file" id="file-upload" accept="application/JSON" class="inputStyle" style="width: 258px;">
569
- <label for="file-export" class="custom-file-upload" style="margin-left: 30px;">
570
- <i class="fa fa-cloud-download" id="fileLabel"></i> <a id="fileLabelText" style="padding-left: 10px;">Export</a>
571
- </label>
572
- <input id="file-export" class="inputStyle" style="width: 258px; display: none;">
573
- <a id="exportJSON" style="display: none"></a>
574
- </div>
575
- </div>
576
-
577
- <div id='read-server-tab' style='display:none'>
578
- <div class="read_server_parent_div">
579
- <div class="form-row">
580
- <label for="node-input-serverEnabled">
581
- Enabled:
582
- </label>
583
- <input type="checkbox" id="node-input-serverEnabled" style="width: auto;"/>
584
- </div>
585
-
586
- <div class="form-row" id="clearServerContainer" style="align-items: center; display: flex;">
587
- <label for="node-input-bacnetServerRebuildSchedule_value" class="clear_server_span"><i class="icon-tag"></i> <span data-i18n="bitpool-bacnet.label.bacnetServerRebuildSchedule"></span> </label>
588
- <p-button class="bacnetServerRebuildSchedule_clearButton p-button-danger" @click="confirm($event)" label="Reinitialize Server" ></p-button>
589
- </div>
590
- </div>
591
- </div>
592
-
593
- </script>
594
- <script type="text/html" data-help-name="Bacnet-Gateway">
595
- <p> This node is the brain of the Bitpool BACnet node collection. It acts are the gateway for all BACnet communications and functionality for the collection. </p>
596
-
597
- <h3><strong>Gateway Tab</strong></h3>
598
- <ul class="node-ports">
599
- <li>Network Interface - the desired interface for the bacstack client to bind to. This interface must not have any other BACnet clients bound to it.</li>
600
- <li>Broadcast Address - the desired subnet for global msgs to be broadcast and recieved on. This should be as strict as possible. Use 255.255.255.255 if unsure.</li>
601
- <li>Local Device Port - the port to be used for BACnet comms. Default is 47808</li>
602
-
603
- </ul>
604
-
605
- <h3><strong>Discovery Tab</strong></h3>
606
- <ul class="node-ports">
607
- <li>APDU Timeout - BACnet msg timeout option</li>
608
- <li>Max APDU Size - BACnet max apdu size</li>
609
- <li>Max Segments - BACnet max segments</li>
610
- <li>Global Discover Frequency - the frequency at which the gateway issues global WhoIs BACnet commands. This should be limited to the least amount possible, as over-loading a network can be a serious issue with BACnet commmunications.</li>
611
- <li>Manual Point Discovery Instance Range - if a BACnet device doesnt have a Object list (BACnet objectType:propertyId - 8:76), the this bacnet client will enter into manual discovery mode, where it iterates through types and instnace ranges. This range can be used to limit this manual scanning </li>
612
- <li>Log Device Found - toggles logging of found devices to the node-red debug tab.</li>
613
- <li>Log BACnet Errors to Console - toggles logging of BACnet related errors to the node-red console</li>
614
- </ul>
615
-
616
- <h3><strong>Server Tab</strong></h3>
617
- <p>This section provides the ability to simulate a BACnet device and BACnet points using node-red. </p>
618
- <p>Injecting a msg.topic and msg.payload into the gateway node will create a virtual point that can be discovered by other devices via BACnet/IP</p>
619
- <p>This node only supports 2 BACnet object types, Analog Value - to show numeric data, and a Character String - to show string data.</p>
620
- <ul class="node-ports">
621
- <li>Enabled - toggles whether or not the local BACnet server is started or not. </li>
622
- <li>Clear Server Points - a schedule for the locally generated BACnet points to get cleared from the node object store</li>
623
- </ul>
624
-
625
- <h3><strong>Examples</strong></h3>
626
- <p>For example flows, please use the examples section for this node. These examples can be found at: Node-red hamburger menu on top right -> Import -> Examples -> @bitpoolos/edge-bacnet</p>
627
- <p>To find captured examples of settings and flows, please go to our wiki <a href="https://wiki.bitpool.com/en/edge/apps/bitpool-edge/nr-bacnet">here</a></p>
628
-
629
-
630
- <h3>Resources:</h3>
631
-
632
- <p><a href="https://youtu.be/4K7mVxfvfbc">Video Walk-through </a></p>
633
-
634
- <h4><strong>Online Docs:</strong></h4>
635
- <ul type="1">
636
- <li><a href="https://www.bitpool.com/">bitpool.com</a> - check us out here.</li>
637
- <li><a href="https://app.bitpool.com/">app.bitpool.com</a> - set up your account.</li>
638
- <li><a href="https://wiki.bitpool.com/">wiki.bitpool.com</a> - find more documentation.</li>
639
- <li><a href="https://bacnet.org/">BACnet</a> - find more about the protocol.</li>
640
- </ul>
641
- </script>
778
+ <div class="form-row" id="clearServerPointContainer">
779
+ <label>Server Objects</label>
780
+ <div v-for="object in serverObjects" :key="object.name">
781
+ <div><p class="point_name">[{{ object.type }}{{ object.instance }}] {{ formatObjectName(object.name) }}</p></div>
782
+ <p-button class="bacnetServerPoint_clearButton p-button-danger" @click="confirm({
783
+ type: object.type,
784
+ instance: object.instance,
785
+ name: object.name
786
+ })" label="Remove Object"></p-button>
787
+ </div>
788
+ </div>
789
+ </div>
790
+ </div>
791
+ </div>
792
+ </script>
793
+ <script type="text/html" data-help-name="Bacnet-Gateway">
794
+ <p>
795
+ This node is the brain of the Bitpool BACnet node collection. It acts are the gateway for all BACnet communications and
796
+ functionality for the collection.
797
+ </p>
798
+
799
+ <h3><strong>Gateway Tab</strong></h3>
800
+ <ul class="node-ports">
801
+ <li>
802
+ Network Interface - the desired interface for the bacstack client to bind to. This interface must not have any other
803
+ BACnet clients bound to it.
804
+ </li>
805
+ <li>
806
+ Broadcast Address - the desired subnet for global msgs to be broadcast and recieved on. This should be as strict as
807
+ possible. Use 255.255.255.255 if unsure.
808
+ </li>
809
+ <li>Local Device Port - the port to be used for BACnet comms. Default is 47808</li>
810
+ </ul>
811
+
812
+ <h3><strong>Discovery Tab</strong></h3>
813
+ <ul class="node-ports">
814
+ <li>APDU Timeout - BACnet msg timeout option</li>
815
+ <li>Max APDU Size - BACnet max apdu size</li>
816
+ <li>Max Segments - BACnet max segments</li>
817
+ <li>
818
+ Global Discover Frequency - the frequency at which the gateway issues global WhoIs BACnet commands. This should be
819
+ limited to the least amount possible, as over-loading a network can be a serious issue with BACnet commmunications.
820
+ </li>
821
+ <li>
822
+ Manual Point Discovery Instance Range - if a BACnet device doesnt have a Object list (BACnet objectType:propertyId -
823
+ 8:76), the this bacnet client will enter into manual discovery mode, where it iterates through types and instnace
824
+ ranges. This range can be used to limit this manual scanning
825
+ </li>
826
+ <li>Log Device Found - toggles logging of found devices to the node-red debug tab.</li>
827
+ <li>Log BACnet Errors to Console - toggles logging of BACnet related errors to the node-red console</li>
828
+ </ul>
829
+
830
+ <h3><strong>Server Tab</strong></h3>
831
+ <p>This section provides the ability to simulate a BACnet device and BACnet points using node-red.</p>
832
+ <p>
833
+ Injecting a msg.topic and msg.payload into the gateway node will create a virtual point that can be discovered by other
834
+ devices via BACnet/IP
835
+ </p>
836
+ <p>
837
+ This node only supports 2 BACnet object types, Analog Value - to show numeric data, and a Character String - to show
838
+ string data.
839
+ </p>
840
+ <ul class="node-ports">
841
+ <li>Enabled - toggles whether or not the local BACnet server is started or not.</li>
842
+ <li>
843
+ Clear Server Points - a schedule for the locally generated BACnet points to get cleared from the node object store
844
+ </li>
845
+ </ul>
846
+
847
+ <h3><strong>Examples</strong></h3>
848
+ <p>
849
+ For example flows, please use the examples section for this node. These examples can be found at: Node-red hamburger menu
850
+ on top right -> Import -> Examples -> @bitpoolos/edge-bacnet
851
+ </p>
852
+ <p>
853
+ To find captured examples of settings and flows, please go to our wiki
854
+ <a href="https://wiki.bitpool.com/en/edge/apps/bitpool-edge/nr-bacnet">here</a>
855
+ </p>
856
+
857
+ <h3>Resources:</h3>
858
+
859
+ <p><a href="https://youtu.be/4K7mVxfvfbc">Video Walk-through </a></p>
860
+
861
+ <h4><strong>Online Docs:</strong></h4>
862
+ <ul type="1">
863
+ <li><a href="https://www.bitpool.com/">bitpool.com</a> - check us out here.</li>
864
+ <li><a href="https://app.bitpool.com/">app.bitpool.com</a> - set up your account.</li>
865
+ <li><a href="https://wiki.bitpool.com/">wiki.bitpool.com</a> - find more documentation.</li>
866
+ <li><a href="https://bacnet.org/">BACnet</a> - find more about the protocol.</li>
867
+ </ul>
868
+ </script>