homebridge-smartsystem 6.3.3 → 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 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
- ### 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
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
- - 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 1 PM
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
-
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
@@ -8,254 +8,164 @@
8
8
  "type": "sun",
9
9
  "channel": "0",
10
10
  "low": 30,
11
- "high": 900,
11
+ "high": 3000,
12
12
  "actions": [
13
13
  {
14
- "name": "Mood A",
14
+ "name": "Lamp-Bottom",
15
15
  "value": false,
16
16
  "masterAddress": "192.168.0.97",
17
17
  "masterPort": 5001,
18
- "logicalAddress": 10,
19
- "logicalNodeAddress": 252
20
- },
21
- {
22
- "name": "Mood A",
23
- "value": 50,
24
- "masterAddress": "192.168.0.97",
25
- "masterPort": 5001,
26
- "logicalAddress": 10,
27
- "logicalNodeAddress": 252
18
+ "logicalAddress": 34,
19
+ "logicalNodeAddress": 3
28
20
  },
29
21
  {
30
- "name": "Mood A",
31
- "value": true,
32
- "masterAddress": "192.168.0.97",
33
- "masterPort": 5001,
34
- "logicalAddress": 10,
35
- "logicalNodeAddress": 252
36
- }
37
- ],
38
- "power": 3263,
39
- "current": 2
40
- },
41
- {
42
- "type": "power",
43
- "channel": "4",
44
- "low": 10,
45
- "high": 20,
46
- "actions": [
47
- {
48
- "name": "Mood B",
22
+ "name": "Lamp-Bottom",
49
23
  "value": false,
50
24
  "masterAddress": "192.168.0.97",
51
25
  "masterPort": 5001,
52
- "logicalAddress": 11,
53
- "logicalNodeAddress": 252
54
- },
55
- {
56
- "name": "Mood B",
57
- "value": 50,
58
- "masterAddress": "192.168.0.97",
59
- "masterPort": 5001,
60
- "logicalAddress": 11,
61
- "logicalNodeAddress": 252
26
+ "logicalAddress": 34,
27
+ "logicalNodeAddress": 3
62
28
  },
63
29
  {
64
- "name": "Mood B",
30
+ "name": "Lamp-Bottom",
65
31
  "value": true,
66
32
  "masterAddress": "192.168.0.97",
67
33
  "masterPort": 5001,
68
- "logicalAddress": 11,
69
- "logicalNodeAddress": 252
34
+ "logicalAddress": 34,
35
+ "logicalNodeAddress": 3
70
36
  }
71
37
  ],
72
- "power": 1,
38
+ "power": -758,
73
39
  "current": 0
74
40
  },
75
41
  {
76
42
  "type": "power",
77
43
  "channel": "7+8+9",
78
- "low": 30,
79
- "high": 900,
44
+ "low": 500,
45
+ "high": 10000,
80
46
  "actions": [
81
47
  {
82
- "name": "",
83
- "value": -1,
48
+ "name": "Blue LED",
49
+ "value": false,
84
50
  "masterAddress": "192.168.0.97",
85
51
  "masterPort": 5001,
86
- "logicalAddress": 4,
52
+ "logicalAddress": 30,
87
53
  "logicalNodeAddress": 3
88
54
  },
89
55
  {
90
- "name": "",
91
- "value": -1,
56
+ "name": "Blue LED",
57
+ "value": true,
92
58
  "masterAddress": "192.168.0.97",
93
59
  "masterPort": 5001,
94
- "logicalAddress": 4,
60
+ "logicalAddress": 30,
95
61
  "logicalNodeAddress": 3
96
62
  },
97
63
  {
98
- "name": "",
99
- "value": -1,
64
+ "name": "--",
65
+ "value": true,
100
66
  "masterAddress": "192.168.0.97",
101
67
  "masterPort": 5001,
102
- "logicalAddress": 4,
103
- "logicalNodeAddress": 3
68
+ "logicalAddress": 0,
69
+ "logicalNodeAddress": 0
104
70
  }
105
71
  ]
106
72
  },
107
73
  {
108
- "type": "sun",
109
- "channel": "7",
110
- "low": 0,
111
- "high": 0,
74
+ "type": "power",
75
+ "channel": "7+8+9",
76
+ "low": 400,
77
+ "high": 900,
112
78
  "actions": [
113
79
  {
114
- "name": "Mood C",
80
+ "name": "Lamp-Top",
115
81
  "value": false,
116
82
  "masterAddress": "192.168.0.97",
117
83
  "masterPort": 5001,
118
- "logicalAddress": 12,
119
- "logicalNodeAddress": 252
84
+ "logicalAddress": 33,
85
+ "logicalNodeAddress": 3
120
86
  },
121
87
  {
122
- "name": "Mood C",
123
- "value": 50,
88
+ "name": "Lamp-Top",
89
+ "value": true,
124
90
  "masterAddress": "192.168.0.97",
125
91
  "masterPort": 5001,
126
- "logicalAddress": 12,
127
- "logicalNodeAddress": 252
92
+ "logicalAddress": 33,
93
+ "logicalNodeAddress": 3
128
94
  },
129
95
  {
130
- "name": "Mood C",
96
+ "name": "--",
131
97
  "value": true,
132
98
  "masterAddress": "192.168.0.97",
133
99
  "masterPort": 5001,
134
- "logicalAddress": 12,
135
- "logicalNodeAddress": 252
100
+ "logicalAddress": 0,
101
+ "logicalNodeAddress": 0
136
102
  }
137
103
  ],
138
- "power": 3263,
139
- "current": 2
104
+ "power": 266,
105
+ "current": 0
140
106
  }
141
107
  ],
142
- "address": "192.168.0.186",
108
+ "address": "192.168.0.183",
143
109
  "uid": "57e3e0d8-bb05-4b04-8662-1a9871998f3f",
144
110
  "bindings": [
145
111
  {
146
- "logicalNodeAddress": 252,
147
- "logicalAddress": 102,
112
+ "channel": "0+1",
148
113
  "masterAddress": "192.168.0.97",
149
114
  "masterPort": 5001,
150
- "name": "unit 252:102",
151
- "displayName": "unit 252:102",
152
- "extendedType": 0,
153
- "channel": "0+1",
154
- "power": 1706
115
+ "register": 1
155
116
  },
156
117
  {
157
- "logicalNodeAddress": 252,
158
- "logicalAddress": 100,
118
+ "channel": "2+3",
159
119
  "masterAddress": "192.168.0.97",
160
120
  "masterPort": 5001,
161
- "name": "unit 252:100",
162
- "displayName": "unit 252:100",
163
- "extendedType": 0,
164
- "channel": "2+3",
165
- "power": 2494
121
+ "register": 2
166
122
  },
167
123
  {
168
- "logicalNodeAddress": 252,
169
- "logicalAddress": 103,
124
+ "channel": "4+5",
170
125
  "masterAddress": "192.168.0.97",
171
126
  "masterPort": 5001,
172
- "name": "unit 252:103",
173
- "displayName": "unit 252:103",
174
- "extendedType": 0,
175
- "channel": "4+5",
176
- "power": null
127
+ "register": 7
177
128
  },
178
129
  {
179
- "logicalNodeAddress": 252,
180
- "logicalAddress": 101,
130
+ "channel": "8",
181
131
  "masterAddress": "192.168.0.97",
182
132
  "masterPort": 5001,
183
- "name": "unit 252:101",
184
- "displayName": "unit 252:101",
185
- "extendedType": 0,
186
- "channel": "8",
187
- "power": null
133
+ "register": 8
188
134
  }
189
135
  ]
190
136
  },
191
137
  "p1": {
192
138
  "debug": false,
193
- "rules": [
194
- {
195
- "type": "power",
196
- "channel": "3+4+5",
197
- "low": 30,
198
- "high": 1500,
199
- "actions": [
200
- {
201
- "name": "--",
202
- "value": false,
203
- "masterAddress": "192.168.0.97",
204
- "masterPort": 5001,
205
- "logicalAddress": 0,
206
- "logicalNodeAddress": 0
207
- },
208
- {
209
- "name": "--",
210
- "value": 50,
211
- "masterAddress": "192.168.0.97",
212
- "masterPort": 5001,
213
- "logicalAddress": 0,
214
- "logicalNodeAddress": 0
215
- },
216
- {
217
- "name": "Alles aan",
218
- "value": true,
219
- "masterAddress": "192.168.0.97",
220
- "masterPort": 5001,
221
- "logicalAddress": 5,
222
- "logicalNodeAddress": 3
223
- }
224
- ]
225
- }
226
- ],
139
+ "rules": [],
227
140
  "bindings": [
228
141
  {
229
- "logicalNodeAddress": 252,
230
- "logicalAddress": 102,
142
+ "channel": "0+1+2",
231
143
  "masterAddress": "192.168.0.97",
232
144
  "masterPort": 5001,
233
- "name": "unit 252:102",
234
- "displayName": "unit 252:102",
235
- "extendedType": 0,
236
- "channel": "0+1+2",
237
- "power": null
145
+ "register": 11
238
146
  },
239
147
  {
240
- "logicalNodeAddress": 252,
241
- "logicalAddress": 100,
148
+ "channel": "3+4+5",
242
149
  "masterAddress": "192.168.0.97",
243
150
  "masterPort": 5001,
244
- "name": "unit 252:100",
245
- "displayName": "unit 252:100",
246
- "extendedType": 0,
247
- "channel": "3+4+5",
248
- "power": null
151
+ "register": 12
249
152
  }
250
153
  ],
251
- "address": "192.168.0.207"
154
+ "address": "192.168.0.206"
252
155
  },
253
156
  "shelly": {
254
157
  "debug": false,
255
158
  "address": "192.168.0.95",
256
159
  "addresses": "192.168.0.95,192.168.0.95",
257
160
  "rules": [],
258
- "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
+ ]
259
169
  },
260
170
  "smartapp": {
261
171
  "apiPort": 8581,
@@ -377,6 +287,21 @@
377
287
  "252": " 20211003"
378
288
  },
379
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
380
305
  }
381
306
  ],
382
307
  "cunits": [
@@ -428,6 +353,54 @@
428
353
  "used": "Y",
429
354
  "group": 0
430
355
  },
356
+ {
357
+ "logicalNodeAddress": 252,
358
+ "logicalAddress": 7,
359
+ "masterAddress": "192.168.0.97",
360
+ "masterPort": 5001,
361
+ "name": "Bottom-Left",
362
+ "displayName": "Bottom-Left",
363
+ "extendedType": 102,
364
+ "active": "Y",
365
+ "used": "Y",
366
+ "group": 0
367
+ },
368
+ {
369
+ "logicalNodeAddress": 3,
370
+ "logicalAddress": 30,
371
+ "masterAddress": "192.168.0.97",
372
+ "masterPort": 5001,
373
+ "name": "Blue LED",
374
+ "displayName": "Blue LED",
375
+ "extendedType": 1,
376
+ "active": "N",
377
+ "used": "Y",
378
+ "group": 0
379
+ },
380
+ {
381
+ "logicalNodeAddress": 3,
382
+ "logicalAddress": 34,
383
+ "masterAddress": "192.168.0.97",
384
+ "masterPort": 5001,
385
+ "name": "Lamp-Bottom",
386
+ "displayName": "Lamp-Bottom",
387
+ "extendedType": 2,
388
+ "active": "N",
389
+ "used": "Y",
390
+ "group": 0
391
+ },
392
+ {
393
+ "logicalNodeAddress": 3,
394
+ "logicalAddress": 33,
395
+ "masterAddress": "192.168.0.97",
396
+ "masterPort": 5001,
397
+ "name": "Lamp-Top",
398
+ "displayName": "Lamp-Top",
399
+ "extendedType": 2,
400
+ "active": "N",
401
+ "used": "Y",
402
+ "group": 0
403
+ },
431
404
  {
432
405
  "logicalNodeAddress": 3,
433
406
  "logicalAddress": 4,
@@ -469,7 +442,7 @@
469
442
  "units": []
470
443
  }
471
444
  ],
472
- "debug": false,
445
+ "debug": true,
473
446
  "settings": {
474
447
  "network": {
475
448
  "ip1": "1.2.3.4",
@@ -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
- if ((next.cmd != protocol_1.Rec.TimeDateStatus) &&
364
- (next.cmd != protocol_1.Rec.Sensor))
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
- receiveHeartbeat(next) {
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);