@homebridge-plugins/homebridge-tado 6.0.14

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +152 -0
  2. package/LICENSE +21 -0
  3. package/README.md +560 -0
  4. package/config.schema.json +878 -0
  5. package/homebridge-ui/public/css/style.css +25 -0
  6. package/homebridge-ui/public/images/tado_logo.png +0 -0
  7. package/homebridge-ui/public/index.html +118 -0
  8. package/homebridge-ui/public/js/main.js +1582 -0
  9. package/homebridge-ui/public/js/modules/compareVersions.min.js +1 -0
  10. package/homebridge-ui/public/js/modules/jquery.min.js +2 -0
  11. package/homebridge-ui/public/js/modules/progressbar.min.js +6 -0
  12. package/homebridge-ui/public/js/progressbars.js +48 -0
  13. package/homebridge-ui/public/js/schema.js +864 -0
  14. package/homebridge-ui/server.js +80 -0
  15. package/images/tado_logo.png +0 -0
  16. package/index.js +14 -0
  17. package/package.json +66 -0
  18. package/src/accessories/airquality.js +56 -0
  19. package/src/accessories/contact.js +124 -0
  20. package/src/accessories/faucet.js +63 -0
  21. package/src/accessories/heatercooler.js +333 -0
  22. package/src/accessories/humidity.js +90 -0
  23. package/src/accessories/lightbulb.js +59 -0
  24. package/src/accessories/lightsensor.js +40 -0
  25. package/src/accessories/motion.js +79 -0
  26. package/src/accessories/occupancy.js +45 -0
  27. package/src/accessories/security.js +79 -0
  28. package/src/accessories/switch.js +261 -0
  29. package/src/accessories/temperature.js +95 -0
  30. package/src/accessories/thermostat.js +337 -0
  31. package/src/helper/handler.js +1467 -0
  32. package/src/helper/logger.js +51 -0
  33. package/src/helper/telegram.js +60 -0
  34. package/src/platform.js +337 -0
  35. package/src/tado/tado-api.js +404 -0
  36. package/src/tado/tado-config.js +1032 -0
  37. package/src/types/custom.js +264 -0
  38. package/src/types/eve.js +337 -0
@@ -0,0 +1,1582 @@
1
+ /*global $, window, homebridge, fetchDevicesBar, schema*/
2
+
3
+ const pageNavigation = {
4
+ currentContent: false,
5
+ previousContent: []
6
+ };
7
+
8
+ let customSchemaActive = false;
9
+ let pluginConfig = false;
10
+ let currentHome = false;
11
+
12
+ const TIMEOUT = (ms) => new Promise((res) => setTimeout(res, ms));
13
+
14
+ function toggleContent(){
15
+
16
+ $('#header').hide();
17
+ $('#main').show();
18
+
19
+ return;
20
+
21
+ }
22
+
23
+ async function showOldSchema(oldVersion) {
24
+
25
+ let config = await homebridge.getPluginConfig();
26
+
27
+ if(oldVersion){
28
+
29
+ $('#main').removeClass('pb-5');
30
+ $('#notSupported').show();
31
+
32
+ setTimeout(() => {
33
+ $('#main').fadeOut(500);
34
+ }, 5000);
35
+
36
+ } else {
37
+
38
+ let activeContent = $('#notConfigured').css('display') !== 'none'
39
+ ? '#notConfigured'
40
+ : '#isConfigured';
41
+
42
+ transPage($('#main, ' + activeContent), $('#headerOld'), false, true);
43
+
44
+ }
45
+
46
+ if(!config.length)
47
+ homebridge.updatePluginConfig([{}]);
48
+
49
+ homebridge.showSchemaForm();
50
+
51
+ return;
52
+
53
+ }
54
+
55
+ function transPage(cur, next, removed, showSchema) {
56
+
57
+ if(showSchema){
58
+
59
+ cur.hide();
60
+ next.show();
61
+
62
+ //pageNavigation.previousContent.push($('#isConfigured'));
63
+ pageNavigation.previousContent.push(cur);
64
+ pageNavigation.currentContent = next;
65
+
66
+ return;
67
+
68
+ } else {
69
+
70
+ toggleContent();
71
+
72
+ }
73
+
74
+ if(cur){
75
+
76
+ cur.fadeOut(500, () =>{
77
+
78
+ next.fadeIn(500);
79
+
80
+ if(!removed)
81
+ pageNavigation.previousContent.push(cur);
82
+
83
+ pageNavigation.currentContent = next;
84
+
85
+ });
86
+
87
+ } else {
88
+
89
+ next.fadeIn(500);
90
+
91
+ if(!removed)
92
+ pageNavigation.previousContent.push(next);
93
+
94
+ pageNavigation.currentContent = next;
95
+
96
+ }
97
+
98
+ if(customSchemaActive)
99
+ customSchemaActive.end();
100
+
101
+ homebridge.hideSchemaForm();
102
+
103
+ return;
104
+
105
+ }
106
+
107
+ function goBack(index) {
108
+
109
+ if(pageNavigation.previousContent.length && pageNavigation.currentContent){
110
+
111
+ index = index === undefined
112
+ ? pageNavigation.previousContent.length - 1
113
+ : index;
114
+
115
+ transPage(pageNavigation.currentContent, pageNavigation.previousContent[index], true);
116
+ //pageNavigation.currentContent = pageNavigation.previousContent[index];
117
+ pageNavigation.previousContent.splice(index, 1);
118
+
119
+ if(customSchemaActive)
120
+ customSchemaActive.end();
121
+
122
+ }
123
+
124
+ return;
125
+
126
+ }
127
+
128
+ async function createCustomSchema(home){
129
+
130
+ //schema.layout.homes.forEach()
131
+
132
+ customSchemaActive = homebridge.createForm(schema, {
133
+ name: pluginConfig[0].name,
134
+ debug: pluginConfig[0].debug,
135
+ homes: home
136
+ });
137
+
138
+ customSchemaActive.onChange(async config => {
139
+
140
+ pluginConfig[0].name = config.name;
141
+ pluginConfig[0].debug = config.debug;
142
+ pluginConfig[0].homes = pluginConfig[0].homes.map(myHome => {
143
+ if(myHome.name === config.homes.name){
144
+ myHome = config.homes;
145
+ }
146
+ return myHome;
147
+ });
148
+
149
+ try {
150
+
151
+ await homebridge.updatePluginConfig(pluginConfig);
152
+
153
+ } catch(err) {
154
+
155
+ console.log(err);
156
+ homebridge.toast.error(err.message, 'Error');
157
+
158
+ }
159
+
160
+ });
161
+
162
+ return;
163
+
164
+ }
165
+
166
+ async function resetUI(){
167
+
168
+ homebridge.request('/reset');
169
+
170
+ resetForm();
171
+ resetSchema();
172
+
173
+ currentHome = false;
174
+
175
+ return;
176
+
177
+ }
178
+
179
+ function resetForm(){
180
+
181
+ $('#homeUsername').val('');
182
+ $('#homePassword').val('');
183
+
184
+ if(fetchDevicesBar)
185
+ fetchDevicesBar.set(0);
186
+
187
+ return;
188
+
189
+ }
190
+
191
+ function resetSchema(){
192
+
193
+ if(customSchemaActive){
194
+ customSchemaActive.end();
195
+ customSchemaActive = false;
196
+ }
197
+
198
+ return;
199
+
200
+ }
201
+
202
+ function addDeviceToList(home){
203
+
204
+ let name = home.name;
205
+ let owner = home.username;
206
+
207
+ $('#deviceSelect').append('<option value="' + name + '">' + name + ' &lt;' + owner + '&gt;' + '</option>');
208
+
209
+ return;
210
+
211
+ }
212
+
213
+ function removeDeviceFromList(home){
214
+
215
+ let name = typeof home === 'string' ? home : home.name;
216
+ $('#deviceSelect option[value=\'' + name + '\']').remove();
217
+
218
+ return;
219
+
220
+ }
221
+
222
+ async function addNewDeviceToConfig(config, refresh, resync){
223
+
224
+ try {
225
+
226
+ for(const i in config[0].homes){
227
+
228
+ let found = false;
229
+
230
+ for(const j in pluginConfig[0].homes)
231
+ if(config[0].homes[i].name === pluginConfig[0].homes[j].name)
232
+ found = true;
233
+
234
+ if(!found){
235
+ addDeviceToList(config[0].homes[i]);
236
+ homebridge.toast.success(config[0].homes[i].name + ' added to config!', 'Success');
237
+ } else if(refresh){
238
+ homebridge.toast.success(config[0].homes[i].name + ' refreshed!', 'Success');
239
+ } else if(resync) {
240
+ homebridge.toast.success(config[0].homes[i].name + ' resynchronized!', 'Success');
241
+ }
242
+
243
+ }
244
+
245
+ pluginConfig = JSON.parse(JSON.stringify(config));
246
+
247
+ await homebridge.updatePluginConfig(pluginConfig);
248
+ await homebridge.savePluginConfig();
249
+
250
+ } catch(err) {
251
+
252
+ console.log(err);
253
+ homebridge.toast.error(err.message, 'Error');
254
+
255
+ }
256
+
257
+ return;
258
+
259
+ }
260
+
261
+ async function removeDeviceFromConfig(name){
262
+
263
+ currentHome = name || currentHome;
264
+
265
+ let foundIndex;
266
+ let pluginConfigBkp = JSON.parse(JSON.stringify(pluginConfig));
267
+
268
+ pluginConfig[0].homes.forEach((home, index) => {
269
+ if(home.name === currentHome){
270
+ foundIndex = index;
271
+ }
272
+ });
273
+
274
+ if(foundIndex !== undefined){
275
+
276
+ try {
277
+
278
+ pluginConfig[0].homes.splice(foundIndex, 1);
279
+ removeDeviceFromList(currentHome);
280
+
281
+ if(!pluginConfig[0].homes.length){
282
+ delete pluginConfig[0].debug;
283
+ }
284
+
285
+ await homebridge.updatePluginConfig(pluginConfig);
286
+ await homebridge.savePluginConfig();
287
+
288
+ homebridge.toast.success(currentHome + ' removed from config!', 'Success');
289
+
290
+ } catch(err) {
291
+
292
+ pluginConfig = JSON.parse(JSON.stringify(pluginConfigBkp));
293
+
294
+ throw err;
295
+
296
+ }
297
+
298
+ } else {
299
+
300
+ throw new Error('No home found in config to remove!');
301
+
302
+ }
303
+
304
+ return;
305
+
306
+ }
307
+
308
+ async function fetchDevices(credentials, refresh, resync){
309
+
310
+ if(!credentials && !resync)
311
+ return homebridge.toast.error('No credentials!', 'Error');
312
+
313
+ const config = JSON.parse(JSON.stringify(pluginConfig));
314
+
315
+ try {
316
+
317
+ if(!resync){
318
+ //Init API with credentials
319
+ homebridge.request('/authenticate', credentials);
320
+
321
+ await TIMEOUT(2000);
322
+
323
+ fetchDevicesBar.animate(0.20);
324
+ }
325
+
326
+ if(refresh){
327
+
328
+ //refresh selected home
329
+
330
+ //Home Informations
331
+ let home = config[0].homes.find(home => home && home.name === currentHome);
332
+
333
+ if(!home)
334
+ return homebridge.toast.error('Cannot refresh ' + currentHome + '. Not found in config!', 'Error');
335
+
336
+ if(!home.id){
337
+ homebridge.toast.info('No Home ID defined in config. Getting Home ID for ' + home.name, credentials.username);
338
+ const me = await homebridge.request('/exec', {dest: 'getMe'});
339
+ me.homes.map(foundHome => {
340
+ if(foundHome.name === home.name)
341
+ home.id = foundHome.id;
342
+ });
343
+ await TIMEOUT(1000);
344
+ if(!home.id)
345
+ return homebridge.toast.error('Cannot get a Home ID for ' + home.name + '. ' + home.name + ' not found for this user!', credentials.username);
346
+ }
347
+
348
+ await TIMEOUT(2000);
349
+
350
+ fetchDevicesBar.animate(0.40);
351
+
352
+ const homeInfo = await homebridge.request('/exec', {dest: 'getHome', data: home.id});
353
+
354
+ for(let [i, home] of config[0].homes.entries()){
355
+
356
+ if(config[0].homes[i].name === homeInfo.name){
357
+
358
+ config[0].homes[i].id = homeInfo.id;
359
+ config[0].homes[i].username = credentials.username;
360
+ config[0].homes[i].password = credentials.password;
361
+ config[0].homes[i].temperatureUnit = homeInfo.temperatureUnit || 'CELSIUS';
362
+ config[0].homes[i].zones = config[0].homes[i].zones || [];
363
+
364
+ if(homeInfo.geolocation)
365
+ config[0].homes[i].geolocation = {
366
+ longitude: homeInfo.geolocation.longitude.toString(),
367
+ latitude: homeInfo.geolocation.latitude.toString()
368
+ };
369
+
370
+ //init devices for childLock
371
+ config[0].homes[i].extras = config[0].homes[i].extras || {};
372
+ config[0].homes[i].extras.childLockSwitches = config[0].homes[i].extras.childLockSwitches || [];
373
+
374
+ let allFoundDevices = [];
375
+
376
+ await TIMEOUT(2000);
377
+
378
+ fetchDevicesBar.animate(0.60);
379
+
380
+ //Mobile Devices Informations
381
+ const mobileDevices = await homebridge.request('/exec', {dest: 'getMobileDevices', data: home.id});
382
+
383
+ if(!config[0].homes[i].presence)
384
+ config[0].homes[i].presence = {
385
+ anyone: false,
386
+ accTypeAnyone: 'OCCUPANCY',
387
+ user: []
388
+ };
389
+
390
+ //Remove not registred devices
391
+ config[0].homes[i].presence.user.forEach((user, index) => {
392
+ let found = false;
393
+ mobileDevices.forEach(foundUser => {
394
+ if(foundUser.name === user.name){
395
+ found = true;
396
+ }
397
+ });
398
+ if(!found){
399
+ homebridge.toast.info(user.name + ' removed from config!', credentials.username);
400
+ config[0].homes[i].presence.user.splice(index, 1);
401
+ }
402
+ });
403
+
404
+ //Check for new registred devices
405
+ if(config[0].homes[i].presence.user.length){
406
+ for(const foundUser of mobileDevices){
407
+ let userIndex;
408
+ config[0].homes[i].presence.user.forEach((user, index) => {
409
+ if(user.name === foundUser.name){
410
+ userIndex = index;
411
+ }
412
+ });
413
+ if(userIndex === undefined){
414
+ config[0].homes[i].presence.user.push({
415
+ active: false,
416
+ name: foundUser.name,
417
+ accType: 'OCCUPANCY'
418
+ });
419
+ }
420
+ }
421
+ } else {
422
+ config[0].homes[i].presence.user = mobileDevices.map(user => {
423
+ return {
424
+ active: false,
425
+ name: user.name,
426
+ accType: 'OCCUPANCY'
427
+ };
428
+ });
429
+ }
430
+
431
+ await TIMEOUT(2000);
432
+
433
+ fetchDevicesBar.animate(0.80);
434
+
435
+ //Zone Informations
436
+ const zones = await homebridge.request('/exec', {dest: 'getZones', data: home.id});
437
+
438
+ //Remove not available zones
439
+ config[0].homes[i].zones.forEach((zone, index) => {
440
+ let found = false;
441
+ zones.forEach(foundZone => {
442
+ if(foundZone.name === zone.name){
443
+ found = true;
444
+ }
445
+ });
446
+ if(!found){
447
+ homebridge.toast.info(zone.name + ' removed from config!', credentials.username);
448
+ config[0].homes[i].zones.splice(index, 1);
449
+ }
450
+ });
451
+
452
+ //Check for new zones or refresh exist one
453
+ if(config[0].homes[i].zones.length){
454
+ for(const foundZone of zones){
455
+
456
+ const capabilities = await homebridge.request('/exec', {dest: 'getZoneCapabilities', data: [home.id, foundZone.id]}) || {};
457
+
458
+ let minTempValue = capabilities.temperatures
459
+ ? homeInfo.temperatureUnit === 'CELSIUS'
460
+ ? capabilities.temperatures.celsius.min
461
+ : capabilities.temperatures.fahrenheit.min
462
+ : foundZone.type === 'HOT_WATER'
463
+ ? homeInfo.temperatureUnit === 'CELSIUS'
464
+ ? 30
465
+ : 86
466
+ : homeInfo.temperatureUnit === 'CELSIUS'
467
+ ? 5
468
+ : 41;
469
+
470
+ let maxTempValue = capabilities.temperatures
471
+ ? homeInfo.temperatureUnit === 'CELSIUS'
472
+ ? capabilities.temperatures.celsius.max
473
+ : capabilities.temperatures.fahrenheit.max
474
+ : foundZone.type === 'HOT_WATER'
475
+ ? homeInfo.temperatureUnit === 'CELSIUS'
476
+ ? 65
477
+ : 149
478
+ : homeInfo.temperatureUnit === 'CELSIUS'
479
+ ? 27
480
+ : 77;
481
+
482
+ let minTempStep = capabilities.temperatures
483
+ ? homeInfo.temperatureUnit === 'CELSIUS'
484
+ ? capabilities.temperatures.celsius.step
485
+ : capabilities.temperatures.fahrenheit.step
486
+ : 1;
487
+
488
+ if(foundZone.devices)
489
+ foundZone.devices.forEach(dev => {
490
+ if(dev.deviceType && (dev.deviceType.includes('VA01') || dev.deviceType.includes('VA02')))
491
+ allFoundDevices.push({
492
+ name: foundZone.name + ' ' + dev.shortSerialNo,
493
+ serialNumber: dev.shortSerialNo
494
+ });
495
+ });
496
+
497
+ let zoneIndex;
498
+ config[0].homes[i].zones.forEach((zone, index) => {
499
+ if(zone.name === foundZone.name){
500
+ zoneIndex = index;
501
+ }
502
+ });
503
+ if(zoneIndex !== undefined){
504
+ config[0].homes[i].zones[zoneIndex].id = foundZone.id;
505
+ config[0].homes[i].zones[zoneIndex].type = foundZone.type;
506
+ config[0].homes[i].zones[zoneIndex].minValue = minTempValue;
507
+ config[0].homes[i].zones[zoneIndex].maxValue = maxTempValue;
508
+ config[0].homes[i].zones[zoneIndex].minStep = minTempStep;
509
+ } else {
510
+ config[0].homes[i].zones.push({
511
+ active: true,
512
+ id: foundZone.id,
513
+ name: foundZone.name,
514
+ type: foundZone.type,
515
+ delaySwitch: false,
516
+ autoOffDelay: false,
517
+ noBattery: false,
518
+ mode: 'MANUAL',
519
+ modeTimer: 30,
520
+ minValue: minTempValue,
521
+ maxValue: maxTempValue,
522
+ minStep: minTempStep,
523
+ easyMode: false,
524
+ openWindowSensor: false,
525
+ openWindowSwitch: false,
526
+ airQuality: false,
527
+ separateTemperature: false,
528
+ separateHumidity: false,
529
+ accTypeBoiler: 'SWITCH',
530
+ boilerTempSupport: false
531
+ });
532
+ }
533
+ }
534
+ } else {
535
+
536
+ for(const zone of zones){
537
+
538
+ const capabilities = await homebridge.request('/exec', {dest: 'getZoneCapabilities', data: [home.id, zone.id]}) || {};
539
+
540
+ let minTempValue = capabilities.temperatures
541
+ ? homeInfo.temperatureUnit === 'CELSIUS'
542
+ ? capabilities.temperatures.celsius.min
543
+ : capabilities.temperatures.fahrenheit.min
544
+ : zone.type === 'HOT_WATER'
545
+ ? homeInfo.temperatureUnit === 'CELSIUS'
546
+ ? 30
547
+ : 86
548
+ : homeInfo.temperatureUnit === 'CELSIUS'
549
+ ? 5
550
+ : 41;
551
+
552
+ let maxTempValue = capabilities.temperatures
553
+ ? homeInfo.temperatureUnit === 'CELSIUS'
554
+ ? capabilities.temperatures.celsius.max
555
+ : capabilities.temperatures.fahrenheit.max
556
+ : zone.type === 'HOT_WATER'
557
+ ? homeInfo.temperatureUnit === 'CELSIUS'
558
+ ? 65
559
+ : 149
560
+ : homeInfo.temperatureUnit === 'CELSIUS'
561
+ ? 27
562
+ : 77;
563
+
564
+ let minTempStep = capabilities.temperatures
565
+ ? homeInfo.temperatureUnit === 'CELSIUS'
566
+ ? capabilities.temperatures.celsius.step
567
+ : capabilities.temperatures.fahrenheit.step
568
+ : 1;
569
+
570
+ if(zone.devices)
571
+ zone.devices.forEach(dev => {
572
+ allFoundDevices.push({
573
+ name: zone.name + ' ' + dev.shortSerialNo,
574
+ serialNumber: dev.shortSerialNo
575
+ });
576
+ });
577
+
578
+ config[0].homes[i].zones.push({
579
+ active: true,
580
+ id: zone.id,
581
+ name: zone.name,
582
+ type: zone.type,
583
+ delaySwitch: false,
584
+ autoOffDelay: false,
585
+ noBattery: false,
586
+ mode: 'MANUAL',
587
+ modeTimer: 30,
588
+ minValue: minTempValue,
589
+ maxValue: maxTempValue,
590
+ minStep: minTempStep,
591
+ easyMode: false,
592
+ openWindowSensor: false,
593
+ openWindowSwitch: false,
594
+ airQuality: false,
595
+ separateTemperature: false,
596
+ separateHumidity: false,
597
+ accTypeBoiler: 'SWITCH',
598
+ boilerTempSupport: false
599
+ });
600
+
601
+ }
602
+ }
603
+
604
+ //remove non existing childLockSwitches
605
+ config[0].homes[i].extras.childLockSwitches.forEach((childLockSwitch, index) => {
606
+ let found = false;
607
+ allFoundDevices.forEach(foundDevice => {
608
+ if(foundDevice.serialNumber === childLockSwitch.serialNumber){
609
+ found = true;
610
+ }
611
+ });
612
+ if(!found){
613
+ homebridge.toast.info(childLockSwitch.name + ' removed from config!', credentials.username);
614
+ config[0].homes[i].extras.childLockSwitches.splice(index, 1);
615
+ }
616
+ });
617
+
618
+ //check for new childLockSwitches
619
+ if(config[0].homes[i].extras.childLockSwitches.length){
620
+ for(const foundDevice of allFoundDevices){
621
+ let found = false;
622
+ config[0].homes[i].extras.childLockSwitches.forEach(childLockSwitch => {
623
+ if(childLockSwitch.serialNumber === foundDevice.serialNumber){
624
+ found = true;
625
+ }
626
+ });
627
+ if(!found){
628
+ config[0].homes[i].extras.childLockSwitches.push({
629
+ active: false,
630
+ name: foundDevice.name,
631
+ serialNumber: foundDevice.serialNumber
632
+ });
633
+ }
634
+ }
635
+ } else {
636
+ config[0].homes[i].extras.childLockSwitches = allFoundDevices.map(device => {
637
+ return {
638
+ active: false,
639
+ name: device.name,
640
+ serialNumber: device.serialNumber
641
+ };
642
+ });
643
+ }
644
+
645
+ }
646
+
647
+ }
648
+
649
+ } else if(resync){
650
+
651
+ homebridge.toast.info('Checking for available homes for given user...', 'Info');
652
+
653
+ const availableHomesInApis = [];
654
+
655
+ for(let home of config[0].homes){
656
+
657
+ if(home.name && home.username && home.password){
658
+
659
+ //Init API with credentials
660
+ homebridge.request('/authenticate', {username: home.username, password: home.password});
661
+
662
+ //resync home (refresh/remove)
663
+ const me = await homebridge.request('/exec', {dest: 'getMe'});
664
+
665
+ me.homes.forEach(foundHome => {
666
+ availableHomesInApis.push({
667
+ id: foundHome.id,
668
+ name: foundHome.name,
669
+ username: home.username,
670
+ password: home.password
671
+ });
672
+ });
673
+
674
+ }
675
+
676
+ }
677
+
678
+ await TIMEOUT(2000);
679
+
680
+ homebridge.toast.info('Found ' + availableHomesInApis.length + ' in total!', 'Info');
681
+
682
+ await TIMEOUT(2000);
683
+
684
+ homebridge.toast.info('Search for homes in the config to remove that were not found in the api...', 'Info');
685
+
686
+ let removedHomes = 0;
687
+
688
+ //remove non exist homes from config that doesnt exist in api
689
+ for(let [i, home] of config[0].homes.entries()){
690
+
691
+ if(home.name && home.username && home.password){
692
+
693
+ //Init API with credentials
694
+ homebridge.request('/authenticate', {username: home.username, password: home.password});
695
+
696
+ let foundHome;
697
+
698
+ for(const apiHome of availableHomesInApis){
699
+ if(home.name === apiHome.name || home.id === apiHome.id){
700
+ foundHome = apiHome;
701
+ }
702
+ }
703
+
704
+ if(!foundHome){
705
+
706
+ homebridge.toast.info(home.name + ' removed from config!', home.username);
707
+
708
+ await removeDeviceFromConfig(home.name);
709
+ config[0].homes.splice(i, 1);
710
+
711
+ removedHomes += 1;
712
+
713
+ await TIMEOUT(2000);
714
+
715
+ }
716
+
717
+ }
718
+
719
+ }
720
+
721
+ if(!removedHomes)
722
+ await TIMEOUT(2000);
723
+
724
+ homebridge.toast.info(removedHomes + ' removed from config in total!', 'Info');
725
+
726
+ await TIMEOUT(2000);
727
+
728
+ //refresh existing homes
729
+ for(let [i, home] of config[0].homes.entries()){
730
+
731
+ if(home.name && home.username && home.password){
732
+
733
+ //Init API with credentials
734
+ homebridge.request('/authenticate', {username: home.username, password: home.password});
735
+
736
+ let foundHome;
737
+
738
+ for(const apiHome of availableHomesInApis){
739
+ if(home.name === apiHome.name || home.id === apiHome.id){
740
+ foundHome = apiHome;
741
+ home.id = apiHome.id;
742
+ }
743
+ }
744
+
745
+ if(foundHome){
746
+
747
+ homebridge.toast.info(home.name + ' resynchronizing...', home.username);
748
+
749
+ const homeInfo = await homebridge.request('/exec', {dest: 'getHome', data: home.id});
750
+
751
+ config[0].homes[i].id = homeInfo.id;
752
+ config[0].homes[i].username = foundHome.username;
753
+ config[0].homes[i].password = foundHome.password;
754
+ config[0].homes[i].temperatureUnit = homeInfo.temperatureUnit || 'CELSIUS';
755
+ config[0].homes[i].zones = config[0].homes[i].zones || [];
756
+
757
+ if(homeInfo.geolocation)
758
+ config[0].homes[i].geolocation = {
759
+ longitude: homeInfo.geolocation.longitude.toString(),
760
+ latitude: homeInfo.geolocation.latitude.toString()
761
+ };
762
+
763
+ //init devices for childLock
764
+ config[0].homes[i].extras = config[0].homes[i].extras || {};
765
+ config[0].homes[i].extras.childLockSwitches = config[0].homes[i].extras.childLockSwitches || [];
766
+
767
+ let allFoundDevices = [];
768
+
769
+ //Mobile Devices Informations
770
+ const mobileDevices = await homebridge.request('/exec', {dest: 'getMobileDevices', data: home.id});
771
+
772
+ if(!config[0].homes[i].presence)
773
+ config[0].homes[i].presence = {
774
+ anyone: false,
775
+ accTypeAnyone: 'OCCUPANCY',
776
+ user: []
777
+ };
778
+
779
+ //Remove not registred devices
780
+ config[0].homes[i].presence.user.forEach((user, index) => {
781
+ let found = false;
782
+ mobileDevices.forEach(foundUser => {
783
+ if(foundUser.name === user.name){
784
+ found = true;
785
+ }
786
+ });
787
+ if(!found){
788
+ homebridge.toast.info(user.name + ' removed from config!', home.username);
789
+ config[0].homes[i].presence.user.splice(index, 1);
790
+ }
791
+ });
792
+
793
+ //Check for new registred devices
794
+ if(config[0].homes[i].presence.user.length){
795
+ for(const foundUser of mobileDevices){
796
+ let userIndex;
797
+ config[0].homes[i].presence.user.forEach((user, index) => {
798
+ if(user.name === foundUser.name){
799
+ userIndex = index;
800
+ }
801
+ });
802
+ if(userIndex === undefined){
803
+ config[0].homes[i].presence.user.push({
804
+ active: false,
805
+ name: foundUser.name,
806
+ accType: 'OCCUPANCY'
807
+ });
808
+ }
809
+ }
810
+ } else {
811
+ config[0].homes[i].presence.user = mobileDevices.map(user => {
812
+ return {
813
+ active: false,
814
+ name: user.name,
815
+ accType: 'OCCUPANCY'
816
+ };
817
+ });
818
+ }
819
+
820
+ //Zone Informations
821
+ const zones = await homebridge.request('/exec', {dest: 'getZones', data: home.id});
822
+
823
+ //Remove not available zones
824
+ config[0].homes[i].zones.forEach((zone, index) => {
825
+ let found = false;
826
+ zones.forEach(foundZone => {
827
+ if(foundZone.name === zone.name){
828
+ found = true;
829
+ }
830
+ });
831
+ if(!found){
832
+ homebridge.toast.info(zone.name + ' removed from config!', home.username);
833
+ config[0].homes[i].zones.splice(index, 1);
834
+ }
835
+ });
836
+
837
+ //Check for new zones or refresh exist one
838
+ if(config[0].homes[i].zones.length){
839
+ for(const foundZone of zones){
840
+
841
+ const capabilities = await homebridge.request('/exec', {dest: 'getZoneCapabilities', data: [home.id, foundZone.id]}) || {};
842
+
843
+ let minTempValue = capabilities.temperatures
844
+ ? homeInfo.temperatureUnit === 'CELSIUS'
845
+ ? capabilities.temperatures.celsius.min
846
+ : capabilities.temperatures.fahrenheit.min
847
+ : foundZone.type === 'HOT_WATER'
848
+ ? homeInfo.temperatureUnit === 'CELSIUS'
849
+ ? 30
850
+ : 86
851
+ : homeInfo.temperatureUnit === 'CELSIUS'
852
+ ? 5
853
+ : 41;
854
+
855
+ let maxTempValue = capabilities.temperatures
856
+ ? homeInfo.temperatureUnit === 'CELSIUS'
857
+ ? capabilities.temperatures.celsius.max
858
+ : capabilities.temperatures.fahrenheit.max
859
+ : foundZone.type === 'HOT_WATER'
860
+ ? homeInfo.temperatureUnit === 'CELSIUS'
861
+ ? 65
862
+ : 149
863
+ : homeInfo.temperatureUnit === 'CELSIUS'
864
+ ? 27
865
+ : 77;
866
+
867
+ let minTempStep = capabilities.temperatures
868
+ ? homeInfo.temperatureUnit === 'CELSIUS'
869
+ ? capabilities.temperatures.celsius.step
870
+ : capabilities.temperatures.fahrenheit.step
871
+ : 1;
872
+
873
+ if(foundZone.devices)
874
+ foundZone.devices.forEach(dev => {
875
+ if(dev.deviceType && (dev.deviceType.includes('VA01') || dev.deviceType.includes('VA02')))
876
+ allFoundDevices.push({
877
+ name: foundZone.name + ' ' + dev.shortSerialNo,
878
+ serialNumber: dev.shortSerialNo
879
+ });
880
+ });
881
+
882
+ let zoneIndex;
883
+ config[0].homes[i].zones.forEach((zone, index) => {
884
+ if(zone.name === foundZone.name){
885
+ zoneIndex = index;
886
+ }
887
+ });
888
+ if(zoneIndex !== undefined){
889
+ config[0].homes[i].zones[zoneIndex].id = foundZone.id;
890
+ config[0].homes[i].zones[zoneIndex].type = foundZone.type;
891
+ config[0].homes[i].zones[zoneIndex].minValue = minTempValue;
892
+ config[0].homes[i].zones[zoneIndex].maxValue = maxTempValue;
893
+ config[0].homes[i].zones[zoneIndex].minStep = minTempStep;
894
+ } else {
895
+ config[0].homes[i].zones.push({
896
+ active: true,
897
+ id: foundZone.id,
898
+ name: foundZone.name,
899
+ type: foundZone.type,
900
+ delaySwitch: false,
901
+ autoOffDelay: false,
902
+ noBattery: false,
903
+ mode: 'MANUAL',
904
+ modeTimer: 30,
905
+ minValue: minTempValue,
906
+ maxValue: maxTempValue,
907
+ minStep: minTempStep,
908
+ easyMode: false,
909
+ openWindowSensor: false,
910
+ openWindowSwitch: false,
911
+ airQuality: false,
912
+ separateTemperature: false,
913
+ separateHumidity: false,
914
+ accTypeBoiler: 'SWITCH',
915
+ boilerTempSupport: false
916
+ });
917
+ }
918
+ }
919
+ } else {
920
+
921
+ for(const zone of zones){
922
+
923
+ const capabilities = await homebridge.request('/exec', {dest: 'getZoneCapabilities', data: [home.id, zone.id]}) || {};
924
+
925
+ let minTempValue = capabilities.temperatures
926
+ ? homeInfo.temperatureUnit === 'CELSIUS'
927
+ ? capabilities.temperatures.celsius.min
928
+ : capabilities.temperatures.fahrenheit.min
929
+ : zone.type === 'HOT_WATER'
930
+ ? homeInfo.temperatureUnit === 'CELSIUS'
931
+ ? 30
932
+ : 86
933
+ : homeInfo.temperatureUnit === 'CELSIUS'
934
+ ? 5
935
+ : 41;
936
+
937
+ let maxTempValue = capabilities.temperatures
938
+ ? homeInfo.temperatureUnit === 'CELSIUS'
939
+ ? capabilities.temperatures.celsius.max
940
+ : capabilities.temperatures.fahrenheit.max
941
+ : zone.type === 'HOT_WATER'
942
+ ? homeInfo.temperatureUnit === 'CELSIUS'
943
+ ? 65
944
+ : 149
945
+ : homeInfo.temperatureUnit === 'CELSIUS'
946
+ ? 27
947
+ : 77;
948
+
949
+ let minTempStep = capabilities.temperatures
950
+ ? homeInfo.temperatureUnit === 'CELSIUS'
951
+ ? capabilities.temperatures.celsius.step
952
+ : capabilities.temperatures.fahrenheit.step
953
+ : 1;
954
+
955
+ if(zone.devices)
956
+ zone.devices.forEach(dev => {
957
+ if(dev.deviceType && (dev.deviceType.includes('VA01') || dev.deviceType.includes('VA02')))
958
+ allFoundDevices.push({
959
+ name: zone.name + ' ' + dev.shortSerialNo,
960
+ serialNumber: dev.shortSerialNo
961
+ });
962
+ });
963
+
964
+ config[0].homes[i].zones.push({
965
+ active: true,
966
+ id: zone.id,
967
+ name: zone.name,
968
+ type: zone.type,
969
+ delaySwitch: false,
970
+ autoOffDelay: false,
971
+ noBattery: false,
972
+ mode: 'MANUAL',
973
+ modeTimer: 30,
974
+ minValue: minTempValue,
975
+ maxValue: maxTempValue,
976
+ minStep: minTempStep,
977
+ easyMode: false,
978
+ openWindowSensor: false,
979
+ openWindowSwitch: false,
980
+ airQuality: false,
981
+ separateTemperature: false,
982
+ separateHumidity: false,
983
+ accTypeBoiler: 'SWITCH',
984
+ boilerTempSupport: false
985
+ });
986
+
987
+ }
988
+ }
989
+
990
+ //remove non existing childLockSwitches
991
+ config[0].homes[i].extras.childLockSwitches.forEach((childLockSwitch, index) => {
992
+ let found = false;
993
+ allFoundDevices.forEach(foundDevice => {
994
+ if(foundDevice.serialNumber === childLockSwitch.serialNumber){
995
+ found = true;
996
+ }
997
+ });
998
+ if(!found){
999
+ homebridge.toast.info(childLockSwitch.serialNumber + ' removed from config!', home.username);
1000
+ config[0].homes[i].extras.childLockSwitches.splice(index, 1);
1001
+ }
1002
+ });
1003
+
1004
+ //check for new childLockSwitches
1005
+ if(config[0].homes[i].extras.childLockSwitches.length){
1006
+ for(const foundDevice of allFoundDevices){
1007
+ let found = false;
1008
+ config[0].homes[i].extras.childLockSwitches.forEach(childLockSwitch => {
1009
+ if(childLockSwitch.serialNumber === foundDevice.serialNumber){
1010
+ found = true;
1011
+ }
1012
+ });
1013
+ if(!found){
1014
+ config[0].homes[i].extras.childLockSwitches.push({
1015
+ active: false,
1016
+ name: foundDevice.name,
1017
+ serialNumber: foundDevice.serialNumber
1018
+ });
1019
+ }
1020
+ }
1021
+ } else {
1022
+ config[0].homes[i].extras.childLockSwitches = allFoundDevices.map(device => {
1023
+ return {
1024
+ active: false,
1025
+ name: device.name,
1026
+ serialNumber: device.serialNumber
1027
+ };
1028
+ });
1029
+ }
1030
+
1031
+ await TIMEOUT(2000);
1032
+
1033
+ homebridge.toast.info(home.name + ' resynchronized!', home.username);
1034
+
1035
+ await TIMEOUT(2000);
1036
+
1037
+
1038
+ }
1039
+
1040
+ }
1041
+
1042
+ }
1043
+
1044
+ homebridge.toast.info('Looking for homes which are found in the api but are not configured...', 'Info');
1045
+
1046
+ await TIMEOUT(2000);
1047
+
1048
+ let addedHomes = 0;
1049
+
1050
+ //add new homes from api that doesnt exist in config
1051
+ for(const foundHome of availableHomesInApis){
1052
+
1053
+ let found = false;
1054
+
1055
+ config[0].homes.forEach(home => {
1056
+ if(home.name === foundHome.name || home.id === foundHome.id)
1057
+ found = true;
1058
+ });
1059
+
1060
+ if(!found){
1061
+
1062
+ homebridge.toast.info('Found ' + foundHome.name, foundHome.username);
1063
+
1064
+ addedHomes += 1;
1065
+
1066
+ //Init API with credentials
1067
+ homebridge.request('/authenticate', {username: foundHome.username, password: foundHome.password});
1068
+
1069
+ const homeConfig = {
1070
+ id: foundHome.id,
1071
+ name: foundHome.name,
1072
+ username: foundHome.username,
1073
+ password: foundHome.password,
1074
+ polling: 30,
1075
+ zones: [],
1076
+ presence: {
1077
+ anyone: false,
1078
+ accTypeAnyone: 'OCCUPANCY',
1079
+ user: []
1080
+ },
1081
+ weather: {
1082
+ temperatureSensor: false,
1083
+ solarIntensity: false,
1084
+ accTypeSolarIntensity: 'LIGHTBULB',
1085
+ airQuality: false
1086
+ },
1087
+ extras: {
1088
+ centralSwitch: false,
1089
+ runningInformation: false,
1090
+ boostSwitch: false,
1091
+ sheduleSwitch: false,
1092
+ turnoffSwitch: false,
1093
+ presenceLock: false,
1094
+ accTypePresenceLock: 'ALARM',
1095
+ childLockSwitches: []
1096
+ },
1097
+ telegram: {
1098
+ active: false
1099
+ }
1100
+ };
1101
+
1102
+ //Home Informations
1103
+ const homeInfo = await homebridge.request('/exec', {dest: 'getHome', data: foundHome.id});
1104
+
1105
+ homeConfig.temperatureUnit = homeInfo.temperatureUnit;
1106
+ homeConfig.geolocation = {
1107
+ longitude: homeInfo.geolocation.longitude.toString(),
1108
+ latitude: homeInfo.geolocation.latitude.toString()
1109
+ };
1110
+
1111
+ //Mobile Devices Informations
1112
+ const mobileDevices = await homebridge.request('/exec', {dest: 'getMobileDevices', data: foundHome.id});
1113
+
1114
+ homeConfig.presence.user = mobileDevices.map(user => {
1115
+ return {
1116
+ active: false,
1117
+ name: user.name,
1118
+ accType: 'OCCUPANCY'
1119
+ };
1120
+ });
1121
+
1122
+ //Zone Informations
1123
+ const zones = await homebridge.request('/exec', {dest: 'getZones', data: foundHome.id});
1124
+
1125
+ for(const zone of zones){
1126
+
1127
+ const capabilities = await homebridge.request('/exec', {dest: 'getZoneCapabilities', data: [homeInfo.id, zone.id]}) || {};
1128
+
1129
+ let minTempValue = capabilities.temperatures
1130
+ ? homeInfo.temperatureUnit === 'CELSIUS'
1131
+ ? capabilities.temperatures.celsius.min
1132
+ : capabilities.temperatures.fahrenheit.min
1133
+ : zone.type === 'HOT_WATER'
1134
+ ? homeInfo.temperatureUnit === 'CELSIUS'
1135
+ ? 30
1136
+ : 86
1137
+ : homeInfo.temperatureUnit === 'CELSIUS'
1138
+ ? 5
1139
+ : 41;
1140
+
1141
+ let maxTempValue = capabilities.temperatures
1142
+ ? homeInfo.temperatureUnit === 'CELSIUS'
1143
+ ? capabilities.temperatures.celsius.max
1144
+ : capabilities.temperatures.fahrenheit.max
1145
+ : zone.type === 'HOT_WATER'
1146
+ ? homeInfo.temperatureUnit === 'CELSIUS'
1147
+ ? 65
1148
+ : 149
1149
+ : homeInfo.temperatureUnit === 'CELSIUS'
1150
+ ? 27
1151
+ : 77;
1152
+
1153
+ let minTempStep = capabilities.temperatures
1154
+ ? homeInfo.temperatureUnit === 'CELSIUS'
1155
+ ? capabilities.temperatures.celsius.step
1156
+ : capabilities.temperatures.fahrenheit.step
1157
+ : 1;
1158
+
1159
+ if(zone.devices)
1160
+ zone.devices.forEach(device => {
1161
+ if(device.deviceType && (device.deviceType.includes('VA01') || device.deviceType.includes('VA02')))
1162
+ homeConfig.extras.childLockSwitches.push({
1163
+ active: false,
1164
+ name: zone.name + ' ' + device.shortSerialNo,
1165
+ serialNumber: device.shortSerialNo
1166
+ });
1167
+ });
1168
+
1169
+ homeConfig.zones.push({
1170
+ active: true,
1171
+ id: zone.id,
1172
+ name: zone.name,
1173
+ type: zone.type,
1174
+ delaySwitch: false,
1175
+ autoOffDelay: false,
1176
+ noBattery: false,
1177
+ mode: 'MANUAL',
1178
+ modeTimer: 30,
1179
+ minValue: minTempValue,
1180
+ maxValue: maxTempValue,
1181
+ minStep: minTempStep,
1182
+ easyMode: false,
1183
+ openWindowSensor: false,
1184
+ openWindowSwitch: false,
1185
+ airQuality: false,
1186
+ separateTemperature: false,
1187
+ separateHumidity: false,
1188
+ accTypeBoiler: 'SWITCH',
1189
+ boilerTempSupport: false
1190
+ });
1191
+
1192
+ }
1193
+
1194
+ config[0].homes.push(homeConfig);
1195
+
1196
+ await TIMEOUT(2000);
1197
+
1198
+ homebridge.toast.info(foundHome.name + ' added to config.json!', foundHome.username);
1199
+
1200
+ await TIMEOUT(2000);
1201
+
1202
+ }
1203
+
1204
+ }
1205
+
1206
+ if(!addedHomes)
1207
+ await TIMEOUT(2000);
1208
+
1209
+ homebridge.toast.info(removedHomes + ' new homes configured!', 'Info');
1210
+
1211
+ } else {
1212
+
1213
+ //add new account/home
1214
+
1215
+ const me = await homebridge.request('/exec', {dest: 'getMe'});
1216
+
1217
+ for(const foundHome of me.homes){
1218
+
1219
+ let homeIndex;
1220
+ config[0].homes.forEach((home, index) => {
1221
+ if(home.name === foundHome.name || home.id === foundHome.id){
1222
+ homeIndex = index;
1223
+ }
1224
+ });
1225
+
1226
+ if(homeIndex === undefined){
1227
+
1228
+ const homeConfig = {
1229
+ id: foundHome.id,
1230
+ name: foundHome.name,
1231
+ username: credentials.username,
1232
+ password: credentials.password,
1233
+ polling: 30,
1234
+ zones: [],
1235
+ presence: {
1236
+ anyone: false,
1237
+ accTypeAnyone: 'OCCUPANCY',
1238
+ user: []
1239
+ },
1240
+ weather: {
1241
+ temperatureSensor: false,
1242
+ solarIntensity: false,
1243
+ accTypeSolarIntensity: 'LIGHTBULB',
1244
+ airQuality: false
1245
+ },
1246
+ extras: {
1247
+ centralSwitch: false,
1248
+ runningInformation: false,
1249
+ boostSwitch: false,
1250
+ sheduleSwitch: false,
1251
+ turnoffSwitch: false,
1252
+ presenceLock: false,
1253
+ accTypePresenceLock: 'ALARM',
1254
+ childLockSwitches: []
1255
+ },
1256
+ telegram: {
1257
+ active: false
1258
+ }
1259
+ };
1260
+
1261
+ await TIMEOUT(2000);
1262
+
1263
+ fetchDevicesBar.animate(0.40);
1264
+
1265
+ //Home Informations
1266
+ const homeInfo = await homebridge.request('/exec', {dest: 'getHome', data: foundHome.id});
1267
+
1268
+ homeConfig.temperatureUnit = homeInfo.temperatureUnit;
1269
+ homeConfig.geolocation = {
1270
+ longitude: homeInfo.geolocation.longitude.toString(),
1271
+ latitude: homeInfo.geolocation.latitude.toString()
1272
+ };
1273
+
1274
+ await TIMEOUT(2000);
1275
+
1276
+ fetchDevicesBar.animate(0.60);
1277
+
1278
+ //Mobile Devices Informations
1279
+ const mobileDevices = await homebridge.request('/exec', {dest: 'getMobileDevices', data: foundHome.id});
1280
+
1281
+ homeConfig.presence.user = mobileDevices.map(user => {
1282
+ return {
1283
+ active: false,
1284
+ name: user.name,
1285
+ accType: 'OCCUPANCY'
1286
+ };
1287
+ });
1288
+
1289
+ await TIMEOUT(2000);
1290
+
1291
+ fetchDevicesBar.animate(0.80);
1292
+
1293
+ //Zone Informations
1294
+ const zones = await homebridge.request('/exec', {dest: 'getZones', data: foundHome.id});
1295
+
1296
+ for(const zone of zones){
1297
+
1298
+ const capabilities = await homebridge.request('/exec', {dest: 'getZoneCapabilities', data: [homeInfo.id, zone.id]}) || {};
1299
+
1300
+ let minTempValue = capabilities.temperatures
1301
+ ? homeInfo.temperatureUnit === 'CELSIUS'
1302
+ ? capabilities.temperatures.celsius.min
1303
+ : capabilities.temperatures.fahrenheit.min
1304
+ : zone.type === 'HOT_WATER'
1305
+ ? homeInfo.temperatureUnit === 'CELSIUS'
1306
+ ? 30
1307
+ : 86
1308
+ : homeInfo.temperatureUnit === 'CELSIUS'
1309
+ ? 5
1310
+ : 41;
1311
+
1312
+ let maxTempValue = capabilities.temperatures
1313
+ ? homeInfo.temperatureUnit === 'CELSIUS'
1314
+ ? capabilities.temperatures.celsius.max
1315
+ : capabilities.temperatures.fahrenheit.max
1316
+ : zone.type === 'HOT_WATER'
1317
+ ? homeInfo.temperatureUnit === 'CELSIUS'
1318
+ ? 65
1319
+ : 149
1320
+ : homeInfo.temperatureUnit === 'CELSIUS'
1321
+ ? 27
1322
+ : 77;
1323
+
1324
+ let minTempStep = capabilities.temperatures
1325
+ ? homeInfo.temperatureUnit === 'CELSIUS'
1326
+ ? capabilities.temperatures.celsius.step
1327
+ : capabilities.temperatures.fahrenheit.step
1328
+ : 1;
1329
+
1330
+ if(zone.devices)
1331
+ zone.devices.forEach(device => {
1332
+ if(device.deviceType && (device.deviceType.includes('VA01') || device.deviceType.includes('VA02')))
1333
+ homeConfig.extras.childLockSwitches.push({
1334
+ active: false,
1335
+ name: zone.name + ' ' + device.shortSerialNo,
1336
+ serialNumber: device.shortSerialNo
1337
+ });
1338
+ });
1339
+
1340
+ homeConfig.zones.push({
1341
+ active: true,
1342
+ id: zone.id,
1343
+ name: zone.name,
1344
+ type: zone.type,
1345
+ delaySwitch: false,
1346
+ autoOffDelay: false,
1347
+ noBattery: false,
1348
+ mode: 'MANUAL',
1349
+ modeTimer: 30,
1350
+ minValue: minTempValue,
1351
+ maxValue: maxTempValue,
1352
+ minStep: minTempStep,
1353
+ easyMode: false,
1354
+ openWindowSensor: false,
1355
+ openWindowSwitch: false,
1356
+ airQuality: false,
1357
+ separateTemperature: false,
1358
+ separateHumidity: false,
1359
+ accTypeBoiler: 'SWITCH',
1360
+ boilerTempSupport: false
1361
+ });
1362
+
1363
+ }
1364
+
1365
+
1366
+ config[0].homes.push(homeConfig);
1367
+
1368
+ }
1369
+
1370
+ }
1371
+
1372
+ }
1373
+
1374
+ await TIMEOUT(2000);
1375
+
1376
+ fetchDevicesBar.animate(1.00);
1377
+
1378
+ if(resync)
1379
+ homebridge.toast.info('Resynchronized!', credentials.username);
1380
+
1381
+ await TIMEOUT(2000);
1382
+
1383
+ return config;
1384
+
1385
+ } catch(err) {
1386
+
1387
+ fetchDevicesBar.set(0);
1388
+ fetchDevicesBar.setText('Error!');
1389
+
1390
+ console.log(err);
1391
+ homebridge.toast.error(err.message, 'Error');
1392
+
1393
+ await TIMEOUT(2000);
1394
+ return false;
1395
+
1396
+ }
1397
+
1398
+ }
1399
+
1400
+ (async () => {
1401
+
1402
+ try {
1403
+
1404
+ //check version before load ui
1405
+ if(window.compareVersions(window.homebridge.serverEnv.env.packageVersion, '4.34.0') < 0){
1406
+ await showOldSchema(true);
1407
+ return;
1408
+ }
1409
+
1410
+ pluginConfig = await homebridge.getPluginConfig();
1411
+
1412
+ if(!pluginConfig.length){
1413
+
1414
+ pluginConfig = [{
1415
+ platform: 'TadoPlatform',
1416
+ name: 'TadoPlatform',
1417
+ homes: []
1418
+ }];
1419
+
1420
+ transPage(false, $('#notConfigured'));
1421
+
1422
+ } else {
1423
+
1424
+ if(!pluginConfig[0].homes || (pluginConfig[0].homes && !pluginConfig[0].homes.length)){
1425
+ pluginConfig[0].homes = [];
1426
+ return transPage(false, $('#notConfigured'));
1427
+ }
1428
+
1429
+ pluginConfig[0].homes.forEach(home => {
1430
+ $('#deviceSelect').append('<option value="' + home.name + '">'+ home.name + ' &lt;' + home.username + '&gt;</option>');
1431
+ });
1432
+
1433
+ transPage(false, $('#isConfigured'));
1434
+
1435
+ }
1436
+
1437
+ } catch(err) {
1438
+
1439
+ console.log(err);
1440
+ homebridge.toast.error(err.message, 'Error');
1441
+
1442
+ }
1443
+
1444
+ })();
1445
+
1446
+ //jquery listener
1447
+
1448
+ $('.back').on('click', () => {
1449
+ goBack();
1450
+ });
1451
+
1452
+ $('.oldConfig').on('click', async () => {
1453
+ await showOldSchema(false);
1454
+ });
1455
+
1456
+ $('#start, #addDevice').on('click', () => {
1457
+
1458
+ resetUI();
1459
+
1460
+ let activeContent = $('#notConfigured').css('display') !== 'none' ? $('#notConfigured') : $('#isConfigured');
1461
+
1462
+ transPage(activeContent, $('#configureDevice'));
1463
+
1464
+ });
1465
+
1466
+ $('#reSync').on('click', async () => {
1467
+
1468
+ try {
1469
+
1470
+ homebridge.showSpinner();
1471
+
1472
+ const config = await fetchDevices(false, false, true);
1473
+
1474
+ if(config){
1475
+ await addNewDeviceToConfig(config, false, true);
1476
+ resetUI();
1477
+ }
1478
+
1479
+ homebridge.hideSpinner();
1480
+
1481
+ } catch(err) {
1482
+
1483
+ homebridge.hideSpinner();
1484
+
1485
+ console.log(err);
1486
+ homebridge.toast.error(err.message, 'Error');
1487
+
1488
+ }
1489
+
1490
+ });
1491
+
1492
+ $('#auth').on('click', async () => {
1493
+
1494
+ try {
1495
+
1496
+ let credentials = {
1497
+ username: $('#homeUsername').val(),
1498
+ password: $('#homePassword').val()
1499
+ };
1500
+
1501
+ transPage($('#configureDevice'), $('#fetchDevices'));
1502
+
1503
+ const config = await fetchDevices(credentials, false, false);
1504
+
1505
+ if(config){
1506
+ await addNewDeviceToConfig(config, false, false);
1507
+ transPage($('#fetchDevices'), $('#isConfigured'));
1508
+ resetUI();
1509
+ }
1510
+
1511
+ } catch(err) {
1512
+
1513
+ console.log(err);
1514
+ homebridge.toast.error(err.message, 'Error');
1515
+
1516
+ }
1517
+
1518
+ });
1519
+
1520
+ $('#editDevice').on('click', () => {
1521
+
1522
+ resetUI();
1523
+
1524
+ currentHome = $( '#deviceSelect option:selected' ).val();
1525
+ let home = pluginConfig[0].homes.find(home => home.name === currentHome);
1526
+
1527
+ if(!home)
1528
+ return homebridge.toast.error('Can not find selected home!', 'Error');
1529
+
1530
+ createCustomSchema(home);
1531
+
1532
+ transPage($('#main, #isConfigured'), $('#header'), false, true);
1533
+
1534
+ });
1535
+
1536
+ $('#refreshDevice').on('click', async () => {
1537
+
1538
+ if(customSchemaActive && currentHome){
1539
+
1540
+ resetSchema();
1541
+
1542
+ let home = pluginConfig[0].homes.find(home => home.name === currentHome);
1543
+
1544
+ if(!home)
1545
+ return homebridge.toast.error('Can not find home in config!', 'Error');
1546
+
1547
+ transPage($('#isConfigured'), $('#fetchDevices'));
1548
+
1549
+ const config = await fetchDevices({ username: home.username, password: home.password }, true, false);
1550
+
1551
+ if(config){
1552
+ await addNewDeviceToConfig(config, true, false);
1553
+ transPage($('#fetchDevices'), $('#isConfigured'));
1554
+ resetUI();
1555
+ }
1556
+
1557
+ } else {
1558
+
1559
+ homebridge.toast.error('No home selected to refresh!', 'Error');
1560
+
1561
+ }
1562
+
1563
+ });
1564
+
1565
+ $('#removeDevice').on('click', async () => {
1566
+
1567
+ try {
1568
+
1569
+ await removeDeviceFromConfig();
1570
+
1571
+ resetUI();
1572
+
1573
+ transPage(false, pluginConfig[0].homes.length ? $('#isConfigured') : $('#notConfigured'));
1574
+
1575
+ } catch (err) {
1576
+
1577
+ console.log(err);
1578
+ homebridge.toast.error(err.message, 'Error');
1579
+
1580
+ }
1581
+
1582
+ });