homebridge-smartsystem 6.3.4 → 6.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/README.md +38 -34
- package/config.json +48 -56
- package/duotecno/master.js +85 -3
- package/duotecno/master.ts +90 -6
- package/duotecno/protocol.js +97 -25
- package/duotecno/protocol.ts +103 -27
- package/duotecno/types.js +8 -4
- package/duotecno/types.ts +12 -6
- package/index.spec.js +1 -0
- package/index.spec.ts +1 -0
- package/package.json +1 -1
- package/server/powerbase.js +15 -16
- package/server/powerbase.ts +18 -17
- package/server/smartapp.js +11 -6
- package/server/smartapp.ts +15 -8
- package/server/views/master-detail.ejs +16 -0
- package/server/views/master-list.ejs +2 -0
- package/server/views/power-binding.ejs +3 -3
- package/server/views/power.ejs +3 -3
package/README.md
CHANGED
|
@@ -245,42 +245,46 @@ Homebridge UI version
|
|
|
245
245
|
added "restart plugin" to settings,
|
|
246
246
|
set lock target state to "locked"
|
|
247
247
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
248
|
+
### v6.1.0 - 15-07-2022
|
|
249
|
+
- global debug, log, err functions in types.ts
|
|
250
|
+
- split smappee.ts in PowerBase + smappee/p1/shelly
|
|
251
|
+
|
|
252
|
+
### v6.1.x - 21-07-2022 - P1 release
|
|
253
|
+
- 0: implemented P1 power meter telegram
|
|
254
|
+
- 1: bugfixes, timeout mgt, etc...
|
|
255
|
+
- 2: try fixing logfunction errors
|
|
256
|
+
- 3: reverting to console.log
|
|
257
|
+
- 4: errors when starting power mgrs from platform.ts
|
|
258
|
+
- 5: v6.1.3 changes were gone... restored them.
|
|
259
|
+
- 6: added login with pw in config + http.get with on-error
|
|
260
|
+
- 6: allow + and - in power rules expressions
|
|
261
|
+
- 7: allow NaN in bindings compare for update
|
|
262
262
|
|
|
263
263
|
### v6.2.0 - 10-08-2022 - fully use Homebridge UI (login, config)
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
264
|
+
- receive config through Platform on startup,
|
|
265
|
+
- moved all config to global variable, keep in sync through API of HB-UI
|
|
266
|
+
- implemented login page, use HB-UI api -> bearer jwt token
|
|
267
|
+
- added upgrade method from 6.1.x to v6.2.x (adding files from /home/homebridge/duotecno/config.*.json to global config.*)
|
|
268
|
+
- homebridge config is saved by UI in: /var/lib/homebridge/config.json (as well as the logfile: homebridge.log)
|
|
269
|
+
- smartapp calls Homebridge UI API to save changes
|
|
270
|
+
|
|
271
|
+
### v6.2.x - 11-08-2022 - P1 release
|
|
272
|
+
- 1 : always write config to file too (next to sending through the HB-UI API)
|
|
273
|
+
- 2: added headers to http calls from switches, dimmers and up/down's (including OH stuff)
|
|
274
|
+
- 3: fixed bug in Sanitizer of UnitConfig preventing from publishing units to homebridge
|
|
275
|
+
- 4: fixed empty name bug in unit-def / new accessory()
|
|
276
|
+
- 5: fixed bad displayNames in published units
|
|
277
|
+
- 6: power: 5% instead of 10% for power rules
|
|
278
|
+
|
|
279
|
+
### v6.3.x - 23-09-2022 - Shelly PM release
|
|
280
|
+
- 1: first test Shelly PM - allow address or addresses, example: "192.168.0.95,102.168.0.96"
|
|
281
|
+
- 2: logging now more according to debug true/false in the config file
|
|
282
|
+
- 3: power bindings now when: 5% change < 1000W, 2% change > 1000W
|
|
283
|
+
- 4: added if in set-plug if smappee not (yet) connected.
|
|
284
|
+
|
|
285
|
+
### v6.4.x - 28-11-2022 - Binding to registers
|
|
286
|
+
- 0: writing to registers
|
|
287
|
+
- 1: ask/show protocol version -> publish
|
|
284
288
|
|
|
285
289
|
## Hardware
|
|
286
290
|
A Raspberry Pi that connects to a Duotecno IP Node
|
package/config.json
CHANGED
|
@@ -35,17 +35,17 @@
|
|
|
35
35
|
"logicalNodeAddress": 3
|
|
36
36
|
}
|
|
37
37
|
],
|
|
38
|
-
"power":
|
|
39
|
-
"current":
|
|
38
|
+
"power": -758,
|
|
39
|
+
"current": 0
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
"type": "power",
|
|
43
43
|
"channel": "7+8+9",
|
|
44
|
-
"low":
|
|
44
|
+
"low": 500,
|
|
45
45
|
"high": 10000,
|
|
46
46
|
"actions": [
|
|
47
47
|
{
|
|
48
|
-
"name": "",
|
|
48
|
+
"name": "Blue LED",
|
|
49
49
|
"value": false,
|
|
50
50
|
"masterAddress": "192.168.0.97",
|
|
51
51
|
"masterPort": 5001,
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"logicalNodeAddress": 3
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
|
-
"name": "",
|
|
56
|
+
"name": "Blue LED",
|
|
57
57
|
"value": true,
|
|
58
58
|
"masterAddress": "192.168.0.97",
|
|
59
59
|
"masterPort": 5001,
|
|
@@ -61,16 +61,14 @@
|
|
|
61
61
|
"logicalNodeAddress": 3
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
|
-
"name": "
|
|
64
|
+
"name": "--",
|
|
65
65
|
"value": true,
|
|
66
66
|
"masterAddress": "192.168.0.97",
|
|
67
67
|
"masterPort": 5001,
|
|
68
68
|
"logicalAddress": 0,
|
|
69
69
|
"logicalNodeAddress": 0
|
|
70
70
|
}
|
|
71
|
-
]
|
|
72
|
-
"power": 446,
|
|
73
|
-
"current": 1
|
|
71
|
+
]
|
|
74
72
|
},
|
|
75
73
|
{
|
|
76
74
|
"type": "power",
|
|
@@ -102,55 +100,37 @@
|
|
|
102
100
|
"logicalAddress": 0,
|
|
103
101
|
"logicalNodeAddress": 0
|
|
104
102
|
}
|
|
105
|
-
]
|
|
103
|
+
],
|
|
104
|
+
"power": 266,
|
|
105
|
+
"current": 0
|
|
106
106
|
}
|
|
107
107
|
],
|
|
108
|
-
"address": "192.168.0.
|
|
108
|
+
"address": "192.168.0.183",
|
|
109
109
|
"uid": "57e3e0d8-bb05-4b04-8662-1a9871998f3f",
|
|
110
110
|
"bindings": [
|
|
111
111
|
{
|
|
112
|
-
"
|
|
113
|
-
"logicalAddress": 102,
|
|
112
|
+
"channel": "0+1",
|
|
114
113
|
"masterAddress": "192.168.0.97",
|
|
115
114
|
"masterPort": 5001,
|
|
116
|
-
"
|
|
117
|
-
"displayName": "unit 252:102",
|
|
118
|
-
"extendedType": 0,
|
|
119
|
-
"channel": "0+1",
|
|
120
|
-
"power": 1706
|
|
115
|
+
"register": 1
|
|
121
116
|
},
|
|
122
117
|
{
|
|
123
|
-
"
|
|
124
|
-
"logicalAddress": 100,
|
|
118
|
+
"channel": "2+3",
|
|
125
119
|
"masterAddress": "192.168.0.97",
|
|
126
120
|
"masterPort": 5001,
|
|
127
|
-
"
|
|
128
|
-
"displayName": "unit 252:100",
|
|
129
|
-
"extendedType": 0,
|
|
130
|
-
"channel": "2+3",
|
|
131
|
-
"power": 2494
|
|
121
|
+
"register": 2
|
|
132
122
|
},
|
|
133
123
|
{
|
|
134
|
-
"
|
|
135
|
-
"logicalAddress": 103,
|
|
124
|
+
"channel": "4+5",
|
|
136
125
|
"masterAddress": "192.168.0.97",
|
|
137
126
|
"masterPort": 5001,
|
|
138
|
-
"
|
|
139
|
-
"displayName": "unit 252:103",
|
|
140
|
-
"extendedType": 0,
|
|
141
|
-
"channel": "4+5",
|
|
142
|
-
"power": null
|
|
127
|
+
"register": 7
|
|
143
128
|
},
|
|
144
129
|
{
|
|
145
|
-
"
|
|
146
|
-
"logicalAddress": 101,
|
|
130
|
+
"channel": "8",
|
|
147
131
|
"masterAddress": "192.168.0.97",
|
|
148
132
|
"masterPort": 5001,
|
|
149
|
-
"
|
|
150
|
-
"displayName": "unit 252:101",
|
|
151
|
-
"extendedType": 0,
|
|
152
|
-
"channel": "8",
|
|
153
|
-
"power": null
|
|
133
|
+
"register": 8
|
|
154
134
|
}
|
|
155
135
|
]
|
|
156
136
|
},
|
|
@@ -159,36 +139,33 @@
|
|
|
159
139
|
"rules": [],
|
|
160
140
|
"bindings": [
|
|
161
141
|
{
|
|
162
|
-
"
|
|
163
|
-
"logicalAddress": 102,
|
|
142
|
+
"channel": "0+1+2",
|
|
164
143
|
"masterAddress": "192.168.0.97",
|
|
165
144
|
"masterPort": 5001,
|
|
166
|
-
"
|
|
167
|
-
"displayName": "unit 252:102",
|
|
168
|
-
"extendedType": 0,
|
|
169
|
-
"channel": "0+1+2",
|
|
170
|
-
"power": null
|
|
145
|
+
"register": 11
|
|
171
146
|
},
|
|
172
147
|
{
|
|
173
|
-
"
|
|
174
|
-
"logicalAddress": 100,
|
|
148
|
+
"channel": "3+4+5",
|
|
175
149
|
"masterAddress": "192.168.0.97",
|
|
176
150
|
"masterPort": 5001,
|
|
177
|
-
"
|
|
178
|
-
"displayName": "unit 252:100",
|
|
179
|
-
"extendedType": 0,
|
|
180
|
-
"channel": "3+4+5",
|
|
181
|
-
"power": null
|
|
151
|
+
"register": 12
|
|
182
152
|
}
|
|
183
153
|
],
|
|
184
|
-
"address": "192.168.0.
|
|
154
|
+
"address": "192.168.0.206"
|
|
185
155
|
},
|
|
186
156
|
"shelly": {
|
|
187
157
|
"debug": false,
|
|
188
158
|
"address": "192.168.0.95",
|
|
189
159
|
"addresses": "192.168.0.95,192.168.0.95",
|
|
190
160
|
"rules": [],
|
|
191
|
-
"bindings": [
|
|
161
|
+
"bindings": [
|
|
162
|
+
{
|
|
163
|
+
"channel": "0+1+2+3+4+5+6+7+8",
|
|
164
|
+
"masterAddress": "192.168.0.97",
|
|
165
|
+
"masterPort": 5001,
|
|
166
|
+
"register": 5
|
|
167
|
+
}
|
|
168
|
+
]
|
|
192
169
|
},
|
|
193
170
|
"smartapp": {
|
|
194
171
|
"apiPort": 8581,
|
|
@@ -310,6 +287,21 @@
|
|
|
310
287
|
"252": " 20211003"
|
|
311
288
|
},
|
|
312
289
|
"debug": false
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"address": "192.168.0.5",
|
|
293
|
+
"port": 5005,
|
|
294
|
+
"password": "duotecno",
|
|
295
|
+
"name": "GM",
|
|
296
|
+
"active": true,
|
|
297
|
+
"nodenames": {
|
|
298
|
+
"3": "IP Server",
|
|
299
|
+
"4": "Sonos",
|
|
300
|
+
"16": "Smartbox Living",
|
|
301
|
+
"17": "Switch Living",
|
|
302
|
+
"252": " 20220925"
|
|
303
|
+
},
|
|
304
|
+
"debug": false
|
|
313
305
|
}
|
|
314
306
|
],
|
|
315
307
|
"cunits": [
|
|
@@ -450,7 +442,7 @@
|
|
|
450
442
|
"units": []
|
|
451
443
|
}
|
|
452
444
|
],
|
|
453
|
-
"debug":
|
|
445
|
+
"debug": true,
|
|
454
446
|
"settings": {
|
|
455
447
|
"network": {
|
|
456
448
|
"ip1": "1.2.3.4",
|
package/duotecno/master.js
CHANGED
|
@@ -134,6 +134,9 @@ class Master extends base_1.Base {
|
|
|
134
134
|
*/
|
|
135
135
|
constructor(system, config) {
|
|
136
136
|
super("master", types_1.Sanitizers.masterConfig(config));
|
|
137
|
+
this.protocol = 0; // major * 100 + minor
|
|
138
|
+
this.version = 0; // idem
|
|
139
|
+
this.registers = {};
|
|
137
140
|
this.resolveLogin = null;
|
|
138
141
|
this.Q = new Q_1.Q();
|
|
139
142
|
// save my eco system
|
|
@@ -150,6 +153,9 @@ class Master extends base_1.Base {
|
|
|
150
153
|
this.closing = false;
|
|
151
154
|
// incoming data
|
|
152
155
|
this.buffer = "";
|
|
156
|
+
// init to v1.00
|
|
157
|
+
this.version = 100;
|
|
158
|
+
this.protocol = 100;
|
|
153
159
|
}
|
|
154
160
|
getName() {
|
|
155
161
|
return this.config.name || "master";
|
|
@@ -360,8 +366,8 @@ class Master extends base_1.Base {
|
|
|
360
366
|
return false;
|
|
361
367
|
}
|
|
362
368
|
else {
|
|
363
|
-
|
|
364
|
-
|
|
369
|
+
// don't log all incoming (no time, no sensor status messages)
|
|
370
|
+
if ((next.cmd != protocol_1.Rec.TimeDateStatus) && (next.cmd != protocol_1.Rec.Sensor))
|
|
365
371
|
this.info("received -> " + (0, protocol_1.recName)(next.cmd) + " -> " + ((!next.message) ?
|
|
366
372
|
"--" : ((next.message instanceof Array) ? next.message.join(",") : next.message)));
|
|
367
373
|
this.Q.do();
|
|
@@ -384,6 +390,12 @@ class Master extends base_1.Base {
|
|
|
384
390
|
else if (next.cmd === protocol_1.Rec.ScheduleStatus) {
|
|
385
391
|
this.receiveSchedule(next.message);
|
|
386
392
|
}
|
|
393
|
+
else if (next.cmd === protocol_1.Rec.NodeMgtInfo) {
|
|
394
|
+
this.receiveNodeMgtInfo(next.message);
|
|
395
|
+
}
|
|
396
|
+
else if (next.cmd === protocol_1.Rec.Register) {
|
|
397
|
+
this.receiveRegister(next.message);
|
|
398
|
+
}
|
|
387
399
|
else {
|
|
388
400
|
this.info("not handled: " + next.message);
|
|
389
401
|
}
|
|
@@ -398,6 +410,10 @@ class Master extends base_1.Base {
|
|
|
398
410
|
if (this.resolveLogin) {
|
|
399
411
|
this.resolveLogin(this.isLoggedIn);
|
|
400
412
|
this.resolveLogin = null;
|
|
413
|
+
// if logged in, ask protocol version
|
|
414
|
+
if (this.isLoggedIn) {
|
|
415
|
+
this.send(protocol_1.Protocol.buildRequestNodeMgt(protocol_1.reqNodeAttributes.nodeProtocol));
|
|
416
|
+
}
|
|
401
417
|
}
|
|
402
418
|
else {
|
|
403
419
|
this.err("unexpected ConnectStatus ?");
|
|
@@ -406,7 +422,45 @@ class Master extends base_1.Base {
|
|
|
406
422
|
///////////////////
|
|
407
423
|
// Info messages //
|
|
408
424
|
///////////////////
|
|
409
|
-
|
|
425
|
+
receiveNodeMgtInfo(message) {
|
|
426
|
+
if (message[1] === protocol_1.reqNodeAttributes.isMaster) {
|
|
427
|
+
this.log("NodeMgtInfo - master " + this.getName() + " is set to master: " + message[2]);
|
|
428
|
+
}
|
|
429
|
+
else if (message[1] === protocol_1.reqNodeAttributes.nodeInfo) {
|
|
430
|
+
// should be the same as the one from the DBInfo (64)
|
|
431
|
+
this.log("NodeMgtInfo - node info for " + this.getName() + ": " + message);
|
|
432
|
+
}
|
|
433
|
+
else if (message[1] === protocol_1.reqNodeAttributes.masterSupported) {
|
|
434
|
+
this.log("NodeMgtInfo - master " + this.getName() + " can be master: " + message[2]);
|
|
435
|
+
}
|
|
436
|
+
else if (message[1] === protocol_1.reqNodeAttributes.nodeVersion) {
|
|
437
|
+
console.log("*** -> " + message);
|
|
438
|
+
this.log("NodeMgtInfo - version " + this.getName() + ", version: " + message[2] + "." + message[3]);
|
|
439
|
+
this.version = message[2] * 100 + message[3];
|
|
440
|
+
//BUG - TODO: remove
|
|
441
|
+
this.protocol = message[2] * 100 + message[3];
|
|
442
|
+
}
|
|
443
|
+
else if (message[1] === protocol_1.reqNodeAttributes.nodeProtocol) {
|
|
444
|
+
console.log("*** -> " + message);
|
|
445
|
+
this.log("NodeMgtInfo - protocol " + this.getName() + ", protocol: " + message[2] + "." + message[3]);
|
|
446
|
+
this.protocol = message[2] * 100 + message[3];
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
this.err("dropped NodeMgtInfo info message = " + message[1] + ", message: " + message);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
receiveRegister(message) {
|
|
453
|
+
const register = protocol_1.Protocol.makeWord(message, 2);
|
|
454
|
+
const value = protocol_1.Protocol.makeSigned(message, 4);
|
|
455
|
+
if ((register >= 0) && (register < 1024)) {
|
|
456
|
+
this.registers[register] = value;
|
|
457
|
+
this.log("receiveRegister(" + register + ") = " + value);
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
this.err("Received register out of bound: " + register);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
receiveHeartbeat(message) {
|
|
410
464
|
this.lastHeartbeat = new Date().getTime();
|
|
411
465
|
//console.log("*HB* Received HB");
|
|
412
466
|
this.log("Received heartbeat at " + (new Date()));
|
|
@@ -486,6 +540,9 @@ class Master extends base_1.Base {
|
|
|
486
540
|
}
|
|
487
541
|
this.system.setActiveState(unit);
|
|
488
542
|
}
|
|
543
|
+
//////////////////
|
|
544
|
+
// request info //
|
|
545
|
+
//////////////////
|
|
489
546
|
fetchAllUnits(node) {
|
|
490
547
|
return __awaiter(this, void 0, void 0, function* () {
|
|
491
548
|
for (let unitInx = 0; unitInx < node.nrUnits; unitInx++) {
|
|
@@ -694,6 +751,20 @@ class Master extends base_1.Base {
|
|
|
694
751
|
this.info("get value of " + unit.node.getName() + "-" + unit.getName());
|
|
695
752
|
});
|
|
696
753
|
}
|
|
754
|
+
requestRegisterValue(register) {
|
|
755
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
756
|
+
if (this.version >= 209) {
|
|
757
|
+
yield this.send(protocol_1.Protocol.buildRegister(register));
|
|
758
|
+
this.info("request register: " + register);
|
|
759
|
+
}
|
|
760
|
+
else {
|
|
761
|
+
this.err("FC_REGISTERMAP not available before protocol v2.09");
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
/////////////////////
|
|
766
|
+
// Settings values //
|
|
767
|
+
/////////////////////
|
|
697
768
|
setUnitStatus(unit, value) {
|
|
698
769
|
return __awaiter(this, void 0, void 0, function* () {
|
|
699
770
|
const params = protocol_1.Protocol.buildSetCmd(unit.node, unit, value);
|
|
@@ -702,6 +773,17 @@ class Master extends base_1.Base {
|
|
|
702
773
|
}
|
|
703
774
|
});
|
|
704
775
|
}
|
|
776
|
+
setRegisterValue(register, value) {
|
|
777
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
778
|
+
if (this.version >= 209) {
|
|
779
|
+
yield this.send(protocol_1.Protocol.buildRegister(register, value));
|
|
780
|
+
this.info("set register: " + register + ", to: " + value);
|
|
781
|
+
}
|
|
782
|
+
else {
|
|
783
|
+
this.err("FC_REGISTERMAP not available before protocol v2.09");
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
}
|
|
705
787
|
setSensorValue(unit, value) {
|
|
706
788
|
return __awaiter(this, void 0, void 0, function* () {
|
|
707
789
|
this.info("SetSensorValue of " + unit.node.logicalAddress + "/" + unit.logicalAddress + " to " + value);
|
package/duotecno/master.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Node, Protocol, Unit, recName, Rec, TempPreset } from "./protocol";
|
|
1
|
+
import { Node, Protocol, Unit, recName, Rec, TempPreset, reqNodeAttributes } from "./protocol";
|
|
2
2
|
import { MasterConfig, WriteError, CommRecord, Message, Sanitizers } from "./types";
|
|
3
3
|
import { log, debug } from "./logger";
|
|
4
4
|
import { System } from "./system";
|
|
@@ -15,6 +15,10 @@ export class Master extends Base {
|
|
|
15
15
|
public schedule: number;
|
|
16
16
|
public date: Date;
|
|
17
17
|
public lastHeartbeat: number;
|
|
18
|
+
public protocol: number = 0; // major * 100 + minor
|
|
19
|
+
public version: number = 0; // idem
|
|
20
|
+
|
|
21
|
+
public registers: {[register: number]: number} = {};
|
|
18
22
|
|
|
19
23
|
public isOpen: boolean;
|
|
20
24
|
public isLoggedIn: boolean;
|
|
@@ -166,6 +170,10 @@ export class Master extends Base {
|
|
|
166
170
|
|
|
167
171
|
// incoming data
|
|
168
172
|
this.buffer = "";
|
|
173
|
+
|
|
174
|
+
// init to v1.00
|
|
175
|
+
this.version = 100;
|
|
176
|
+
this.protocol = 100;
|
|
169
177
|
}
|
|
170
178
|
|
|
171
179
|
getName() {
|
|
@@ -398,8 +406,8 @@ export class Master extends Base {
|
|
|
398
406
|
return false;
|
|
399
407
|
|
|
400
408
|
} else {
|
|
401
|
-
|
|
402
|
-
|
|
409
|
+
// don't log all incoming (no time, no sensor status messages)
|
|
410
|
+
if ((next.cmd != Rec.TimeDateStatus) && (next.cmd != Rec.Sensor))
|
|
403
411
|
this.info("received -> " + recName(next.cmd) + " -> " + ((!next.message) ?
|
|
404
412
|
"--" : ((next.message instanceof Array) ? next.message.join(",") : next.message)));
|
|
405
413
|
|
|
@@ -423,6 +431,12 @@ export class Master extends Base {
|
|
|
423
431
|
|
|
424
432
|
} else if (next.cmd === Rec.ScheduleStatus) {
|
|
425
433
|
this.receiveSchedule(next.message);
|
|
434
|
+
|
|
435
|
+
} else if (next.cmd === Rec.NodeMgtInfo) {
|
|
436
|
+
this.receiveNodeMgtInfo(next.message);
|
|
437
|
+
|
|
438
|
+
} else if (next.cmd === Rec.Register) {
|
|
439
|
+
this.receiveRegister(next.message);
|
|
426
440
|
|
|
427
441
|
} else {
|
|
428
442
|
this.info("not handled: " + next.message);
|
|
@@ -442,6 +456,12 @@ export class Master extends Base {
|
|
|
442
456
|
if (this.resolveLogin) {
|
|
443
457
|
this.resolveLogin(this.isLoggedIn);
|
|
444
458
|
this.resolveLogin = null;
|
|
459
|
+
|
|
460
|
+
// if logged in, ask protocol version
|
|
461
|
+
if (this.isLoggedIn) {
|
|
462
|
+
this.send(Protocol.buildRequestNodeMgt(reqNodeAttributes.nodeProtocol));
|
|
463
|
+
}
|
|
464
|
+
|
|
445
465
|
} else {
|
|
446
466
|
this.err("unexpected ConnectStatus ?");
|
|
447
467
|
}
|
|
@@ -451,7 +471,48 @@ export class Master extends Base {
|
|
|
451
471
|
// Info messages //
|
|
452
472
|
///////////////////
|
|
453
473
|
|
|
454
|
-
|
|
474
|
+
receiveNodeMgtInfo(message: Message) {
|
|
475
|
+
if (message[1] === reqNodeAttributes.isMaster) {
|
|
476
|
+
this.log("NodeMgtInfo - master " + this.getName() + " is set to master: " + message[2]);
|
|
477
|
+
|
|
478
|
+
} else if (message[1] === reqNodeAttributes.nodeInfo) {
|
|
479
|
+
// should be the same as the one from the DBInfo (64)
|
|
480
|
+
this.log("NodeMgtInfo - node info for " + this.getName() + ": " + message);
|
|
481
|
+
|
|
482
|
+
} else if (message[1] === reqNodeAttributes.masterSupported) {
|
|
483
|
+
this.log("NodeMgtInfo - master " + this.getName() + " can be master: " + message[2]);
|
|
484
|
+
|
|
485
|
+
} else if (message[1] === reqNodeAttributes.nodeVersion) {
|
|
486
|
+
console.log("*** -> " + message);
|
|
487
|
+
this.log("NodeMgtInfo - version " + this.getName() + ", version: " + message[2] + "." + message[3]);
|
|
488
|
+
this.version = message[2] * 100 + message[3];
|
|
489
|
+
//BUG - TODO: remove
|
|
490
|
+
this.protocol = message[2] * 100 + message[3];
|
|
491
|
+
|
|
492
|
+
} else if (message[1] === reqNodeAttributes.nodeProtocol) {
|
|
493
|
+
console.log("*** -> " + message);
|
|
494
|
+
this.log("NodeMgtInfo - protocol " + this.getName() + ", protocol: " + message[2] + "." + message[3]);
|
|
495
|
+
this.protocol = message[2] * 100 + message[3];
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
} else {
|
|
499
|
+
this.err("dropped NodeMgtInfo info message = " + message[1] + ", message: " + message);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
receiveRegister(message: Message) {
|
|
504
|
+
const register = Protocol.makeWord(message, 2);
|
|
505
|
+
const value = Protocol.makeSigned(message, 4);
|
|
506
|
+
|
|
507
|
+
if ((register >=0) && (register < 1024)) {
|
|
508
|
+
this.registers[register] = value;
|
|
509
|
+
this.log("receiveRegister(" + register + ") = " + value);
|
|
510
|
+
} else {
|
|
511
|
+
this.err("Received register out of bound: " + register);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
receiveHeartbeat(message: Message) {
|
|
455
516
|
this.lastHeartbeat = new Date().getTime();
|
|
456
517
|
//console.log("*HB* Received HB");
|
|
457
518
|
this.log("Received heartbeat at " + (new Date()));
|
|
@@ -478,6 +539,7 @@ export class Master extends Base {
|
|
|
478
539
|
this.info("received week schedule = " + this.schedule);
|
|
479
540
|
}
|
|
480
541
|
|
|
542
|
+
|
|
481
543
|
receiveDateTime(message: Message) {
|
|
482
544
|
// 71,0,9,37,3,3,4,3,21,20 -> 09:37:03 Wednesday(3) 4 march 2120
|
|
483
545
|
this.date = new Date( (message[8]-1) * 100 + message[9], message[7]-1, message[6],
|
|
@@ -540,7 +602,9 @@ export class Master extends Base {
|
|
|
540
602
|
this.system.setActiveState(unit);
|
|
541
603
|
}
|
|
542
604
|
|
|
543
|
-
|
|
605
|
+
//////////////////
|
|
606
|
+
// request info //
|
|
607
|
+
//////////////////
|
|
544
608
|
async fetchAllUnits(node: Node) {
|
|
545
609
|
for (let unitInx=0; unitInx < node.nrUnits; unitInx++) {
|
|
546
610
|
await this.fetchUnit(node, unitInx);
|
|
@@ -755,6 +819,18 @@ export class Master extends Base {
|
|
|
755
819
|
this.info("get value of " + unit.node.getName() + "-" + unit.getName());
|
|
756
820
|
}
|
|
757
821
|
|
|
822
|
+
async requestRegisterValue(register: number) {
|
|
823
|
+
if (this.version >= 209) {
|
|
824
|
+
await this.send(Protocol.buildRegister(register));
|
|
825
|
+
this.info("request register: " + register);
|
|
826
|
+
} else {
|
|
827
|
+
this.err("FC_REGISTERMAP not available before protocol v2.09")
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/////////////////////
|
|
832
|
+
// Settings values //
|
|
833
|
+
/////////////////////
|
|
758
834
|
async setUnitStatus(unit: Unit, value: number) {
|
|
759
835
|
const params = Protocol.buildSetCmd(unit.node, unit, value);
|
|
760
836
|
if (params.cmd) {
|
|
@@ -762,6 +838,15 @@ export class Master extends Base {
|
|
|
762
838
|
}
|
|
763
839
|
}
|
|
764
840
|
|
|
841
|
+
async setRegisterValue(register: number, value: number) {
|
|
842
|
+
if (this.version >= 209) {
|
|
843
|
+
await this.send(Protocol.buildRegister(register, value));
|
|
844
|
+
this.info("set register: " + register + ", to: " + value);
|
|
845
|
+
} else {
|
|
846
|
+
this.err("FC_REGISTERMAP not available before protocol v2.09")
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
|
|
765
850
|
async setSensorValue(unit: Unit, value: number) {
|
|
766
851
|
this.info("SetSensorValue of " + unit.node.logicalAddress + "/" + unit.logicalAddress + " to " + value);
|
|
767
852
|
await this.send(Protocol.buildSetPreset(unit.node, unit, TempPreset.sun, Math.trunc(value / 100 / 100 / 100) % 100));
|
|
@@ -798,5 +883,4 @@ export class Master extends Base {
|
|
|
798
883
|
this.info("set temp preset of " + unit.node.getName() + "-" + unit.getName() + ": " + (inc ? "up" : "down"));
|
|
799
884
|
}
|
|
800
885
|
|
|
801
|
-
|
|
802
886
|
}
|