homebridge-smartsystem 6.1.6 → 6.1.7

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
@@ -257,6 +257,7 @@ Homebridge UI version
257
257
  - 4: errors when starting power mgrs from platform.ts
258
258
  - 5: v6.1.3 changes were gone... restored them.
259
259
  - 6: added login with pw in config + http.get with on-error
260
+ - 7: allow NaN in bindings compare for update
260
261
 
261
262
  ## Hardware
262
263
  A Raspberry Pi that connects to a Duotecno IP Node
package/config.json ADDED
@@ -0,0 +1,578 @@
1
+ {
2
+ "manufacturer": "Duotecno-Coppieterscc",
3
+ "platform": "DuotecnoPlatform",
4
+ "smappee": {
5
+ "rules": [
6
+ {
7
+ "type": "sun",
8
+ "channel": "0",
9
+ "low": 30,
10
+ "high": 900,
11
+ "actions": [
12
+ {
13
+ "name": "Mood A",
14
+ "value": false,
15
+ "masterAddress": "192.168.0.97",
16
+ "masterPort": 5001,
17
+ "logicalAddress": 10,
18
+ "logicalNodeAddress": 252
19
+ },
20
+ {
21
+ "name": "Mood A",
22
+ "value": 50,
23
+ "masterAddress": "192.168.0.97",
24
+ "masterPort": 5001,
25
+ "logicalAddress": 10,
26
+ "logicalNodeAddress": 252
27
+ },
28
+ {
29
+ "name": "Mood A",
30
+ "value": true,
31
+ "masterAddress": "192.168.0.97",
32
+ "masterPort": 5001,
33
+ "logicalAddress": 10,
34
+ "logicalNodeAddress": 252
35
+ }
36
+ ],
37
+ "power": -3382,
38
+ "current": 0
39
+ },
40
+ {
41
+ "type": "power",
42
+ "channel": "4",
43
+ "low": 10,
44
+ "high": 20,
45
+ "actions": [
46
+ {
47
+ "name": "Mood B",
48
+ "value": false,
49
+ "masterAddress": "192.168.0.97",
50
+ "masterPort": 5001,
51
+ "logicalAddress": 11,
52
+ "logicalNodeAddress": 252
53
+ },
54
+ {
55
+ "name": "Mood B",
56
+ "value": 50,
57
+ "masterAddress": "192.168.0.97",
58
+ "masterPort": 5001,
59
+ "logicalAddress": 11,
60
+ "logicalNodeAddress": 252
61
+ },
62
+ {
63
+ "name": "Mood B",
64
+ "value": true,
65
+ "masterAddress": "192.168.0.97",
66
+ "masterPort": 5001,
67
+ "logicalAddress": 11,
68
+ "logicalNodeAddress": 252
69
+ }
70
+ ],
71
+ "power": 0,
72
+ "current": 0
73
+ },
74
+ {
75
+ "type": "power",
76
+ "channel": "7+8+9",
77
+ "low": 30,
78
+ "high": 900,
79
+ "actions": [
80
+ {
81
+ "name": "Mood C",
82
+ "value": false,
83
+ "masterAddress": "192.168.0.97",
84
+ "masterPort": 5001,
85
+ "logicalAddress": 12,
86
+ "logicalNodeAddress": 252
87
+ },
88
+ {
89
+ "name": "Mood C",
90
+ "value": 50,
91
+ "masterAddress": "192.168.0.97",
92
+ "masterPort": 5001,
93
+ "logicalAddress": 12,
94
+ "logicalNodeAddress": 252
95
+ },
96
+ {
97
+ "name": "Mood C",
98
+ "value": true,
99
+ "masterAddress": "192.168.0.97",
100
+ "masterPort": 5001,
101
+ "logicalAddress": 12,
102
+ "logicalNodeAddress": 252
103
+ }
104
+ ],
105
+ "power": 2207,
106
+ "current": 2
107
+ },
108
+ {
109
+ "type": "sun",
110
+ "channel": "7",
111
+ "low": 0,
112
+ "high": 0,
113
+ "actions": [
114
+ {
115
+ "name": "Mood C",
116
+ "value": false,
117
+ "masterAddress": "192.168.0.97",
118
+ "masterPort": 5001,
119
+ "logicalAddress": 12,
120
+ "logicalNodeAddress": 252
121
+ },
122
+ {
123
+ "name": "Mood C",
124
+ "value": 50,
125
+ "masterAddress": "192.168.0.97",
126
+ "masterPort": 5001,
127
+ "logicalAddress": 12,
128
+ "logicalNodeAddress": 252
129
+ },
130
+ {
131
+ "name": "Mood C",
132
+ "value": true,
133
+ "masterAddress": "192.168.0.97",
134
+ "masterPort": 5001,
135
+ "logicalAddress": 12,
136
+ "logicalNodeAddress": 252
137
+ }
138
+ ]
139
+ }
140
+ ],
141
+ "address": "192.168.0.186",
142
+ "uid": "57e3e0d8-bb05-4b04-8662-1a9871998f3f",
143
+ "debug": false,
144
+ "bindings": [
145
+ {
146
+ "name": "<Solar",
147
+ "value": 0,
148
+ "masterAddress": "192.168.0.97",
149
+ "masterPort": 5001,
150
+ "logicalAddress": 102,
151
+ "logicalNodeAddress": 252,
152
+ "channel": "0+1",
153
+ "power": 1706
154
+ },
155
+ {
156
+ "name": ">Grid",
157
+ "value": 0,
158
+ "masterAddress": "192.168.0.97",
159
+ "masterPort": 5001,
160
+ "logicalAddress": 100,
161
+ "logicalNodeAddress": 252,
162
+ "channel": "2+3",
163
+ "power": 2494
164
+ },
165
+ {
166
+ "name": ">Cars",
167
+ "value": 0,
168
+ "masterAddress": "192.168.0.97",
169
+ "masterPort": 5001,
170
+ "logicalAddress": 103,
171
+ "logicalNodeAddress": 252,
172
+ "channel": "4+5",
173
+ "power": 0
174
+ },
175
+ {
176
+ "name": ">Swimmingpool",
177
+ "value": 0,
178
+ "masterAddress": "192.168.0.97",
179
+ "masterPort": 5001,
180
+ "logicalAddress": 101,
181
+ "logicalNodeAddress": 252,
182
+ "channel": "8",
183
+ "power": 0
184
+ }
185
+ ]
186
+ },
187
+ "p1": {
188
+ "rules": [
189
+ {
190
+ "type": "power",
191
+ "channel": "3+4+5",
192
+ "low": 30,
193
+ "high": 1500,
194
+ "actions": [
195
+ {
196
+ "name": "--",
197
+ "value": false,
198
+ "masterAddress": "192.168.0.97",
199
+ "masterPort": 5001,
200
+ "logicalAddress": 0,
201
+ "logicalNodeAddress": 0
202
+ },
203
+ {
204
+ "name": "--",
205
+ "value": 50,
206
+ "masterAddress": "192.168.0.97",
207
+ "masterPort": 5001,
208
+ "logicalAddress": 0,
209
+ "logicalNodeAddress": 0
210
+ },
211
+ {
212
+ "name": "Alles aan",
213
+ "value": true,
214
+ "masterAddress": "192.168.0.97",
215
+ "masterPort": 5001,
216
+ "logicalAddress": 5,
217
+ "logicalNodeAddress": 3
218
+ }
219
+ ]
220
+ }
221
+ ],
222
+ "bindings": [
223
+ {
224
+ "name": "<Solar Panels",
225
+ "value": 0,
226
+ "masterAddress": "192.168.0.97",
227
+ "masterPort": 5001,
228
+ "logicalAddress": 102,
229
+ "logicalNodeAddress": 252,
230
+ "channel": "0+1+2",
231
+ "power": null
232
+ },
233
+ {
234
+ "name": ">Grid",
235
+ "value": 0,
236
+ "masterAddress": "192.168.0.97",
237
+ "masterPort": 5001,
238
+ "logicalAddress": 100,
239
+ "logicalNodeAddress": 252,
240
+ "channel": "3+4+5",
241
+ "power": null
242
+ }
243
+ ],
244
+ "address": "192.168.0.214"
245
+ },
246
+ "shelly": false,
247
+ "smartapp": {
248
+ "apiPort": 8581,
249
+ "apiHost": "192.168.0.99",
250
+ "socapp": false,
251
+ "port": 5002,
252
+ "switches": [
253
+ {
254
+ "name": "Shelly Valies",
255
+ "unitName": "Red",
256
+ "masterAddress": "192.168.0.97",
257
+ "masterPort": 5001,
258
+ "nomacro": "Y",
259
+ "nostop": "Y",
260
+ "logicalAddress": 107,
261
+ "logicalNodeAddress": 252,
262
+ "type": "httpdim",
263
+ "plug": "http://192.168.0.96/light/0?brightness=$&turn=#",
264
+ "data": "",
265
+ "method": "GET",
266
+ "value": 0
267
+ },
268
+ {
269
+ "name": "Screen Salon Top",
270
+ "unitName": "Salon Top",
271
+ "masterAddress": "192.168.0.97",
272
+ "masterPort": 5001,
273
+ "nomacro": "N",
274
+ "nostop": "N",
275
+ "logicalAddress": 105,
276
+ "logicalNodeAddress": 252,
277
+ "type": "somfy",
278
+ "plug": "1",
279
+ "data": "",
280
+ "method": "GET",
281
+ "value": 0
282
+ },
283
+ {
284
+ "name": "Screen Tim small",
285
+ "unitName": "Tim Small",
286
+ "masterAddress": "192.168.0.97",
287
+ "masterPort": 5001,
288
+ "nomacro": "N",
289
+ "nostop": "Y",
290
+ "logicalAddress": 104,
291
+ "logicalNodeAddress": 252,
292
+ "type": "httpupdown",
293
+ "plug": "2",
294
+ "data": "",
295
+ "method": "GET",
296
+ "value": 0
297
+ },
298
+ {
299
+ "name": "Test Plug",
300
+ "unitName": "Plug",
301
+ "masterAddress": "gm.coppieters.be",
302
+ "masterPort": 5005,
303
+ "nomacro": "N",
304
+ "nostop": "N",
305
+ "logicalAddress": 35,
306
+ "logicalNodeAddress": 16,
307
+ "type": "smappee",
308
+ "plug": "1",
309
+ "data": "",
310
+ "method": "GET",
311
+ "value": 0
312
+ }
313
+ ],
314
+ "debug": false
315
+ },
316
+ "system": {
317
+ "language": "EN",
318
+ "stores": false,
319
+ "multiple": false,
320
+ "socketserver": "ws.duotecno.eu",
321
+ "socketport": 9999,
322
+ "mood": "sfeer",
323
+ "debug": false,
324
+ "cmasters": [
325
+ {
326
+ "address": "192.168.0.97",
327
+ "port": 5001,
328
+ "password": "GMTecno",
329
+ "name": "Valies",
330
+ "active": true,
331
+ "nodenames": {
332
+ "3": "SB 1",
333
+ "4": "oled",
334
+ "252": " 20211003"
335
+ },
336
+ "debug": false
337
+ }
338
+ ],
339
+ "cunits": [
340
+ {
341
+ "active": "Y",
342
+ "used": "Y",
343
+ "group": 0,
344
+ "name": "<Solar Panels",
345
+ "displayName": "<Solar Panels",
346
+ "type": 4,
347
+ "extendedType": null,
348
+ "masterAddress": "192.168.0.97",
349
+ "masterPort": 5001,
350
+ "logicalNodeAddress": 252,
351
+ "logicalAddress": 102
352
+ },
353
+ {
354
+ "active": "Y",
355
+ "used": "Y",
356
+ "group": 0,
357
+ "name": ">Cars",
358
+ "displayName": ">Cars",
359
+ "type": 4,
360
+ "extendedType": null,
361
+ "masterAddress": "192.168.0.97",
362
+ "masterPort": 5001,
363
+ "logicalNodeAddress": 252,
364
+ "logicalAddress": 103
365
+ },
366
+ {
367
+ "active": "Y",
368
+ "used": "Y",
369
+ "group": 0,
370
+ "name": ">Grid",
371
+ "displayName": ">Grid",
372
+ "type": 4,
373
+ "extendedType": null,
374
+ "masterAddress": "192.168.0.97",
375
+ "masterPort": 5001,
376
+ "logicalNodeAddress": 252,
377
+ "logicalAddress": 100
378
+ },
379
+ {
380
+ "active": "Y",
381
+ "used": "Y",
382
+ "group": 0,
383
+ "name": ">Swimmingpool",
384
+ "displayName": ">Swimmingpool",
385
+ "type": 4,
386
+ "extendedType": null,
387
+ "masterAddress": "192.168.0.97",
388
+ "masterPort": 5001,
389
+ "logicalNodeAddress": 252,
390
+ "logicalAddress": 101
391
+ },
392
+ {
393
+ "active": "Y",
394
+ "used": "Y",
395
+ "group": 0,
396
+ "name": "Salon Top",
397
+ "displayName": "Salon Top",
398
+ "type": 8,
399
+ "extendedType": 8,
400
+ "masterAddress": "192.168.0.97",
401
+ "masterPort": 5001,
402
+ "logicalNodeAddress": 252,
403
+ "logicalAddress": 105
404
+ },
405
+ {
406
+ "active": "Y",
407
+ "used": "Y",
408
+ "group": 0,
409
+ "name": "Tim Small",
410
+ "displayName": "Tim Small",
411
+ "type": 8,
412
+ "extendedType": 8,
413
+ "masterAddress": "192.168.0.97",
414
+ "masterPort": 5001,
415
+ "logicalNodeAddress": 252,
416
+ "logicalAddress": 104
417
+ },
418
+ {
419
+ "active": "Y",
420
+ "used": "Y",
421
+ "group": 0,
422
+ "name": "Plug 1",
423
+ "displayName": "Plug 1",
424
+ "type": 2,
425
+ "extendedType": 2,
426
+ "masterAddress": "192.168.0.97",
427
+ "masterPort": 5001,
428
+ "logicalNodeAddress": 252,
429
+ "logicalAddress": 106
430
+ },
431
+ {
432
+ "active": "Y",
433
+ "used": "Y",
434
+ "group": 0,
435
+ "name": "Smartbox",
436
+ "displayName": "Smartbox",
437
+ "type": 4,
438
+ "extendedType": null,
439
+ "masterAddress": "192.168.0.97",
440
+ "masterPort": 5001,
441
+ "logicalNodeAddress": 3,
442
+ "logicalAddress": 1
443
+ },
444
+ {
445
+ "active": "Y",
446
+ "used": "Y",
447
+ "group": 0,
448
+ "name": "Valies",
449
+ "displayName": "Valies",
450
+ "type": 4,
451
+ "extendedType": null,
452
+ "masterAddress": "192.168.0.97",
453
+ "masterPort": 5001,
454
+ "logicalNodeAddress": 3,
455
+ "logicalAddress": 0
456
+ },
457
+ {
458
+ "active": "Y",
459
+ "used": "Y",
460
+ "group": 0,
461
+ "name": "Blue LED",
462
+ "displayName": "Blue LED",
463
+ "type": 1,
464
+ "extendedType": null,
465
+ "masterAddress": "192.168.0.97",
466
+ "masterPort": 5001,
467
+ "logicalNodeAddress": 3,
468
+ "logicalAddress": 30
469
+ },
470
+ {
471
+ "active": "Y",
472
+ "used": "Y",
473
+ "group": 0,
474
+ "name": "Red LED",
475
+ "displayName": "Red LED",
476
+ "type": 1,
477
+ "extendedType": null,
478
+ "masterAddress": "192.168.0.97",
479
+ "masterPort": 5001,
480
+ "logicalNodeAddress": 3,
481
+ "logicalAddress": 29
482
+ },
483
+ {
484
+ "active": "Y",
485
+ "used": "Y",
486
+ "group": 0,
487
+ "name": "Bulb",
488
+ "displayName": "Bulb",
489
+ "type": 2,
490
+ "extendedType": 2,
491
+ "masterAddress": "192.168.0.97",
492
+ "masterPort": 5001,
493
+ "logicalNodeAddress": 3,
494
+ "logicalAddress": 35
495
+ },
496
+ {
497
+ "active": "Y",
498
+ "used": "Y",
499
+ "group": 0,
500
+ "name": "Lamp-Bottom",
501
+ "displayName": "Lamp-Bottom",
502
+ "type": 2,
503
+ "extendedType": 2,
504
+ "masterAddress": "192.168.0.97",
505
+ "masterPort": 5001,
506
+ "logicalNodeAddress": 3,
507
+ "logicalAddress": 34
508
+ },
509
+ {
510
+ "active": "Y",
511
+ "used": "Y",
512
+ "group": 0,
513
+ "name": "Lamp-Top",
514
+ "displayName": "Lamp-Top",
515
+ "type": 2,
516
+ "extendedType": 2,
517
+ "masterAddress": "192.168.0.97",
518
+ "masterPort": 5001,
519
+ "logicalNodeAddress": 3,
520
+ "logicalAddress": 33
521
+ },
522
+ {
523
+ "active": "Y",
524
+ "used": "Y",
525
+ "group": 0,
526
+ "name": "Stopcontact stk",
527
+ "displayName": "Stopcontact stk",
528
+ "type": 2,
529
+ "extendedType": 2,
530
+ "masterAddress": "192.168.0.97",
531
+ "masterPort": 5001,
532
+ "logicalNodeAddress": 3,
533
+ "logicalAddress": 36
534
+ },
535
+ {
536
+ "active": "Y",
537
+ "used": "Y",
538
+ "group": 0,
539
+ "name": "Alles aan",
540
+ "displayName": "Alles aan",
541
+ "type": 7,
542
+ "extendedType": 7,
543
+ "masterAddress": "192.168.0.97",
544
+ "masterPort": 5001,
545
+ "logicalNodeAddress": 3,
546
+ "logicalAddress": 5
547
+ },
548
+ {
549
+ "active": "Y",
550
+ "used": "Y",
551
+ "group": 0,
552
+ "name": "Alles uit",
553
+ "displayName": "Alles uit",
554
+ "type": 7,
555
+ "extendedType": 7,
556
+ "masterAddress": "192.168.0.97",
557
+ "masterPort": 5001,
558
+ "logicalNodeAddress": 3,
559
+ "logicalAddress": 4
560
+ }
561
+ ]
562
+ },
563
+ "scenes": [
564
+ {
565
+ "name": "Scene",
566
+ "trigger": {
567
+ "masterAddress": "0.0.0.0",
568
+ "masterPort": 5001,
569
+ "name": "unit",
570
+ "logicalAddress": 0,
571
+ "logicalNodeAddress": 0,
572
+ "value": true
573
+ },
574
+ "order": 0,
575
+ "units": []
576
+ }
577
+ ]
578
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.post = exports.get = void 0;
13
+ const http = require("http");
14
+ const types_1 = require("./types");
15
+ ///////////////////
16
+ // http function //
17
+ ///////////////////
18
+ function get(host, port, path, headers = {}) {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ return request('GET', host, port, path, {}, headers);
21
+ });
22
+ }
23
+ exports.get = get;
24
+ function post(host, port, path, body, headers = {}) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ return request('POST', host, port, path, body, headers);
27
+ });
28
+ }
29
+ exports.post = post;
30
+ function request(method, host, port, path, body, headers = {}) {
31
+ return __awaiter(this, void 0, void 0, function* () {
32
+ let timer;
33
+ let httpReq;
34
+ return new Promise((resolve, reject) => {
35
+ try {
36
+ timer = setTimeout(() => {
37
+ if (httpReq) {
38
+ httpReq.destroy();
39
+ }
40
+ reject("Request to " + host + path + " timed out");
41
+ }, 4000);
42
+ httpReq = http.request({ host, port, path, headers, method }, (response) => {
43
+ let str = '';
44
+ // another chunk of data has been received, so append it to `str`
45
+ response.on('data', (chunk) => {
46
+ str += chunk;
47
+ });
48
+ // the whole response has been received,
49
+ // stop the timer and resolve the promise with ithe collected result
50
+ response.on('end', () => {
51
+ if (timer)
52
+ clearTimeout(timer);
53
+ resolve(str);
54
+ });
55
+ }).on('error', (e) => {
56
+ if (timer)
57
+ clearTimeout(timer);
58
+ (0, types_1.err)("http", "http.get failed with " + JSON.stringify(e));
59
+ reject(e);
60
+ });
61
+ if (method === "POST") {
62
+ httpReq.write(JSON.stringify(body));
63
+ }
64
+ httpReq.end();
65
+ }
66
+ catch (error) {
67
+ (0, types_1.err)("http", "http.get failed with " + JSON.stringify(error));
68
+ reject(error);
69
+ }
70
+ });
71
+ });
72
+ }
73
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1,61 @@
1
+ import * as http from "http";
2
+ import { err } from "./types";
3
+
4
+
5
+ ///////////////////
6
+ // http function //
7
+ ///////////////////
8
+ export async function get(host: string, port: number, path: string, headers = {}): Promise<string> {
9
+ return request('GET', host, port, path, {}, headers);
10
+ }
11
+
12
+ export async function post(host: string, port: number, path: string, body: object, headers = {}): Promise<string> {
13
+ return request('POST', host, port, path, body, headers);
14
+ }
15
+
16
+ async function request(method: string, host: string, port: number, path: string, body: object, headers = {}): Promise<string> {
17
+ let timer;
18
+ let httpReq: http.ClientRequest;
19
+
20
+ return new Promise<any>((resolve, reject) => {
21
+ try {
22
+ timer = setTimeout(() => {
23
+ if (httpReq) {
24
+ httpReq.destroy();
25
+ }
26
+ reject("Request to " + host + path + " timed out");
27
+ }, 4000);
28
+
29
+ httpReq = http.request({ host, port, path, headers, method }, (response) => {
30
+ let str = '';
31
+
32
+ // another chunk of data has been received, so append it to `str`
33
+ response.on('data', (chunk) => {
34
+ str += chunk;
35
+ });
36
+
37
+ // the whole response has been received,
38
+ // stop the timer and resolve the promise with ithe collected result
39
+ response.on('end', () => {
40
+ if (timer) clearTimeout(timer);
41
+ resolve(str);
42
+ });
43
+
44
+ }).on('error', (e) => {
45
+ if (timer) clearTimeout(timer);
46
+ err("http", "http.get failed with " + JSON.stringify(e));
47
+ reject(e);
48
+ });
49
+
50
+ if (method === "POST") {
51
+ httpReq.write(JSON.stringify(body));
52
+ }
53
+ httpReq.end();
54
+
55
+
56
+ } catch(error) {
57
+ err("http", "http.get failed with " + JSON.stringify(error));
58
+ reject(error);
59
+ }
60
+ });
61
+ }
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ ///////////////////
3
+ // Global Config //
4
+ ///////////////////
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setAPIConfig = exports.getAPIConfig = exports.setSubConfig = exports.getSubConfig = exports.getConfig = exports.setConfig = exports.setToken = void 0;
7
+ const api_1 = require("./api");
8
+ const types_1 = require("./types");
9
+ const fs = require("fs");
10
+ const os_1 = require("os");
11
+ let gToken = "";
12
+ function setToken(token) {
13
+ gToken = token;
14
+ }
15
+ exports.setToken = setToken;
16
+ const isMac = ((0, os_1.platform)() === "darwin");
17
+ const kConfigFiles = (isMac) ? (__dirname + "/..") : ((0, os_1.homedir)() + "/duotecno");
18
+ if (!fs.existsSync(kConfigFiles))
19
+ fs.mkdirSync(kConfigFiles);
20
+ // set up empty config
21
+ let gPlatformConfig = types_1.Sanitizers.platform(null);
22
+ add("smartapp"); // webserver interface
23
+ add("settings"); // Pi settings
24
+ add("system"); // Duotecno system
25
+ add("server"); // web socket
26
+ add("smappee"); // power-smappee
27
+ add("p1"); // power-p1
28
+ // add("shelly"); // power-shelly
29
+ function add(type, cfg = null) {
30
+ gPlatformConfig[type] = types_1.Sanitizers[type] ? types_1.Sanitizers[type](cfg) : cfg;
31
+ }
32
+ // getter and setter
33
+ function setConfig(cfg) {
34
+ gPlatformConfig = types_1.Sanitizers.platform(cfg);
35
+ }
36
+ exports.setConfig = setConfig;
37
+ function getConfig() {
38
+ return gPlatformConfig;
39
+ }
40
+ exports.getConfig = getConfig;
41
+ function getSubConfig(type) {
42
+ const cfg = gPlatformConfig[type];
43
+ return types_1.Sanitizers[type] ? types_1.Sanitizers[type](cfg) : cfg;
44
+ }
45
+ exports.getSubConfig = getSubConfig;
46
+ function setSubConfig(type, cfg) {
47
+ gPlatformConfig[type] = types_1.Sanitizers[type] ? types_1.Sanitizers[type](cfg) : cfg;
48
+ }
49
+ exports.setSubConfig = setSubConfig;
50
+ // we should get the config through the homebridge platform init call !!
51
+ function getAPIConfig(done) {
52
+ let config = null;
53
+ if (gPlatformConfig.apiHost) {
54
+ const headers = { "Content-Type": "application/json" };
55
+ if (gToken) {
56
+ headers["Authorization"] = "Bearer " + gToken;
57
+ }
58
+ (0, api_1.get)(gPlatformConfig.apiHost, gPlatformConfig.apiPort, "/api/config-editor", headers).then((resp) => {
59
+ (0, types_1.debug)("smartapp", "OK: " + resp);
60
+ const parsed = JSON.parse(resp);
61
+ setConfig(parsed);
62
+ if (done)
63
+ done(parsed);
64
+ }, (err) => {
65
+ (0, types_1.debug)("smartapp", "ERROR: " + JSON.stringify(err));
66
+ done(null);
67
+ });
68
+ }
69
+ else {
70
+ const fn = kConfigFiles + "/config.json";
71
+ try {
72
+ const configBuf = fs.readFileSync(fn);
73
+ const configStr = configBuf.toString();
74
+ config = JSON.parse(configStr);
75
+ }
76
+ catch (err) {
77
+ (0, types_1.log)("system", "Couldn't read my config file (" + fn + ") -- Creating empty config.");
78
+ }
79
+ // sanitize the config
80
+ const sanitized = types_1.Sanitizers.platform(config);
81
+ setConfig(sanitized);
82
+ done(sanitized);
83
+ }
84
+ }
85
+ exports.getAPIConfig = getAPIConfig;
86
+ function setAPIConfig() {
87
+ if (gPlatformConfig.apiHost) {
88
+ const headers = { "Content-Type": "application/json" };
89
+ if (gToken) {
90
+ headers["Authorization"] = "Bearer " + gToken;
91
+ }
92
+ (0, api_1.post)(gPlatformConfig.apiHost, gPlatformConfig.apiPort, "/api/config-editor", gPlatformConfig, headers).then((resp) => (0, types_1.debug)("smartapp", "OK: " + resp), (err) => (0, types_1.debug)("smartapp", "ERROR: " + JSON.stringify(err)));
93
+ }
94
+ else {
95
+ const fn = kConfigFiles + "/config.json";
96
+ try {
97
+ fs.writeFileSync(fn, JSON.stringify(gPlatformConfig, null, 2));
98
+ }
99
+ catch (error) {
100
+ (0, types_1.err)(this.type, "Couldn't write config.json file (" + fn + ")");
101
+ }
102
+ }
103
+ }
104
+ exports.setAPIConfig = setAPIConfig;
105
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,118 @@
1
+
2
+ ///////////////////
3
+ // Global Config //
4
+ ///////////////////
5
+
6
+ import { get, post } from "./api";
7
+ import { debug, err, log, PlatformConfig, Sanitizers } from "./types";
8
+ import * as fs from "fs";
9
+ import { homedir, platform } from "os";
10
+
11
+ let gToken = "";
12
+
13
+ export function setToken(token: string) {
14
+ gToken = token;
15
+ }
16
+
17
+ const isMac = (platform() === "darwin");
18
+ const kConfigFiles = (isMac) ? (__dirname+"/..") : (homedir() + "/duotecno");
19
+ if (! fs.existsSync(kConfigFiles)) fs.mkdirSync(kConfigFiles);
20
+
21
+
22
+ // set up empty config
23
+ let gPlatformConfig: PlatformConfig = Sanitizers.platform(null);
24
+
25
+ add("smartapp"); // webserver interface
26
+ add("settings"); // Pi settings
27
+ add("system"); // Duotecno system
28
+ add("server"); // web socket
29
+
30
+ add("smappee"); // power-smappee
31
+ add("p1"); // power-p1
32
+ // add("shelly"); // power-shelly
33
+
34
+ function add(type: string, cfg = null) {
35
+ gPlatformConfig[type] = Sanitizers[type] ? Sanitizers[type](cfg) : cfg;
36
+ }
37
+
38
+ // getter and setter
39
+ export function setConfig(cfg: PlatformConfig) {
40
+ gPlatformConfig = Sanitizers.platform(cfg);
41
+ }
42
+ export function getConfig(): PlatformConfig {
43
+ return gPlatformConfig;
44
+ }
45
+
46
+
47
+
48
+
49
+ export function getSubConfig(type: string): object {
50
+ const cfg = gPlatformConfig[type];
51
+ return Sanitizers[type] ? Sanitizers[type](cfg) : cfg;
52
+ }
53
+
54
+ export function setSubConfig(type: string, cfg: object) {
55
+ gPlatformConfig[type] = Sanitizers[type] ? Sanitizers[type](cfg) : cfg;
56
+ }
57
+
58
+
59
+ // we should get the config through the homebridge platform init call !!
60
+ export function getAPIConfig(done) {
61
+ let config = null;
62
+ if (gPlatformConfig.apiHost) {
63
+ const headers = {"Content-Type": "application/json"};
64
+ if (gToken) {
65
+ headers["Authorization"] = "Bearer "+ gToken;
66
+ }
67
+ get(gPlatformConfig.apiHost, gPlatformConfig.apiPort, "/api/config-editor", headers).then(
68
+ (resp) => {
69
+ debug("smartapp", "OK: " + resp);
70
+ const parsed = JSON.parse(resp);
71
+ setConfig(parsed);
72
+ if (done)
73
+ done(parsed);
74
+ },
75
+ (err) => {
76
+ debug("smartapp", "ERROR: " + JSON.stringify(err));
77
+ done(null);
78
+ }
79
+ );
80
+ } else {
81
+ const fn = kConfigFiles + "/config.json";
82
+
83
+ try {
84
+ const configBuf = fs.readFileSync(fn);
85
+ const configStr = configBuf.toString();
86
+ config = JSON.parse(configStr);
87
+
88
+ } catch(err) {
89
+ log("system", "Couldn't read my config file (" + fn + ") -- Creating empty config.")
90
+ }
91
+ // sanitize the config
92
+ const sanitized = Sanitizers.platform(config);
93
+ setConfig(sanitized);
94
+
95
+ done(sanitized);
96
+ }
97
+ }
98
+
99
+ export function setAPIConfig() {
100
+ if (gPlatformConfig.apiHost) {
101
+ const headers = {"Content-Type": "application/json"};
102
+ if (gToken) {
103
+ headers["Authorization"] = "Bearer "+ gToken;
104
+ }
105
+ post(gPlatformConfig.apiHost, gPlatformConfig.apiPort, "/api/config-editor", gPlatformConfig, headers).then(
106
+ (resp) => debug("smartapp", "OK: " + resp),
107
+ (err) => debug("smartapp", "ERROR: " + JSON.stringify(err))
108
+ );
109
+ } else {
110
+ const fn = kConfigFiles + "/config.json";
111
+ try {
112
+ fs.writeFileSync(fn, JSON.stringify(gPlatformConfig, null, 2));
113
+
114
+ } catch(error) {
115
+ err(this.type, "Couldn't write config.json file (" + fn + ")");
116
+ }
117
+ }
118
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-smartsystem",
3
3
  "displayname": "Duotecno Bridge",
4
- "version": "6.1.6",
4
+ "version": "6.1.7",
5
5
  "description": "SmartServer (Proxy Websockets to TCP sockets, Smappee MQTT, Duotecno IP Nodes, Homekit interface)",
6
6
  "main": "index.js",
7
7
  "author": "Johan Coppieters",
@@ -137,7 +137,7 @@ class PowerBase extends base_1.Base {
137
137
  // for all bindings
138
138
  this.bindings.forEach(b => {
139
139
  const power = this.evalPower(b.channel);
140
- if (!isNaN(b.power) && !isNaN(power) && (Math.abs(b.power - power) > Math.abs(b.power * 0.1))) {
140
+ if ((!isNaN(power)) && (isNaN(b.power) || (Math.abs(b.power - power) > Math.abs(b.power * 0.1)))) {
141
141
  (0, types_1.debug)("power", "APPLY to " + b.channel + " = " + b.power + " -> " + power + " for " + b.name + " (" + b.logicalNodeAddress + ";" + b.logicalAddress + "): difference: " + Math.abs(b.power - power) + " > threshold: " + Math.abs(b.power * 0.1));
142
142
  this.applyBinding(b, power)
143
143
  .then(value => {
@@ -158,7 +158,7 @@ export class PowerBase extends Base {
158
158
  // for all bindings
159
159
  this.bindings.forEach( b => {
160
160
  const power = this.evalPower(b.channel);
161
- if (!isNaN(b.power) && !isNaN(power) && (Math.abs(b.power - power) > Math.abs(b.power * 0.1))) {
161
+ if ((!isNaN(power)) && (isNaN(b.power) || (Math.abs(b.power - power) > Math.abs(b.power * 0.1)))) {
162
162
  debug("power", "APPLY to " + b.channel + " = " + b.power + " -> " + power + " for " + b.name + " (" + b.logicalNodeAddress + ";" + b.logicalAddress + "): difference: " + Math.abs(b.power - power) + " > threshold: " + Math.abs(b.power * 0.1))
163
163
  this.applyBinding(b, power)
164
164
  .then(value => {
@@ -0,0 +1,57 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <link type="text/css" rel="stylesheet" href="/files/min.css" media="screen,projection"/>
5
+
6
+ <!--Let browser know website is optimized for mobile-->
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
8
+ <link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
9
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
10
+
11
+ <%- include('/views/style'); -%>
12
+ </head>
13
+
14
+ <body>
15
+ <nav>
16
+ <div class="nav-wrapper">
17
+ <a href="/" target=_blank class="brand-logo hide-on-small-only">Duotecno</a>
18
+ </div>
19
+ </nav>
20
+
21
+ <% if (message) { %>
22
+ <p class="message"><b>Message: </b>
23
+ <%= message %>
24
+ </p>
25
+ <% } %>
26
+
27
+ <form method="post" action="/login">
28
+ <input type="hidden" name="daction" value="login" />
29
+
30
+ <h1>
31
+ <button class="right btn waves-effect waves-light" type="submit" name="action" value="login">Log in</button>
32
+ </h1>
33
+
34
+ <div class="row">
35
+ <div class="input-field col s12">
36
+ <input type="text" name="user" id="user" value="" />
37
+ <label for="user">Username</label>
38
+ </div>
39
+ </div>
40
+
41
+ <div class="row">
42
+ <div class="input-field col s12">
43
+ <input type="password" name="password" id="password" value="" />
44
+ <label for="password">Password</label>
45
+ </div>
46
+ </div>
47
+ </form>
48
+
49
+ <footer class="page-footer">
50
+ <p>
51
+ Johan Coppieters - Duotecno, 2019-<%= year %> - v<%= version %>
52
+ </p>
53
+ </footer>
54
+
55
+ </body>
56
+ <%- include('/views/scripts'); -%>
57
+ </html>