@@ -45,6 +45,7 @@ class Tado extends utils.Adapter {
45
45
this . apiCallinExecution = false ;
46
46
JsonExplorer . init ( this , state_attr ) ;
47
47
this . intervall_time = 60 * 1000 ;
48
+ this . roomCapabilities = { } ;
48
49
}
49
50
50
51
/**
@@ -397,7 +398,6 @@ class Tado extends utils.Adapter {
397
398
*/
398
399
async setZoneOverlay ( home_id , zone_id , power , temperature , typeSkillBasedApp , durationInSeconds , type , acMode , fanLevel , horizontalSwing , verticalSwing , fanSpeed ) {
399
400
power = power . toUpperCase ( ) ;
400
- if ( ! temperature ) temperature = 20 ;
401
401
typeSkillBasedApp = typeSkillBasedApp . toUpperCase ( ) ;
402
402
durationInSeconds = Math . max ( 10 , durationInSeconds ) ;
403
403
type = type . toUpperCase ( ) ;
@@ -406,87 +406,15 @@ class Tado extends utils.Adapter {
406
406
fanLevel = fanLevel . toUpperCase ( ) ;
407
407
horizontalSwing = horizontalSwing . toUpperCase ( ) ;
408
408
verticalSwing = verticalSwing . toUpperCase ( ) ;
409
-
410
- if ( power != 'ON' && power != 'OFF' ) {
411
- this . log . error ( `Invalid value '${ power } ' for state 'power'. Allowed values are ON and OFF` ) ;
412
- return ;
413
- }
414
- if ( typeSkillBasedApp != 'TIMER' && typeSkillBasedApp != 'MANUAL' && typeSkillBasedApp != 'NEXT_TIME_BLOCK' && typeSkillBasedApp != 'NO_OVERLAY' ) {
415
- this . log . error ( `Invalid value '${ typeSkillBasedApp } ' for state 'typeSkillBasedApp'. Allowed values are TIMER, MANUAL and NEXT_TIME_BLOCK` ) ;
416
- return ;
417
- }
418
- if ( horizontalSwing != 'ON' && horizontalSwing != 'OFF' && horizontalSwing != 'NOT_AVAILABLE' ) {
419
- this . log . error ( `Invalid value '${ horizontalSwing } ' for state 'horizontalSwing'. Allowed values are ON and OFF` ) ;
420
- return ;
421
- }
422
- if ( verticalSwing != 'ON' && verticalSwing != 'OFF' && verticalSwing != 'NOT_AVAILABLE' ) {
423
- this . log . error ( `Invalid value '${ verticalSwing } ' for state 'verticalSwing'. Allowed values are ON and OFF` ) ;
424
- return ;
425
- }
426
- if ( type != 'HEATING' && type != 'AIR_CONDITIONING' && type != 'HOT_WATER' ) {
427
- this . log . error ( `Invalid value '${ type } ' for state 'type'. Allowed values are HOT_WATER, AIR_CONDITIONING and HEATING` ) ;
428
- return ;
429
- }
430
- if ( fanSpeed != 'AUTO' && fanSpeed != 'HIGH' && fanSpeed != 'MIDDLE' && fanSpeed != 'LOW' && fanSpeed != 'NOT_AVAILABLE' ) {
431
- this . log . error ( `Invalid value '${ fanSpeed } ' for state 'fanSpeed'. Allowed values are HIGH, MIDDLE, LOW and AUTO` ) ;
432
- return ;
433
- }
434
- if ( fanLevel != 'AUTO' && fanLevel != 'SILENT' && fanLevel != 'LEVEL1' && fanLevel != 'LEVEL2' && fanLevel != 'LEVEL3' && fanLevel != 'LEVEL4' && fanLevel != 'LEVEL5' && fanLevel != 'NOT_AVAILABLE' ) {
435
- this . log . error ( `Invalid value '${ fanLevel } ' for state 'fanLevel'. Allowed values are AUTO, SILENT, LEVEL1, LEVEL2, LEVEL3, LEVEL4 and LEVEL5` ) ;
436
- return ;
437
- }
438
- if ( acMode != 'AUTO' && acMode != 'COOL' && acMode != 'DRY' && acMode != 'FAN' && acMode != 'HEAT' && acMode != 'NOT_AVAILABLE' ) {
439
- this . log . error ( `Invalid value '${ acMode } ' for state 'acMode'. Allowed values are AUTO, COOL, DRY, FAN and HEAT` ) ;
440
- return ;
441
- }
442
-
443
- const config = {
409
+ if ( ! temperature ) temperature = 21 ;
410
+ let config = {
444
411
setting : {
445
412
type : type ,
446
413
}
447
414
} ;
448
415
449
416
try {
450
- if ( type == 'HEATING' ) {
451
- //Temp range is 5-25
452
- if ( temperature > 25 ) {
453
- this . log . info ( `Temperature set to 25° instead of ${ temperature } ° for HEATING device` ) ;
454
- temperature = 25 ;
455
- } else if ( temperature < 5 ) {
456
- this . log . info ( `Temperature set to 5° instead of ${ temperature } ° for HEATING device` ) ;
457
- temperature = 5 ;
458
- }
459
- }
460
- if ( type == 'AIR_CONDITIONING' ) {
461
- //Temp range is 16-30
462
- if ( temperature > 30 ) {
463
- this . log . info ( `Temperature set to 30° instead of ${ temperature } ° for AIR_CONDITIONING device` ) ;
464
- temperature = 30 ;
465
- } else if ( temperature < 16 ) {
466
- this . log . info ( `Temperature set to 16° instead of ${ temperature } ° for AIR_CONDITIONING device` ) ;
467
- temperature = 16 ;
468
- }
469
- //acMode is always needed if AIR_CONDITION
470
- if ( acMode != 'NOT_AVAILABLE' ) config . setting . mode = acMode ;
471
- else config . setting . mode = 'COOL' ;
472
- if ( verticalSwing != 'NOT_AVAILABLE' ) config . setting . verticalSwing = verticalSwing ;
473
- if ( horizontalSwing != 'NOT_AVAILABLE' ) config . setting . horizontalSwing = horizontalSwing ;
474
- //fan level not allowed in mode DRY
475
- if ( fanLevel != 'NOT_AVAILABLE' && acMode != 'DRY' ) config . setting . fanLevel = fanLevel ;
476
- if ( fanSpeed != 'NOT_AVAILABLE' && acMode != 'DRY' ) config . setting . fanSpeed = fanSpeed ;
477
- }
478
- if ( power == 'ON' ) {
479
- config . setting . power = 'ON' ;
480
- //temperature required for mode AUTO
481
- //temperature required for mode DRY
482
- //Temperature not for aircondition if mode is FAN, DRY(deactivated!) and not for HOT_WATER
483
- if ( ! ( type == 'HOT_WATER' || ( type == 'AIR_CONDITIONING' && ( acMode == 'DRY_DEACTIVATED!!' || acMode == 'FAN' ) ) ) ) {
484
- config . setting . temperature = { } ;
485
- config . setting . temperature . celsius = temperature ;
486
- }
487
- } else {
488
- config . setting . power = 'OFF' ;
489
- }
417
+ config . setting . power = power ;
490
418
if ( typeSkillBasedApp != 'NO_OVERLAY' ) {
491
419
config . termination = { } ;
492
420
config . termination . typeSkillBasedApp = typeSkillBasedApp ;
@@ -497,6 +425,89 @@ class Tado extends utils.Adapter {
497
425
config . termination . durationInSeconds = durationInSeconds ;
498
426
}
499
427
}
428
+ if ( type != 'HEATING' && type != 'AIR_CONDITIONING' && type != 'HOT_WATER' ) {
429
+ this . log . error ( `Invalid value '${ type } ' for state 'type'. Supported values are HOT_WATER, AIR_CONDITIONING and HEATING` ) ;
430
+ return ;
431
+ }
432
+ if ( power != 'ON' && power != 'OFF' ) {
433
+ this . log . error ( `Invalid value '${ power } ' for state 'power'. Supported values are ON and OFF` ) ;
434
+ return ;
435
+ }
436
+ if ( typeSkillBasedApp != 'TIMER' && typeSkillBasedApp != 'MANUAL' && typeSkillBasedApp != 'NEXT_TIME_BLOCK' && typeSkillBasedApp != 'NO_OVERLAY' ) {
437
+ this . log . error ( `Invalid value '${ typeSkillBasedApp } ' for state 'typeSkillBasedApp'. Allowed values are TIMER, MANUAL and NEXT_TIME_BLOCK` ) ;
438
+ return ;
439
+ }
440
+ let capType = this . roomCapabilities [ zone_id ] . type ;
441
+ if ( capType && capType != type ) {
442
+ this . log . error ( `Type ${ type } not valid. Type ${ capType } expected.` ) ;
443
+ return ;
444
+ }
445
+
446
+ if ( type == 'HEATING' && power == 'ON' ) {
447
+ let capMinTemp = this . roomCapabilities [ zone_id ] . temperatures . celsius . min ;
448
+ let capMaxTemp = this . roomCapabilities [ zone_id ] . temperatures . celsius . max ;
449
+
450
+ if ( capMinTemp && capMaxTemp ) {
451
+ if ( temperature > capMaxTemp || temperature < capMinTemp ) {
452
+ this . log . error ( `Temperature of ${ temperature } °C outside supported range of ${ capMinTemp } °C to ${ capMaxTemp } °C` ) ;
453
+ return ;
454
+ }
455
+ config . setting . temperature = { } ;
456
+ config . setting . temperature . celsius = temperature ;
457
+ }
458
+ }
459
+
460
+ if ( type == 'AIR_CONDITIONING' && power == 'ON' ) {
461
+ if ( ! this . roomCapabilities [ zone_id ] [ acMode ] ) {
462
+ this . log . error ( `AC-Mode ${ acMode } not supported!` ) ;
463
+ return ;
464
+ }
465
+ config . setting . mode = acMode ;
466
+ let capMinTemp = this . roomCapabilities [ zone_id ] [ acMode ] . temperatures . celsius . min ;
467
+ let capMaxTemp = this . roomCapabilities [ zone_id ] [ acMode ] . temperatures . celsius . max ;
468
+ let capHorizontalSwing = this . roomCapabilities [ zone_id ] [ acMode ] . horizontalSwing ;
469
+ let capVerticalSwing = this . roomCapabilities [ zone_id ] [ acMode ] . verticalSwing ;
470
+ let capFanSpeed = this . roomCapabilities [ zone_id ] [ acMode ] . fanSpeed ;
471
+ let capFanLevel = this . roomCapabilities [ zone_id ] [ acMode ] . fanLevel ;
472
+
473
+ if ( capMinTemp && capMaxTemp ) {
474
+ if ( temperature > capMaxTemp || temperature < capMinTemp ) {
475
+ this . log . error ( `Temperature of ${ temperature } °C outside supported range of ${ capMinTemp } °C to ${ capMaxTemp } °C` ) ;
476
+ return ;
477
+ }
478
+ config . setting . temperature = { } ;
479
+ config . setting . temperature . celsius = temperature ;
480
+ }
481
+ if ( capHorizontalSwing ) {
482
+ if ( ! capHorizontalSwing . includes ( horizontalSwing ) ) {
483
+ this . log . error ( `Invalid value '${ horizontalSwing } ' for state 'horizontalSwing'. Allowed values are ${ JSON . stringify ( capHorizontalSwing ) } ` ) ;
484
+ return ;
485
+ }
486
+ config . setting . horizontalSwing = horizontalSwing ;
487
+ }
488
+ if ( capVerticalSwing ) {
489
+ if ( ! capVerticalSwing . includes ( verticalSwing ) ) {
490
+ this . log . error ( `Invalid value '${ verticalSwing } ' for state 'verticalSwing'. Allowed values are ${ JSON . stringify ( capVerticalSwing ) } ` ) ;
491
+ return ;
492
+ }
493
+ config . setting . verticalSwing = verticalSwing ;
494
+ }
495
+ if ( capFanSpeed ) {
496
+ if ( ! capFanSpeed . includes ( fanSpeed ) ) {
497
+ this . log . error ( `Invalid value '${ fanSpeed } ' for state 'fanSpeed'. Allowed values are ${ JSON . stringify ( capFanSpeed ) } ` ) ;
498
+ return ;
499
+ }
500
+ config . setting . fanSpeed = fanSpeed ;
501
+ }
502
+ if ( capFanLevel ) {
503
+ if ( ! capFanLevel . includes ( fanLevel ) ) {
504
+ this . log . error ( `Invalid value '${ fanLevel } ' for state 'fanLevel'. Allowed values are ${ JSON . stringify ( capFanLevel ) } ` ) ;
505
+ return ;
506
+ }
507
+ config . setting . fanLevel = fanLevel ;
508
+ }
509
+ }
510
+
500
511
let result = await this . poolApiCall ( home_id , zone_id , config ) ;
501
512
this . log . debug ( `API 'ZoneOverlay' for home '${ home_id } ' and zone '${ zone_id } ' with body ${ JSON . stringify ( config ) } called.` ) ;
502
513
@@ -770,9 +781,11 @@ class Tado extends utils.Adapter {
770
781
JsonExplorer . TraverseJson ( this . Zones_data , `${ HomeId } .Rooms` , true , true , 0 , 0 ) ;
771
782
772
783
for ( const i in this . Zones_data ) {
773
- await this . DoZoneStates ( HomeId , this . Zones_data [ i ] . id ) ;
774
- await this . DoAwayConfiguration ( HomeId , this . Zones_data [ i ] . id ) ;
775
- await this . DoTimeTables ( HomeId , this . Zones_data [ i ] . id ) ;
784
+ let zoneId = this . Zones_data [ i ] . id ;
785
+ await this . DoZoneStates ( HomeId , zoneId ) ;
786
+ if ( ! this . roomCapabilities [ zoneId ] ) await this . DoCapabilities ( HomeId , zoneId ) ;
787
+ await this . DoAwayConfiguration ( HomeId , zoneId ) ;
788
+ await this . DoTimeTables ( HomeId , zoneId ) ;
776
789
}
777
790
}
778
791
@@ -788,6 +801,14 @@ class Tado extends utils.Adapter {
788
801
JsonExplorer . TraverseJson ( ZonesState_data , HomeId + '.Rooms.' + ZoneId , true , true , 0 , 2 ) ;
789
802
}
790
803
804
+ async DoCapabilities ( HomeId , ZoneId ) {
805
+ const capabilities_data = await this . getCapabilities ( HomeId , ZoneId ) ;
806
+ this . roomCapabilities [ ZoneId ] = capabilities_data ;
807
+ this . log . debug ( `Capabilities_data result for room '${ ZoneId } ' is ${ JSON . stringify ( capabilities_data ) } ` ) ;
808
+ this . DoWriteJsonRespons ( HomeId , 'Stage_09_Capabilities_data_' + ZoneId , capabilities_data ) ;
809
+ JsonExplorer . TraverseJson ( capabilities_data , HomeId + '.Rooms.' + ZoneId + '.capabilities' , true , true , 0 , 2 ) ;
810
+ }
811
+
791
812
/**
792
813
* @param {string } HomeId
793
814
* @param {string } ZoneId
@@ -809,7 +830,7 @@ class Tado extends utils.Adapter {
809
830
const AwayConfiguration_data = await this . getAwayConfiguration ( HomeId , ZoneId ) ;
810
831
this . log . debug ( 'AwayConfiguration_data Result: ' + JSON . stringify ( AwayConfiguration_data ) ) ;
811
832
this . DoWriteJsonRespons ( HomeId , 'Stage_10_AwayConfiguration_' + ZoneId , AwayConfiguration_data ) ;
812
- JsonExplorer . TraverseJson ( AwayConfiguration_data , HomeId + '.Rooms.' + ZoneId + '.AwayConfig ' , true , true , 0 , 2 ) ;
833
+ JsonExplorer . TraverseJson ( AwayConfiguration_data , HomeId + '.Rooms.' + ZoneId + '.awayConfig ' , true , true , 0 , 2 ) ;
813
834
}
814
835
815
836
async DoWriteJsonRespons ( HomeId , state_name , value ) {
@@ -840,7 +861,6 @@ class Tado extends utils.Adapter {
840
861
//////////////////////////////////////////////////////////////////////
841
862
/* MASTERSWITCH */
842
863
//////////////////////////////////////////////////////////////////////
843
-
844
864
async setMasterSwitch ( masterswitch ) {
845
865
masterswitch = masterswitch . toUpperCase ( ) ;
846
866
if ( ! ( masterswitch == 'ON' || masterswitch == 'OFF' ) ) throw new Error ( `Masterswitch value 'ON' or 'OFF' expected but received '${ masterswitch } '` ) ;
@@ -1072,6 +1092,10 @@ class Tado extends utils.Adapter {
1072
1092
return this . apiCall ( `/api/v2/homes/${ home_id } /zones/${ zone_id } /state` ) ;
1073
1093
}
1074
1094
1095
+ getCapabilities ( home_id , zone_id ) {
1096
+ return this . apiCall ( `/api/v2/homes/${ home_id } /zones/${ zone_id } /capabilities` ) ;
1097
+ }
1098
+
1075
1099
getAwayConfiguration ( home_id , zone_id ) {
1076
1100
return this . apiCall ( `/api/v2/homes/${ home_id } /zones/${ zone_id } /awayConfiguration` ) ;
1077
1101
}
@@ -1093,19 +1117,10 @@ class Tado extends utils.Adapter {
1093
1117
return this.apiCall(`/api/v2/homes/${home_id}/devices`);
1094
1118
}*/
1095
1119
1096
- /*getTimeTable(home_id, zone_id, timetable_id) {
1097
- return this.apiCall(`/api/v2/homes/${home_id}/zones/${zone_id}/schedule/timetables/${timetable_id}/blocks`);
1098
- }*/
1099
-
1100
1120
/*getZoneOverlay(home_id, zone_id) {
1101
1121
return this.apiCall(`/api/v2/homes/${home_id}/zones/${zone_id}/overlay`);
1102
1122
}*/
1103
1123
1104
- /*
1105
- getZoneCapabilities(home_id, zone_id) {
1106
- return this.apiCall(`/api/v2/homes/${home_id}/zones/${zone_id}/capabilities`);
1107
- }*/
1108
-
1109
1124
/*getInstallations(home_id) {
1110
1125
return this.apiCall(`/api/v2/homes/${home_id}/installations`);
1111
1126
}*/
0 commit comments