@homebridge-plugins/homebridge-tado 8.5.1-beta.1 → 8.5.1-beta.3

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.
@@ -3,9 +3,10 @@ import moment from 'moment';
3
3
  import { writeFile, access, readFile } from 'fs/promises';
4
4
  import { join } from "path";
5
5
 
6
- var settingState = false;
7
- var delayTimer = {};
6
+ let settingState = false;
8
7
  let tasksInitialized = false;
8
+ let lastGetStates = 0;
9
+ const delayTimer = {};
9
10
 
10
11
  const timeout = (ms) => new Promise((res) => setTimeout(res, ms));
11
12
  const aRefreshHistoryHandlers = [];
@@ -23,6 +24,7 @@ export async function getPersistedStates(storagePath) {
23
24
  }
24
25
 
25
26
  export default (api, accessories, config, tado, telegram) => {
27
+ const statesIntervalTime = Math.max(config.polling, 30) * 1000;
26
28
  const storagePath = api.user.storagePath();
27
29
 
28
30
  async function setStates(accessory, accs, target, value) {
@@ -565,9 +567,11 @@ export default (api, accessories, config, tado, telegram) => {
565
567
  } catch (err) {
566
568
  errorHandler(err);
567
569
  } finally {
568
- //always update zone to set correct state in Apple Home
569
- if (zoneUpdated) await updateZones(accessory.context.config.zoneId);
570
570
  settingState = false;
571
+ //update zones to ensure correct state in Apple Home
572
+ const timeSinceLastGetStates = Date.now() - lastGetStates;
573
+ const statesIntervalTimeLeft = statesIntervalTime - timeSinceLastGetStates;
574
+ if (zoneUpdated && statesIntervalTimeLeft > 10_000) await updateZones();
571
575
  }
572
576
  }
573
577
 
@@ -746,7 +750,7 @@ export default (api, accessories, config, tado, telegram) => {
746
750
  }
747
751
  try {
748
752
  //wait for fakegato history services to be loaded
749
- await new Promise(r => setTimeout(r, 4000));
753
+ await timeout(4000);
750
754
  for (const refreshHistory of aRefreshHistoryHandlers) {
751
755
  refreshHistory();
752
756
  }
@@ -769,13 +773,14 @@ export default (api, accessories, config, tado, telegram) => {
769
773
  tasksInitialized = true;
770
774
 
771
775
  void getStates();
772
- setInterval(() => getStates(), Math.max(config.polling, 30) * 1000);
776
+ setInterval(() => getStates(), statesIntervalTime);
773
777
 
774
778
  void logCounter();
775
779
  setInterval(() => logCounter(), 60 * 60 * 1000);
776
780
  }
777
781
 
778
782
  async function getStates() {
783
+ lastGetStates = Date.now();
779
784
  let zoneStates = {};
780
785
  try {
781
786
  //ME
@@ -809,413 +814,382 @@ export default (api, accessories, config, tado, telegram) => {
809
814
  }
810
815
 
811
816
  async function updateMe() {
812
- if (!settingState) {
813
- Logger.debug('Polling User Info...', config.homeName);
817
+ if (settingState) return;
814
818
 
815
- const me = await tado.getMe();
819
+ Logger.debug('Polling User Info...', config.homeName);
816
820
 
817
- if (config.homeName !== me.homes[0].name) throw ('Cannot find requested home in the API!', config.homeName);
821
+ const me = await tado.getMe();
818
822
 
819
- config.homeId = me.homes[0].id;
820
- }
823
+ if (config.homeName !== me.homes[0].name) throw ('Cannot find requested home in the API!', config.homeName);
821
824
 
822
- return;
825
+ config.homeId = me.homes[0].id;
823
826
  }
824
827
 
825
828
  async function updateHome() {
826
- if (!settingState) {
827
- Logger.debug('Polling Home Info...', config.homeName);
829
+ if (settingState) return;
828
830
 
829
- const home = await tado.getHome(config.homeId);
831
+ Logger.debug('Polling Home Info...', config.homeName);
830
832
 
831
- if (!config.temperatureUnit) config.temperatureUnit = home.temperatureUnit || 'CELSIUS';
833
+ const home = await tado.getHome(config.homeId);
832
834
 
833
- //config.skills = home.skills || []; //do we need this?
835
+ if (!config.temperatureUnit) config.temperatureUnit = home.temperatureUnit || 'CELSIUS';
834
836
 
835
- if (
836
- !config.geolocation ||
837
- (config.geolocation && !config.geolocation.longitude) ||
838
- !config.geolocation.latitude
839
- ) {
840
- if (!home.geolocation) home.geolocation = {};
837
+ //config.skills = home.skills || []; //do we need this?
841
838
 
842
- config.geolocation = {
843
- longitude: (home.geolocation.longitude || '').toString() || false,
844
- latitude: (home.geolocation.latitude || '').toString() || false,
845
- };
846
- }
847
- }
839
+ if (
840
+ !config.geolocation ||
841
+ (config.geolocation && !config.geolocation.longitude) ||
842
+ !config.geolocation.latitude
843
+ ) {
844
+ if (!home.geolocation) home.geolocation = {};
848
845
 
849
- return;
846
+ config.geolocation = {
847
+ longitude: (home.geolocation.longitude || '').toString() || false,
848
+ latitude: (home.geolocation.latitude || '').toString() || false,
849
+ };
850
+ }
850
851
  }
851
852
 
852
- async function updateZones(idToUpdate) {
853
- let zoneStates = {};
854
- if (!settingState || idToUpdate !== undefined) {
855
- Logger.debug('Polling Zones...', config.homeName);
853
+ async function updateZones() {
854
+ if (settingState) return;
856
855
 
857
- //CentralSwitch
858
- let inManualMode = 0;
859
- let inOffMode = 0;
860
- let inAutoMode = 0;
856
+ Logger.debug('Polling Zones...', config.homeName);
861
857
 
862
- let zonesWithoutID = config.zones.filter((zone) => zone && !zone.id);
858
+ //CentralSwitch
859
+ let inManualMode = 0;
860
+ let inOffMode = 0;
861
+ let inAutoMode = 0;
863
862
 
864
- if (zonesWithoutID.length) {
865
- const allZones = (await tado.getZones(config.homeId)) || [];
866
-
867
- for (const [index, zone] of config.zones.entries()) {
868
- allZones.forEach((zoneWithID) => {
869
- if (zoneWithID.name === zone.name) config.zones[index].id = zoneWithID.id;
870
- });
871
- }
872
- }
863
+ let zonesWithoutID = config.zones.filter((zone) => zone && !zone.id);
873
864
 
865
+ if (zonesWithoutID.length) {
874
866
  const allZones = (await tado.getZones(config.homeId)) || [];
875
867
 
876
868
  for (const [index, zone] of config.zones.entries()) {
877
869
  allZones.forEach((zoneWithID) => {
878
- if (zoneWithID.name === zone.name) {
879
- const heatAccessory = accessories.filter(
880
- (acc) => acc && acc.displayName === config.homeName + ' ' + zone.name + ' Heater'
881
- );
882
-
883
- if (heatAccessory.length) heatAccessory[0].context.config.zoneId = zoneWithID.id;
884
-
885
- config.zones[index].id = zoneWithID.id;
886
- config.zones[index].battery = !config.zones[index].noBattery
887
- ? zoneWithID.devices.filter(
888
- (device) =>
889
- device &&
890
- (zone.type === 'HEATING' || zone.type === 'AIR_CONDITIONING') &&
891
- typeof device.batteryState === 'string' &&
892
- !device.batteryState.includes('NORMAL')
893
- ).length
894
- ? zoneWithID.devices.filter((device) => device && !device.batteryState.includes('NORMAL'))[0]
895
- .batteryState
896
- : zoneWithID.devices.filter((device) => device && device.duties.includes('ZONE_LEADER'))[0].batteryState
897
- : false;
898
- config.zones[index].openWindowEnabled =
899
- zoneWithID.openWindowDetection && zoneWithID.openWindowDetection.enabled ? true : false;
900
- }
870
+ if (zoneWithID.name === zone.name) config.zones[index].id = zoneWithID.id;
901
871
  });
902
872
  }
873
+ }
903
874
 
904
- let zonesToUpdate = [];
905
- if (idToUpdate !== undefined) {
906
- zoneStates[idToUpdate] = await tado.getZoneState(config.homeId, idToUpdate);
907
- zonesToUpdate = config.zones.filter(zone => zone.id === idToUpdate);
908
- } else {
909
- zoneStates = (await tado.getZoneStates(config.homeId))["zoneStates"];
910
- zonesToUpdate = config.zones;
911
- }
875
+ const allZones = (await tado.getZones(config.homeId)) || [];
912
876
 
913
- for (const zone of zonesToUpdate) {
914
- const zoneState = zoneStates[zone.id];
877
+ for (const [index, zone] of config.zones.entries()) {
878
+ allZones.forEach((zoneWithID) => {
879
+ if (zoneWithID.name === zone.name) {
880
+ const heatAccessory = accessories.filter(
881
+ (acc) => acc && acc.displayName === config.homeName + ' ' + zone.name + ' Heater'
882
+ );
915
883
 
916
- let currentState, targetState, currentTemp, targetTemp, humidity, active, battery, tempEqual;
884
+ if (heatAccessory.length) heatAccessory[0].context.config.zoneId = zoneWithID.id;
885
+
886
+ config.zones[index].id = zoneWithID.id;
887
+ config.zones[index].battery = !config.zones[index].noBattery
888
+ ? zoneWithID.devices.filter(
889
+ (device) =>
890
+ device &&
891
+ (zone.type === 'HEATING' || zone.type === 'AIR_CONDITIONING') &&
892
+ typeof device.batteryState === 'string' &&
893
+ !device.batteryState.includes('NORMAL')
894
+ ).length
895
+ ? zoneWithID.devices.filter((device) => device && !device.batteryState.includes('NORMAL'))[0]
896
+ .batteryState
897
+ : zoneWithID.devices.filter((device) => device && device.duties.includes('ZONE_LEADER'))[0].batteryState
898
+ : false;
899
+ config.zones[index].openWindowEnabled =
900
+ zoneWithID.openWindowDetection && zoneWithID.openWindowDetection.enabled ? true : false;
901
+ }
902
+ });
903
+ }
917
904
 
918
- if (zoneState.setting.type === 'HEATING') {
919
- battery = zone.battery === 'NORMAL' ? 100 : 10;
905
+ const zoneStates = (await tado.getZoneStates(config.homeId))["zoneStates"] ?? {};
906
+ const zonesToUpdate = config.zones;
920
907
 
921
- if (zoneState.sensorDataPoints.humidity) humidity = zoneState.sensorDataPoints.humidity.percentage;
908
+ for (const zone of zonesToUpdate) {
909
+ const zoneState = zoneStates[zone.id.toString()];
910
+ Logger.debug(`Update state of zone ${zone.id} to:`, zoneState);
922
911
 
923
- //HEATING
924
- if (zoneState.sensorDataPoints.insideTemperature) {
925
- currentTemp =
926
- config.temperatureUnit === 'FAHRENHEIT'
927
- ? zoneState.sensorDataPoints.insideTemperature.fahrenheit
928
- : zoneState.sensorDataPoints.insideTemperature.celsius;
912
+ let currentState, targetState, currentTemp, targetTemp, humidity, active, battery, tempEqual;
929
913
 
930
- if (zoneState.setting.power === 'ON') {
931
- targetTemp =
932
- config.temperatureUnit === 'FAHRENHEIT'
933
- ? zoneState.setting.temperature.fahrenheit
934
- : zoneState.setting.temperature.celsius;
914
+ if (zoneState.setting.type === 'HEATING') {
915
+ battery = zone.battery === 'NORMAL' ? 100 : 10;
935
916
 
936
- tempEqual = Math.round(currentTemp) === Math.round(targetTemp);
917
+ if (zoneState.sensorDataPoints.humidity) humidity = zoneState.sensorDataPoints.humidity.percentage;
937
918
 
938
- //show as currently heating if current temp is lower than target temp, otherwise show as temp set
939
- currentState = currentTemp < targetTemp ? 1 : 0;
919
+ //HEATING
920
+ if (zoneState.sensorDataPoints.insideTemperature) {
921
+ currentTemp =
922
+ config.temperatureUnit === 'FAHRENHEIT'
923
+ ? zoneState.sensorDataPoints.insideTemperature.fahrenheit
924
+ : zoneState.sensorDataPoints.insideTemperature.celsius;
940
925
 
941
- //check if auto mode is enabled
942
- targetState = zoneState.overlayType === null ? 3 : 1;
926
+ if (zoneState.setting.power === 'ON') {
927
+ targetTemp =
928
+ config.temperatureUnit === 'FAHRENHEIT'
929
+ ? zoneState.setting.temperature.fahrenheit
930
+ : zoneState.setting.temperature.celsius;
943
931
 
944
- active = 1;
945
- } else {
946
- //heating is switched off
947
- currentState = 0;
948
- targetState = 0;
949
- active = 0;
950
- }
932
+ tempEqual = Math.round(currentTemp) === Math.round(targetTemp);
951
933
 
952
- if (targetState === undefined && zoneState.overlayType === null) {
953
- targetState = 3;
954
- }
955
- }
934
+ //show as currently heating if current temp is lower than target temp, otherwise show as temp set
935
+ currentState = currentTemp < targetTemp ? 1 : 0;
956
936
 
957
- //Thermostat/HeaterCooler
958
- const thermoAccessory = accessories.filter(
959
- (acc) =>
960
- acc &&
961
- (acc.context.config.subtype === 'zone-thermostat' ||
962
- acc.context.config.subtype === 'zone-heatercooler' ||
963
- acc.context.config.subtype === 'zone-heatercooler-ac')
964
- );
937
+ //check if auto mode is enabled
938
+ targetState = zoneState.overlayType === null ? 3 : 1;
965
939
 
966
- if (thermoAccessory.length) {
967
- thermoAccessory.forEach((acc) => {
968
- if (acc.displayName.includes(zone.name)) {
969
- let serviceThermostat = acc.getService(api.hap.Service.Thermostat);
970
- let serviceHeaterCooler = acc.getService(api.hap.Service.HeaterCooler);
940
+ active = 1;
941
+ } else {
942
+ //heating is switched off
943
+ currentState = 0;
944
+ targetState = 0;
945
+ active = 0;
946
+ }
971
947
 
972
- let serviceBattery = acc.getService(api.hap.Service.BatteryService);
973
- let characteristicBattery = api.hap.Characteristic.BatteryLevel;
948
+ if (targetState === undefined && zoneState.overlayType === null) {
949
+ targetState = 3;
950
+ }
951
+ }
974
952
 
975
- if (serviceBattery && zone.battery) {
976
- serviceBattery.getCharacteristic(characteristicBattery).updateValue(battery);
977
- }
953
+ //Thermostat/HeaterCooler
954
+ const thermoAccessory = accessories.filter(
955
+ (acc) =>
956
+ acc &&
957
+ (acc.context.config.subtype === 'zone-thermostat' ||
958
+ acc.context.config.subtype === 'zone-heatercooler' ||
959
+ acc.context.config.subtype === 'zone-heatercooler-ac')
960
+ );
978
961
 
979
- if (serviceThermostat) {
980
- let characteristicCurrentTemp = api.hap.Characteristic.CurrentTemperature;
981
- let characteristicTargetTemp = api.hap.Characteristic.TargetTemperature;
982
- let characteristicCurrentState = api.hap.Characteristic.CurrentHeatingCoolingState;
983
- let characteristicTargetState = api.hap.Characteristic.TargetHeatingCoolingState;
984
- let characteristicHumidity = api.hap.Characteristic.CurrentRelativeHumidity;
985
- let characteristicUnit = api.hap.Characteristic.TemperatureDisplayUnits;
962
+ if (thermoAccessory.length) {
963
+ thermoAccessory.forEach((acc) => {
964
+ if (acc.displayName.includes(zone.name)) {
965
+ let serviceThermostat = acc.getService(api.hap.Service.Thermostat);
966
+ let serviceHeaterCooler = acc.getService(api.hap.Service.HeaterCooler);
986
967
 
987
- if (!isNaN(currentTemp)) {
988
- acc.context.config.temperatureUnit = acc.context.config.temperatureUnit || config.temperatureUnit;
968
+ let serviceBattery = acc.getService(api.hap.Service.BatteryService);
969
+ let characteristicBattery = api.hap.Characteristic.BatteryLevel;
989
970
 
990
- let isFahrenheit = serviceThermostat.getCharacteristic(characteristicUnit).value === 1;
991
- let unitChanged = config.temperatureUnit !== acc.context.config.temperatureUnit;
971
+ if (serviceBattery && zone.battery) {
972
+ serviceBattery.getCharacteristic(characteristicBattery).updateValue(battery);
973
+ }
992
974
 
993
- let cToF = (c) => Math.round((c * 9) / 5 + 32);
994
- let fToC = (f) => Math.round(((f - 32) * 5) / 9);
975
+ if (serviceThermostat) {
976
+ let characteristicCurrentTemp = api.hap.Characteristic.CurrentTemperature;
977
+ let characteristicTargetTemp = api.hap.Characteristic.TargetTemperature;
978
+ let characteristicCurrentState = api.hap.Characteristic.CurrentHeatingCoolingState;
979
+ let characteristicTargetState = api.hap.Characteristic.TargetHeatingCoolingState;
980
+ let characteristicHumidity = api.hap.Characteristic.CurrentRelativeHumidity;
981
+ let characteristicUnit = api.hap.Characteristic.TemperatureDisplayUnits;
995
982
 
996
- let newValue = unitChanged ? (isFahrenheit ? cToF(currentTemp) : fToC(currentTemp)) : currentTemp;
983
+ if (!isNaN(currentTemp)) {
984
+ acc.context.config.temperatureUnit = acc.context.config.temperatureUnit || config.temperatureUnit;
997
985
 
998
- serviceThermostat.getCharacteristic(characteristicCurrentTemp).updateValue(newValue);
999
- }
986
+ let isFahrenheit = serviceThermostat.getCharacteristic(characteristicUnit).value === 1;
987
+ let unitChanged = config.temperatureUnit !== acc.context.config.temperatureUnit;
1000
988
 
1001
- if (!isNaN(targetTemp))
1002
- serviceThermostat.getCharacteristic(characteristicTargetTemp).updateValue(targetTemp);
989
+ let cToF = (c) => Math.round((c * 9) / 5 + 32);
990
+ let fToC = (f) => Math.round(((f - 32) * 5) / 9);
1003
991
 
1004
- if (!isNaN(currentState))
1005
- serviceThermostat.getCharacteristic(characteristicCurrentState).updateValue(currentState);
992
+ let newValue = unitChanged ? (isFahrenheit ? cToF(currentTemp) : fToC(currentTemp)) : currentTemp;
1006
993
 
1007
- if (!isNaN(targetState))
1008
- serviceThermostat.getCharacteristic(characteristicTargetState).updateValue(targetState);
1009
-
1010
- if (!isNaN(humidity) && serviceThermostat.testCharacteristic(characteristicHumidity))
1011
- serviceThermostat.getCharacteristic(characteristicHumidity).updateValue(humidity);
994
+ serviceThermostat.getCharacteristic(characteristicCurrentTemp).updateValue(newValue);
1012
995
  }
1013
996
 
1014
- if (serviceHeaterCooler) {
1015
- let characteristicHumidity = api.hap.Characteristic.CurrentRelativeHumidity;
1016
- let characteristicCurrentTemp = api.hap.Characteristic.CurrentTemperature;
1017
- let characteristicTargetTempHeating = api.hap.Characteristic.HeatingThresholdTemperature;
1018
- let characteristicTargetTempCooling = api.hap.Characteristic.CoolingThresholdTemperature;
1019
- let characteristicCurrentState = api.hap.Characteristic.CurrentHeaterCoolerState;
1020
- let characteristicTargetState = api.hap.Characteristic.TargetHeaterCoolerState;
1021
- let characteristicActive = api.hap.Characteristic.Active;
997
+ if (!isNaN(targetTemp))
998
+ serviceThermostat.getCharacteristic(characteristicTargetTemp).updateValue(targetTemp);
1022
999
 
1023
- currentState = active ? (targetState === 3 || tempEqual ? 1 : currentState + 1) : 0;
1000
+ if (!isNaN(currentState))
1001
+ serviceThermostat.getCharacteristic(characteristicCurrentState).updateValue(currentState);
1024
1002
 
1025
- targetState = 1;
1003
+ if (!isNaN(targetState))
1004
+ serviceThermostat.getCharacteristic(characteristicTargetState).updateValue(targetState);
1026
1005
 
1027
- if (!isNaN(active)) serviceHeaterCooler.getCharacteristic(characteristicActive).updateValue(active);
1006
+ if (!isNaN(humidity) && serviceThermostat.testCharacteristic(characteristicHumidity))
1007
+ serviceThermostat.getCharacteristic(characteristicHumidity).updateValue(humidity);
1008
+ }
1028
1009
 
1029
- if (!isNaN(currentTemp))
1030
- serviceHeaterCooler.getCharacteristic(characteristicCurrentTemp).updateValue(currentTemp);
1010
+ if (serviceHeaterCooler) {
1011
+ let characteristicHumidity = api.hap.Characteristic.CurrentRelativeHumidity;
1012
+ let characteristicCurrentTemp = api.hap.Characteristic.CurrentTemperature;
1013
+ let characteristicTargetTempHeating = api.hap.Characteristic.HeatingThresholdTemperature;
1014
+ let characteristicTargetTempCooling = api.hap.Characteristic.CoolingThresholdTemperature;
1015
+ let characteristicCurrentState = api.hap.Characteristic.CurrentHeaterCoolerState;
1016
+ let characteristicTargetState = api.hap.Characteristic.TargetHeaterCoolerState;
1017
+ let characteristicActive = api.hap.Characteristic.Active;
1031
1018
 
1032
- if (!isNaN(targetTemp)) {
1033
- serviceHeaterCooler.getCharacteristic(characteristicTargetTempHeating).updateValue(targetTemp);
1019
+ currentState = active ? (targetState === 3 || tempEqual ? 1 : currentState + 1) : 0;
1034
1020
 
1035
- serviceHeaterCooler.getCharacteristic(characteristicTargetTempCooling).updateValue(targetTemp);
1036
- }
1021
+ targetState = 1;
1037
1022
 
1038
- if (!isNaN(currentState))
1039
- serviceHeaterCooler.getCharacteristic(characteristicCurrentState).updateValue(currentState);
1023
+ if (!isNaN(active)) serviceHeaterCooler.getCharacteristic(characteristicActive).updateValue(active);
1040
1024
 
1041
- if (!isNaN(targetState))
1042
- serviceHeaterCooler.getCharacteristic(characteristicTargetState).updateValue(targetState);
1025
+ if (!isNaN(currentTemp))
1026
+ serviceHeaterCooler.getCharacteristic(characteristicCurrentTemp).updateValue(currentTemp);
1043
1027
 
1044
- if (!isNaN(humidity) && serviceHeaterCooler.testCharacteristic(characteristicHumidity))
1045
- serviceHeaterCooler.getCharacteristic(characteristicHumidity).updateValue(humidity);
1046
- }
1047
- }
1048
- });
1049
- }
1050
- } else {
1051
- // Non-HEATING zones (AIR_CONDITIONING, HOT_WATER, etc.)
1052
- battery = zone.battery === 'NORMAL' ? 100 : 10;
1028
+ if (!isNaN(targetTemp)) {
1029
+ serviceHeaterCooler.getCharacteristic(characteristicTargetTempHeating).updateValue(targetTemp);
1053
1030
 
1054
- if (zoneState.sensorDataPoints.humidity) {
1055
- humidity = zoneState.sensorDataPoints.humidity.percentage;
1056
- }
1031
+ serviceHeaterCooler.getCharacteristic(characteristicTargetTempCooling).updateValue(targetTemp);
1032
+ }
1057
1033
 
1058
- // Get current temperature from sensor data (same as HEATING zones)
1059
- if (zoneState.sensorDataPoints.insideTemperature) {
1060
- currentTemp =
1061
- config.temperatureUnit === 'FAHRENHEIT'
1062
- ? zoneState.sensorDataPoints.insideTemperature.fahrenheit
1063
- : zoneState.sensorDataPoints.insideTemperature.celsius;
1064
- }
1034
+ if (!isNaN(currentState))
1035
+ serviceHeaterCooler.getCharacteristic(characteristicCurrentState).updateValue(currentState);
1065
1036
 
1066
- if (zoneState.setting.power === 'ON') {
1067
- active = 1;
1037
+ if (!isNaN(targetState))
1038
+ serviceHeaterCooler.getCharacteristic(characteristicTargetState).updateValue(targetState);
1068
1039
 
1069
- // Get target temperature from setting
1070
- targetTemp =
1071
- zoneState.setting.temperature !== null && zoneState.setting.temperature
1072
- ? config.temperatureUnit === 'FAHRENHEIT'
1073
- ? zoneState.setting.temperature.fahrenheit
1074
- : zoneState.setting.temperature.celsius
1075
- : undefined;
1076
-
1077
- // Enhanced AC state handling
1078
- if (zone.type === 'AIR_CONDITIONING') {
1079
- const acMode = zoneState.setting.mode || 'COOL';
1080
- tempEqual = currentTemp && targetTemp ? Math.abs(currentTemp - targetTemp) < 0.5 : false;
1081
-
1082
- // Map AC modes to HomeKit states
1083
- switch (acMode.toUpperCase()) {
1084
- case 'HEAT':
1085
- targetState = 1; // Heating
1086
- currentState = tempEqual ? 1 : (currentTemp < targetTemp ? 2 : 1); // Idle or Heating
1087
- break;
1088
- case 'COOL':
1089
- case 'AUTO':
1090
- default:
1091
- targetState = 2; // Cooling
1092
- currentState = tempEqual ? 1 : (currentTemp > targetTemp ? 3 : 1); // Idle or Cooling
1093
- break;
1040
+ if (!isNaN(humidity) && serviceHeaterCooler.testCharacteristic(characteristicHumidity))
1041
+ serviceHeaterCooler.getCharacteristic(characteristicHumidity).updateValue(humidity);
1094
1042
  }
1095
- } else {
1096
- // Non-AC zones (HOT_WATER, etc.)
1097
- currentState = zoneState.overlayType === null ? 1 : 2;
1098
- targetState = 1;
1099
1043
  }
1100
- } else {
1101
- active = 0;
1102
- currentState = 0;
1103
- targetTemp = undefined;
1104
- targetState = zone.type === 'AIR_CONDITIONING' ? 2 : 1; // Default to cooling for AC, heating for others
1105
- }
1044
+ });
1045
+ }
1046
+ } else {
1047
+ // Non-HEATING zones (AIR_CONDITIONING, HOT_WATER, etc.)
1048
+ battery = zone.battery === 'NORMAL' ? 100 : 10;
1106
1049
 
1107
- //Thermostat/HeaterCooler
1108
- const heaterAccessory = accessories.filter(
1109
- (acc) => acc && (acc.context.config.subtype === 'zone-heatercooler-boiler' ||
1110
- acc.context.config.subtype === 'zone-heatercooler-ac')
1111
- );
1112
- const switchAccessory = accessories.filter((acc) => acc && acc.context.config.subtype === 'zone-switch');
1113
- const faucetAccessory = accessories.filter((acc) => acc && acc.context.config.subtype === 'zone-faucet');
1050
+ if (zoneState.sensorDataPoints.humidity) {
1051
+ humidity = zoneState.sensorDataPoints.humidity.percentage;
1052
+ }
1114
1053
 
1115
- if (heaterAccessory.length) {
1116
- heaterAccessory.forEach((acc) => {
1117
- if (acc.displayName.includes(zone.name)) {
1118
- let service = acc.getService(api.hap.Service.HeaterCooler);
1054
+ // Get current temperature from sensor data (same as HEATING zones)
1055
+ if (zoneState.sensorDataPoints.insideTemperature) {
1056
+ currentTemp =
1057
+ config.temperatureUnit === 'FAHRENHEIT'
1058
+ ? zoneState.sensorDataPoints.insideTemperature.fahrenheit
1059
+ : zoneState.sensorDataPoints.insideTemperature.celsius;
1060
+ }
1119
1061
 
1120
- let characteristicCurrentTemp = api.hap.Characteristic.CurrentTemperature;
1121
- let characteristicActive = api.hap.Characteristic.Active;
1122
- let characteristicCurrentState = api.hap.Characteristic.CurrentHeaterCoolerState;
1123
- let characteristicTargetState = api.hap.Characteristic.TargetHeaterCoolerState;
1124
- let characteristicTargetTempHeating = api.hap.Characteristic.HeatingThresholdTemperature;
1125
- let characteristicTargetTempCooling = api.hap.Characteristic.CoolingThresholdTemperature;
1062
+ if (zoneState.setting.power === 'ON') {
1063
+ active = 1;
1064
+
1065
+ // Get target temperature from setting
1066
+ targetTemp =
1067
+ zoneState.setting.temperature !== null && zoneState.setting.temperature
1068
+ ? config.temperatureUnit === 'FAHRENHEIT'
1069
+ ? zoneState.setting.temperature.fahrenheit
1070
+ : zoneState.setting.temperature.celsius
1071
+ : undefined;
1072
+
1073
+ // Enhanced AC state handling
1074
+ if (zone.type === 'AIR_CONDITIONING') {
1075
+ const acMode = zoneState.setting.mode || 'COOL';
1076
+ tempEqual = currentTemp && targetTemp ? Math.abs(currentTemp - targetTemp) < 0.5 : false;
1077
+
1078
+ // Map AC modes to HomeKit states
1079
+ switch (acMode.toUpperCase()) {
1080
+ case 'HEAT':
1081
+ targetState = 1; // Heating
1082
+ currentState = tempEqual ? 1 : (currentTemp < targetTemp ? 2 : 1); // Idle or Heating
1083
+ break;
1084
+ case 'COOL':
1085
+ case 'AUTO':
1086
+ default:
1087
+ targetState = 2; // Cooling
1088
+ currentState = tempEqual ? 1 : (currentTemp > targetTemp ? 3 : 1); // Idle or Cooling
1089
+ break;
1090
+ }
1091
+ } else {
1092
+ // Non-AC zones (HOT_WATER, etc.)
1093
+ currentState = zoneState.overlayType === null ? 1 : 2;
1094
+ targetState = 1;
1095
+ }
1096
+ } else {
1097
+ active = 0;
1098
+ currentState = 0;
1099
+ targetTemp = undefined;
1100
+ targetState = zone.type === 'AIR_CONDITIONING' ? 2 : 1; // Default to cooling for AC, heating for others
1101
+ }
1126
1102
 
1127
- service.getCharacteristic(characteristicActive).updateValue(active);
1103
+ //Thermostat/HeaterCooler
1104
+ const heaterAccessory = accessories.filter(
1105
+ (acc) => acc && (acc.context.config.subtype === 'zone-heatercooler-boiler' ||
1106
+ acc.context.config.subtype === 'zone-heatercooler-ac')
1107
+ );
1108
+ const switchAccessory = accessories.filter((acc) => acc && acc.context.config.subtype === 'zone-switch');
1109
+ const faucetAccessory = accessories.filter((acc) => acc && acc.context.config.subtype === 'zone-faucet');
1128
1110
 
1129
- service.getCharacteristic(characteristicCurrentState).updateValue(currentState);
1111
+ if (heaterAccessory.length) {
1112
+ heaterAccessory.forEach((acc) => {
1113
+ if (acc.displayName.includes(zone.name)) {
1114
+ let service = acc.getService(api.hap.Service.HeaterCooler);
1130
1115
 
1131
- service.getCharacteristic(characteristicTargetState).updateValue(targetState);
1116
+ let characteristicCurrentTemp = api.hap.Characteristic.CurrentTemperature;
1117
+ let characteristicActive = api.hap.Characteristic.Active;
1118
+ let characteristicCurrentState = api.hap.Characteristic.CurrentHeaterCoolerState;
1119
+ let characteristicTargetState = api.hap.Characteristic.TargetHeaterCoolerState;
1120
+ let characteristicTargetTempHeating = api.hap.Characteristic.HeatingThresholdTemperature;
1121
+ let characteristicTargetTempCooling = api.hap.Characteristic.CoolingThresholdTemperature;
1132
1122
 
1133
- // Set current temperature from sensor data
1134
- if (!isNaN(currentTemp) || acc.context.currentTemp) {
1135
- if (!isNaN(currentTemp)) acc.context.currentTemp = currentTemp; //store current temp in config
1123
+ service.getCharacteristic(characteristicActive).updateValue(active);
1136
1124
 
1137
- service.getCharacteristic(characteristicCurrentTemp).updateValue(acc.context.currentTemp);
1138
- }
1125
+ service.getCharacteristic(characteristicCurrentState).updateValue(currentState);
1139
1126
 
1140
- // Set target temperature for both heating and cooling
1141
- if (!isNaN(targetTemp)) {
1142
- // For AC zones, set temperature based on the mode
1143
- if (zone.type === 'AIR_CONDITIONING') {
1144
- // Always set both characteristics but log which one is active
1145
- service.getCharacteristic(characteristicTargetTempHeating).updateValue(targetTemp);
1146
- service.getCharacteristic(characteristicTargetTempCooling).updateValue(targetTemp);
1147
- } else {
1148
- // Non-AC zones (like boiler/hot water)
1149
- service.getCharacteristic(characteristicTargetTempHeating).updateValue(targetTemp);
1150
- service.getCharacteristic(characteristicTargetTempCooling).updateValue(targetTemp);
1151
- }
1152
- }
1127
+ service.getCharacteristic(characteristicTargetState).updateValue(targetState);
1153
1128
 
1154
- // Fan speed polling removed for AIR_CONDITIONING zones
1129
+ // Set current temperature from sensor data
1130
+ if (!isNaN(currentTemp) || acc.context.currentTemp) {
1131
+ if (!isNaN(currentTemp)) acc.context.currentTemp = currentTemp; //store current temp in config
1155
1132
 
1156
- // Update humidity for all zones that support it
1157
- if (!isNaN(humidity) && service.testCharacteristic(api.hap.Characteristic.CurrentRelativeHumidity)) {
1158
- service.getCharacteristic(api.hap.Characteristic.CurrentRelativeHumidity).updateValue(humidity);
1159
- }
1133
+ service.getCharacteristic(characteristicCurrentTemp).updateValue(acc.context.currentTemp);
1160
1134
  }
1161
- });
1162
- }
1163
1135
 
1164
- if (switchAccessory.length) {
1165
- switchAccessory.forEach((acc) => {
1166
- if (acc.displayName.includes(zone.name)) {
1167
- let service = acc.getService(api.hap.Service.Switch);
1136
+ // Set target temperature for both heating and cooling
1137
+ if (!isNaN(targetTemp)) {
1138
+ // For AC zones, set temperature based on the mode
1139
+ if (zone.type === 'AIR_CONDITIONING') {
1140
+ // Always set both characteristics but log which one is active
1141
+ service.getCharacteristic(characteristicTargetTempHeating).updateValue(targetTemp);
1142
+ service.getCharacteristic(characteristicTargetTempCooling).updateValue(targetTemp);
1143
+ } else {
1144
+ // Non-AC zones (like boiler/hot water)
1145
+ service.getCharacteristic(characteristicTargetTempHeating).updateValue(targetTemp);
1146
+ service.getCharacteristic(characteristicTargetTempCooling).updateValue(targetTemp);
1147
+ }
1148
+ }
1168
1149
 
1169
- let characteristic = api.hap.Characteristic.On;
1150
+ // Fan speed polling removed for AIR_CONDITIONING zones
1170
1151
 
1171
- service.getCharacteristic(characteristic).updateValue(active ? true : false);
1152
+ // Update humidity for all zones that support it
1153
+ if (!isNaN(humidity) && service.testCharacteristic(api.hap.Characteristic.CurrentRelativeHumidity)) {
1154
+ service.getCharacteristic(api.hap.Characteristic.CurrentRelativeHumidity).updateValue(humidity);
1172
1155
  }
1173
- });
1174
- }
1175
-
1176
- if (faucetAccessory.length) {
1177
- faucetAccessory.forEach((acc) => {
1178
- if (acc.displayName.includes(zone.name)) {
1179
- let service = acc.getService(api.hap.Service.Valve);
1156
+ }
1157
+ });
1158
+ }
1180
1159
 
1181
- let characteristicActive = api.hap.Characteristic.Active;
1182
- let characteristicInUse = api.hap.Characteristic.InUse;
1160
+ if (switchAccessory.length) {
1161
+ switchAccessory.forEach((acc) => {
1162
+ if (acc.displayName.includes(zone.name)) {
1163
+ let service = acc.getService(api.hap.Service.Switch);
1183
1164
 
1184
- service.getCharacteristic(characteristicActive).updateValue(active ? 1 : 0);
1165
+ let characteristic = api.hap.Characteristic.On;
1185
1166
 
1186
- service.getCharacteristic(characteristicInUse).updateValue(active ? 1 : 0);
1187
- }
1188
- });
1189
- }
1167
+ service.getCharacteristic(characteristic).updateValue(active ? true : false);
1168
+ }
1169
+ });
1190
1170
  }
1191
1171
 
1192
- //TemperatureSensor
1193
- const tempAccessory = accessories.filter((acc) => acc && acc.context.config.subtype === 'zone-temperature');
1194
-
1195
- if (tempAccessory.length) {
1196
- tempAccessory.forEach((acc) => {
1172
+ if (faucetAccessory.length) {
1173
+ faucetAccessory.forEach((acc) => {
1197
1174
  if (acc.displayName.includes(zone.name)) {
1198
- let serviceBattery = acc.getService(api.hap.Service.BatteryService);
1199
- let characteristicBattery = api.hap.Characteristic.BatteryLevel;
1175
+ let service = acc.getService(api.hap.Service.Valve);
1200
1176
 
1201
- if (serviceBattery && !isNaN(battery)) {
1202
- serviceBattery.getCharacteristic(characteristicBattery).updateValue(battery);
1203
- }
1177
+ let characteristicActive = api.hap.Characteristic.Active;
1178
+ let characteristicInUse = api.hap.Characteristic.InUse;
1204
1179
 
1205
- if (!isNaN(currentTemp)) {
1206
- let service = acc.getService(api.hap.Service.TemperatureSensor);
1207
- let characteristic = api.hap.Characteristic.CurrentTemperature;
1180
+ service.getCharacteristic(characteristicActive).updateValue(active ? 1 : 0);
1208
1181
 
1209
- service.getCharacteristic(characteristic).updateValue(currentTemp);
1210
- }
1182
+ service.getCharacteristic(characteristicInUse).updateValue(active ? 1 : 0);
1211
1183
  }
1212
1184
  });
1213
1185
  }
1186
+ }
1214
1187
 
1215
- //HumiditySensor
1216
- const humidityAccessory = accessories.filter((acc) => acc && acc.context.config.subtype === 'zone-humidity');
1188
+ //TemperatureSensor
1189
+ const tempAccessory = accessories.filter((acc) => acc && acc.context.config.subtype === 'zone-temperature');
1217
1190
 
1218
- humidityAccessory.forEach((acc) => {
1191
+ if (tempAccessory.length) {
1192
+ tempAccessory.forEach((acc) => {
1219
1193
  if (acc.displayName.includes(zone.name)) {
1220
1194
  let serviceBattery = acc.getService(api.hap.Service.BatteryService);
1221
1195
  let characteristicBattery = api.hap.Characteristic.BatteryLevel;
@@ -1224,327 +1198,343 @@ export default (api, accessories, config, tado, telegram) => {
1224
1198
  serviceBattery.getCharacteristic(characteristicBattery).updateValue(battery);
1225
1199
  }
1226
1200
 
1227
- if (!isNaN(humidity)) {
1228
- let service = acc.getService(api.hap.Service.HumiditySensor);
1229
- let characteristic = api.hap.Characteristic.CurrentRelativeHumidity;
1201
+ if (!isNaN(currentTemp)) {
1202
+ let service = acc.getService(api.hap.Service.TemperatureSensor);
1203
+ let characteristic = api.hap.Characteristic.CurrentTemperature;
1230
1204
 
1231
- service.getCharacteristic(characteristic).updateValue(humidity);
1205
+ service.getCharacteristic(characteristic).updateValue(currentTemp);
1232
1206
  }
1233
1207
  }
1234
1208
  });
1209
+ }
1235
1210
 
1236
- //WindowSensor
1237
- const windowContactAccessory = accessories.filter(
1238
- (acc) => acc && acc.context.config.subtype === 'zone-window-contact'
1239
- );
1240
- const windowSwitchAccessory = accessories.filter(
1241
- (acc) => acc && acc.displayName === acc.context.config.homeName + ' Open Window'
1242
- );
1243
-
1244
- if (windowContactAccessory.length) {
1245
- windowContactAccessory.forEach((acc) => {
1246
- if (acc.displayName.includes(zone.name)) {
1247
- let serviceBattery = acc.getService(api.hap.Service.BatteryService);
1248
- let characteristicBattery = api.hap.Characteristic.BatteryLevel;
1211
+ //HumiditySensor
1212
+ const humidityAccessory = accessories.filter((acc) => acc && acc.context.config.subtype === 'zone-humidity');
1249
1213
 
1250
- if (serviceBattery && !isNaN(battery)) {
1251
- serviceBattery.getCharacteristic(characteristicBattery).updateValue(battery);
1252
- }
1214
+ humidityAccessory.forEach((acc) => {
1215
+ if (acc.displayName.includes(zone.name)) {
1216
+ let serviceBattery = acc.getService(api.hap.Service.BatteryService);
1217
+ let characteristicBattery = api.hap.Characteristic.BatteryLevel;
1253
1218
 
1254
- let service = acc.getService(api.hap.Service.ContactSensor);
1255
- let characteristic = api.hap.Characteristic.ContactSensorState;
1219
+ if (serviceBattery && !isNaN(battery)) {
1220
+ serviceBattery.getCharacteristic(characteristicBattery).updateValue(battery);
1221
+ }
1256
1222
 
1257
- let state = zoneState.openWindow || zoneState.openWindowDetected ? 1 : 0;
1223
+ if (!isNaN(humidity)) {
1224
+ let service = acc.getService(api.hap.Service.HumiditySensor);
1225
+ let characteristic = api.hap.Characteristic.CurrentRelativeHumidity;
1258
1226
 
1259
- service.getCharacteristic(characteristic).updateValue(state);
1260
- }
1261
- });
1227
+ service.getCharacteristic(characteristic).updateValue(humidity);
1228
+ }
1262
1229
  }
1230
+ });
1263
1231
 
1264
- if (windowSwitchAccessory.length) {
1265
- windowSwitchAccessory[0].services.forEach((switchService) => {
1266
- if (switchService.subtype && switchService.subtype.includes(zone.name)) {
1267
- let service = windowSwitchAccessory[0].getServiceById(api.hap.Service.Switch, switchService.subtype);
1268
- let characteristic = api.hap.Characteristic.On;
1232
+ //WindowSensor
1233
+ const windowContactAccessory = accessories.filter(
1234
+ (acc) => acc && acc.context.config.subtype === 'zone-window-contact'
1235
+ );
1236
+ const windowSwitchAccessory = accessories.filter(
1237
+ (acc) => acc && acc.displayName === acc.context.config.homeName + ' Open Window'
1238
+ );
1269
1239
 
1270
- let state = zone.openWindowEnabled ? true : false;
1240
+ if (windowContactAccessory.length) {
1241
+ windowContactAccessory.forEach((acc) => {
1242
+ if (acc.displayName.includes(zone.name)) {
1243
+ Logger.debug("Update window contact sensor.");
1244
+
1245
+ let serviceBattery = acc.getService(api.hap.Service.BatteryService);
1246
+ let characteristicBattery = api.hap.Characteristic.BatteryLevel;
1271
1247
 
1272
- service.getCharacteristic(characteristic).updateValue(state);
1248
+ if (serviceBattery && !isNaN(battery)) {
1249
+ serviceBattery.getCharacteristic(characteristicBattery).updateValue(battery);
1273
1250
  }
1274
- });
1275
- }
1276
1251
 
1277
- if (zoneState.setting.type === 'HEATING') {
1278
- //CentralSwitch
1279
- if (zoneState.overlayType === null) inAutoMode += 1;
1252
+ let service = acc.getService(api.hap.Service.ContactSensor);
1253
+ let characteristic = api.hap.Characteristic.ContactSensorState;
1280
1254
 
1281
- if (zoneState.overlayType !== null && zoneState.setting.power === 'OFF') inOffMode += 1;
1255
+ let state = zoneState.openWindow || zoneState.openWindowDetected ? 1 : 0;
1282
1256
 
1283
- if (zoneState.overlayType !== null && zoneState.setting.power === 'ON' && zoneState.overlay.termination)
1284
- inManualMode += 1;
1285
- }
1257
+ service.getCharacteristic(characteristic).updateValue(state);
1258
+ }
1259
+ });
1286
1260
  }
1287
1261
 
1288
- //CentralSwitch
1289
- const centralSwitchAccessory = accessories.filter(
1290
- (acc) => acc && acc.displayName === acc.context.config.homeName + ' Central Switch'
1291
- );
1262
+ if (windowSwitchAccessory.length) {
1263
+ windowSwitchAccessory[0].services.forEach((switchService) => {
1264
+ if (switchService.subtype && switchService.subtype.includes(zone.name)) {
1265
+ Logger.debug("Update window switch accessory.");
1292
1266
 
1293
- if (centralSwitchAccessory.length) {
1294
- centralSwitchAccessory[0].services.forEach((service) => {
1295
- if (service.subtype === 'Central') {
1296
- let serviceSwitch = centralSwitchAccessory[0].getServiceById(api.hap.Service.Switch, service.subtype);
1297
- let characteristicOn = api.hap.Characteristic.On;
1298
- let characteristicAuto = api.hap.Characteristic.AutoThermostats;
1299
- let characteristicOff = api.hap.Characteristic.OfflineThermostats;
1300
- let characteristicManual = api.hap.Characteristic.ManualThermostats;
1267
+ let service = windowSwitchAccessory[0].getServiceById(api.hap.Service.Switch, switchService.subtype);
1268
+ let characteristic = api.hap.Characteristic.On;
1301
1269
 
1302
- let state = (inManualMode || inAutoMode) !== 0;
1270
+ let state = zone.openWindowEnabled ? true : false;
1303
1271
 
1304
- serviceSwitch.getCharacteristic(characteristicAuto).updateValue(inAutoMode);
1272
+ service.getCharacteristic(characteristic).updateValue(state);
1273
+ }
1274
+ });
1275
+ }
1305
1276
 
1306
- serviceSwitch.getCharacteristic(characteristicManual).updateValue(inManualMode);
1277
+ if (zoneState.setting.type === 'HEATING') {
1278
+ //CentralSwitch
1279
+ if (zoneState.overlayType === null) inAutoMode += 1;
1307
1280
 
1308
- serviceSwitch.getCharacteristic(characteristicOff).updateValue(inOffMode);
1281
+ if (zoneState.overlayType !== null && zoneState.setting.power === 'OFF') inOffMode += 1;
1309
1282
 
1310
- serviceSwitch.getCharacteristic(characteristicOn).updateValue(state);
1311
- }
1312
- });
1283
+ if (zoneState.overlayType !== null && zoneState.setting.power === 'ON' && zoneState.overlay.termination)
1284
+ inManualMode += 1;
1313
1285
  }
1314
1286
  }
1287
+
1288
+ //CentralSwitch
1289
+ const centralSwitchAccessory = accessories.filter(
1290
+ (acc) => acc && acc.displayName === acc.context.config.homeName + ' Central Switch'
1291
+ );
1292
+
1293
+ if (centralSwitchAccessory.length) {
1294
+ centralSwitchAccessory[0].services.forEach((service) => {
1295
+ if (service.subtype === 'Central') {
1296
+ let serviceSwitch = centralSwitchAccessory[0].getServiceById(api.hap.Service.Switch, service.subtype);
1297
+ let characteristicOn = api.hap.Characteristic.On;
1298
+ let characteristicAuto = api.hap.Characteristic.AutoThermostats;
1299
+ let characteristicOff = api.hap.Characteristic.OfflineThermostats;
1300
+ let characteristicManual = api.hap.Characteristic.ManualThermostats;
1301
+
1302
+ let state = (inManualMode || inAutoMode) !== 0;
1303
+
1304
+ Logger.debug(`Update central switch:`, { inAutoMode: inAutoMode, inManualMode: inManualMode, inOffMode: inOffMode, state: state });
1305
+
1306
+ serviceSwitch.getCharacteristic(characteristicAuto).updateValue(inAutoMode);
1307
+ serviceSwitch.getCharacteristic(characteristicManual).updateValue(inManualMode);
1308
+ serviceSwitch.getCharacteristic(characteristicOff).updateValue(inOffMode);
1309
+ serviceSwitch.getCharacteristic(characteristicOn).updateValue(state);
1310
+ }
1311
+ });
1312
+ }
1315
1313
  return zoneStates;
1316
1314
  }
1317
1315
 
1318
1316
  async function updateMobileDevices() {
1319
- if (!settingState) {
1320
- Logger.debug('Polling MobileDevices...', config.homeName);
1317
+ if (settingState) return;
1321
1318
 
1322
- const mobileDevices = await tado.getMobileDevices(config.homeId);
1319
+ Logger.debug('Polling MobileDevices...', config.homeName);
1323
1320
 
1324
- const userAccessories = accessories.filter(
1325
- (user) =>
1326
- user &&
1327
- user.context.config.subtype.includes('presence') &&
1328
- user.displayName !== user.context.config.homeName + ' Anyone'
1329
- );
1321
+ const mobileDevices = await tado.getMobileDevices(config.homeId);
1330
1322
 
1331
- const anyone = accessories.filter(
1332
- (user) =>
1333
- user &&
1334
- user.context.config.subtype.includes('presence') &&
1335
- user.displayName === user.context.config.homeName + ' Anyone'
1336
- );
1323
+ const userAccessories = accessories.filter(
1324
+ (user) =>
1325
+ user &&
1326
+ user.context.config.subtype.includes('presence') &&
1327
+ user.displayName !== user.context.config.homeName + ' Anyone'
1328
+ );
1337
1329
 
1338
- let activeUser = 0;
1330
+ const anyone = accessories.filter(
1331
+ (user) =>
1332
+ user &&
1333
+ user.context.config.subtype.includes('presence') &&
1334
+ user.displayName === user.context.config.homeName + ' Anyone'
1335
+ );
1339
1336
 
1340
- mobileDevices.forEach((device) => {
1341
- userAccessories.forEach((acc) => {
1342
- if (acc.context.config.homeName + ' ' + device.name === acc.displayName) {
1343
- let atHome = device.location && device.location.atHome ? 1 : 0;
1337
+ let activeUser = 0;
1344
1338
 
1345
- if (atHome) activeUser += 1;
1339
+ mobileDevices.forEach((device) => {
1340
+ userAccessories.forEach((acc) => {
1341
+ if (acc.context.config.homeName + ' ' + device.name === acc.displayName) {
1342
+ let atHome = device.location && device.location.atHome ? 1 : 0;
1346
1343
 
1347
- let service =
1348
- acc.getService(api.hap.Service.MotionSensor) || acc.getService(api.hap.Service.OccupancySensor);
1344
+ if (atHome) activeUser += 1;
1349
1345
 
1350
- let characteristic = service.testCharacteristic(api.hap.Characteristic.MotionDetected)
1351
- ? api.hap.Characteristic.MotionDetected
1352
- : api.hap.Characteristic.OccupancyDetected;
1346
+ let service =
1347
+ acc.getService(api.hap.Service.MotionSensor) || acc.getService(api.hap.Service.OccupancySensor);
1353
1348
 
1354
- service.getCharacteristic(characteristic).updateValue(atHome);
1355
- }
1356
- });
1349
+ let characteristic = service.testCharacteristic(api.hap.Characteristic.MotionDetected)
1350
+ ? api.hap.Characteristic.MotionDetected
1351
+ : api.hap.Characteristic.OccupancyDetected;
1352
+
1353
+ service.getCharacteristic(characteristic).updateValue(atHome);
1354
+ }
1357
1355
  });
1356
+ });
1358
1357
 
1359
- if (anyone.length) {
1360
- let service =
1361
- anyone[0].getService(api.hap.Service.MotionSensor) || anyone[0].getService(api.hap.Service.OccupancySensor);
1358
+ if (anyone.length) {
1359
+ let service =
1360
+ anyone[0].getService(api.hap.Service.MotionSensor) || anyone[0].getService(api.hap.Service.OccupancySensor);
1362
1361
 
1363
- let characteristic = service.testCharacteristic(api.hap.Characteristic.MotionDetected)
1364
- ? api.hap.Characteristic.MotionDetected
1365
- : api.hap.Characteristic.OccupancyDetected;
1362
+ let characteristic = service.testCharacteristic(api.hap.Characteristic.MotionDetected)
1363
+ ? api.hap.Characteristic.MotionDetected
1364
+ : api.hap.Characteristic.OccupancyDetected;
1366
1365
 
1367
- service.getCharacteristic(characteristic).updateValue(activeUser ? 1 : 0);
1368
- }
1366
+ service.getCharacteristic(characteristic).updateValue(activeUser ? 1 : 0);
1369
1367
  }
1370
-
1371
- return;
1372
1368
  }
1373
1369
 
1374
1370
  async function updateWeather() {
1375
- if (!settingState) {
1376
- const weatherTemperatureAccessory = accessories.filter(
1377
- (acc) => acc && acc.displayName === acc.context.config.homeName + ' Weather'
1378
- );
1371
+ if (settingState) return;
1379
1372
 
1380
- const solarIntensityAccessory = accessories.filter(
1381
- (acc) => acc && acc.displayName === acc.context.config.homeName + ' Solar Intensity'
1382
- );
1373
+ const weatherTemperatureAccessory = accessories.filter(
1374
+ (acc) => acc && acc.displayName === acc.context.config.homeName + ' Weather'
1375
+ );
1383
1376
 
1384
- if (weatherTemperatureAccessory.length || solarIntensityAccessory.length) {
1385
- Logger.debug('Polling Weather...', config.homeName);
1377
+ const solarIntensityAccessory = accessories.filter(
1378
+ (acc) => acc && acc.displayName === acc.context.config.homeName + ' Solar Intensity'
1379
+ );
1386
1380
 
1387
- const weather = await tado.getWeather(config.homeId);
1381
+ if (weatherTemperatureAccessory.length || solarIntensityAccessory.length) {
1382
+ Logger.debug('Polling Weather...', config.homeName);
1388
1383
 
1389
- if (weatherTemperatureAccessory.length && weather.outsideTemperature) {
1390
- let tempUnit = config.temperatureUnit;
1391
- let service = weatherTemperatureAccessory[0].getService(api.hap.Service.TemperatureSensor);
1392
- let characteristic = api.hap.Characteristic.CurrentTemperature;
1384
+ const weather = await tado.getWeather(config.homeId);
1393
1385
 
1394
- let temp =
1395
- tempUnit === 'FAHRENHEIT' ? weather.outsideTemperature.fahrenheit : weather.outsideTemperature.celsius;
1386
+ if (weatherTemperatureAccessory.length && weather.outsideTemperature) {
1387
+ let tempUnit = config.temperatureUnit;
1388
+ let service = weatherTemperatureAccessory[0].getService(api.hap.Service.TemperatureSensor);
1389
+ let characteristic = api.hap.Characteristic.CurrentTemperature;
1396
1390
 
1397
- service.getCharacteristic(characteristic).updateValue(temp);
1398
- }
1391
+ let temp =
1392
+ tempUnit === 'FAHRENHEIT' ? weather.outsideTemperature.fahrenheit : weather.outsideTemperature.celsius;
1399
1393
 
1400
- if (solarIntensityAccessory.length && weather.solarIntensity) {
1401
- let state = weather.solarIntensity.percentage !== 0;
1402
- let brightness = weather.solarIntensity.percentage;
1394
+ service.getCharacteristic(characteristic).updateValue(temp);
1395
+ }
1403
1396
 
1404
- solarIntensityAccessory[0].context.lightBulbState = state;
1405
- solarIntensityAccessory[0].context.lightBulbBrightness = brightness;
1397
+ if (solarIntensityAccessory.length && weather.solarIntensity) {
1398
+ let state = weather.solarIntensity.percentage !== 0;
1399
+ let brightness = weather.solarIntensity.percentage;
1406
1400
 
1407
- let serviceLightbulb = solarIntensityAccessory[0].getService(api.hap.Service.Lightbulb);
1408
- let serviceLightsensor = solarIntensityAccessory[0].getService(api.hap.Service.LightSensor);
1401
+ solarIntensityAccessory[0].context.lightBulbState = state;
1402
+ solarIntensityAccessory[0].context.lightBulbBrightness = brightness;
1409
1403
 
1410
- if (serviceLightbulb) {
1411
- let characteristicOn = api.hap.Characteristic.On;
1412
- let characteristicBrightness = api.hap.Characteristic.Brightness;
1404
+ let serviceLightbulb = solarIntensityAccessory[0].getService(api.hap.Service.Lightbulb);
1405
+ let serviceLightsensor = solarIntensityAccessory[0].getService(api.hap.Service.LightSensor);
1413
1406
 
1414
- serviceLightbulb.getCharacteristic(characteristicOn).updateValue(state);
1407
+ if (serviceLightbulb) {
1408
+ let characteristicOn = api.hap.Characteristic.On;
1409
+ let characteristicBrightness = api.hap.Characteristic.Brightness;
1415
1410
 
1416
- serviceLightbulb.getCharacteristic(characteristicBrightness).updateValue(brightness);
1417
- } else {
1418
- let characteristicLux = api.hap.Characteristic.CurrentAmbientLightLevel;
1411
+ serviceLightbulb.getCharacteristic(characteristicOn).updateValue(state);
1419
1412
 
1420
- serviceLightsensor
1421
- .getCharacteristic(characteristicLux)
1422
- .updateValue(brightness ? brightness * 1000 : 0.0001);
1423
- }
1413
+ serviceLightbulb.getCharacteristic(characteristicBrightness).updateValue(brightness);
1414
+ } else {
1415
+ let characteristicLux = api.hap.Characteristic.CurrentAmbientLightLevel;
1416
+
1417
+ serviceLightsensor
1418
+ .getCharacteristic(characteristicLux)
1419
+ .updateValue(brightness ? brightness * 1000 : 0.0001);
1424
1420
  }
1425
1421
  }
1426
1422
  }
1427
-
1428
- return;
1429
1423
  }
1430
1424
 
1431
1425
  async function updatePresence() {
1432
- if (!settingState) {
1433
- const presenceLockAccessory = accessories.filter(
1434
- (acc) => acc && acc.displayName === acc.context.config.homeName + ' Presence Lock'
1435
- );
1426
+ if (settingState) return;
1436
1427
 
1437
- if (presenceLockAccessory.length) {
1438
- Logger.debug('Polling PresenceLock...', config.homeName);
1428
+ const presenceLockAccessory = accessories.filter(
1429
+ (acc) => acc && acc.displayName === acc.context.config.homeName + ' Presence Lock'
1430
+ );
1439
1431
 
1440
- const presenceLock = await tado.getState(config.homeId);
1432
+ if (presenceLockAccessory.length) {
1433
+ Logger.debug('Polling PresenceLock...', config.homeName);
1441
1434
 
1442
- /*
1443
- 0: Home | true
1444
- 1: Away | true
1445
- 3: Off | false
1446
- */
1435
+ const presenceLock = await tado.getState(config.homeId);
1447
1436
 
1448
- let state = presenceLock.presenceLocked ? (presenceLock.presence === 'AWAY' ? 1 : 0) : 3;
1437
+ /*
1438
+ 0: Home | true
1439
+ 1: Away | true
1440
+ 3: Off | false
1441
+ */
1449
1442
 
1450
- let serviceSecurity = presenceLockAccessory[0].getService(api.hap.Service.SecuritySystem);
1451
- let serviceHomeSwitch = presenceLockAccessory[0].getServiceById(api.hap.Service.Switch, 'HomeSwitch');
1452
- let serviceAwaySwitch = presenceLockAccessory[0].getServiceById(api.hap.Service.Switch, 'AwaySwitch');
1443
+ let state = presenceLock.presenceLocked ? (presenceLock.presence === 'AWAY' ? 1 : 0) : 3;
1453
1444
 
1454
- if (serviceSecurity) {
1455
- let characteristicCurrent = api.hap.Characteristic.SecuritySystemCurrentState;
1456
- let characteristicTarget = api.hap.Characteristic.SecuritySystemTargetState;
1445
+ let serviceSecurity = presenceLockAccessory[0].getService(api.hap.Service.SecuritySystem);
1446
+ let serviceHomeSwitch = presenceLockAccessory[0].getServiceById(api.hap.Service.Switch, 'HomeSwitch');
1447
+ let serviceAwaySwitch = presenceLockAccessory[0].getServiceById(api.hap.Service.Switch, 'AwaySwitch');
1457
1448
 
1458
- serviceSecurity.getCharacteristic(characteristicCurrent).updateValue(state);
1449
+ if (serviceSecurity) {
1450
+ let characteristicCurrent = api.hap.Characteristic.SecuritySystemCurrentState;
1451
+ let characteristicTarget = api.hap.Characteristic.SecuritySystemTargetState;
1459
1452
 
1460
- serviceSecurity.getCharacteristic(characteristicTarget).updateValue(state);
1461
- } else if (serviceHomeSwitch || serviceAwaySwitch) {
1462
- let characteristicOn = api.hap.Characteristic.On;
1453
+ serviceSecurity.getCharacteristic(characteristicCurrent).updateValue(state);
1463
1454
 
1464
- let homeState = !state ? true : false;
1455
+ serviceSecurity.getCharacteristic(characteristicTarget).updateValue(state);
1456
+ } else if (serviceHomeSwitch || serviceAwaySwitch) {
1457
+ let characteristicOn = api.hap.Characteristic.On;
1465
1458
 
1466
- let awayState = state === 1 ? true : false;
1459
+ let homeState = !state ? true : false;
1467
1460
 
1468
- serviceAwaySwitch.getCharacteristic(characteristicOn).updateValue(awayState);
1461
+ let awayState = state === 1 ? true : false;
1469
1462
 
1470
- serviceHomeSwitch.getCharacteristic(characteristicOn).updateValue(homeState);
1471
- }
1463
+ serviceAwaySwitch.getCharacteristic(characteristicOn).updateValue(awayState);
1464
+
1465
+ serviceHomeSwitch.getCharacteristic(characteristicOn).updateValue(homeState);
1472
1466
  }
1473
1467
  }
1474
1468
  }
1475
1469
 
1476
1470
  async function updateRunningTime() {
1477
- if (!settingState) {
1478
- const centralSwitchAccessory = accessories.filter(
1479
- (acc) => acc && acc.displayName === acc.context.config.homeName + ' Central Switch'
1480
- );
1471
+ if (settingState) return;
1481
1472
 
1482
- if (centralSwitchAccessory.length) {
1483
- Logger.debug('Polling RunningTime...', config.homeName);
1473
+ const centralSwitchAccessory = accessories.filter(
1474
+ (acc) => acc && acc.displayName === acc.context.config.homeName + ' Central Switch'
1475
+ );
1484
1476
 
1485
- let periods = ['days', 'months', 'years'];
1477
+ if (centralSwitchAccessory.length) {
1478
+ Logger.debug('Polling RunningTime...', config.homeName);
1486
1479
 
1487
- for (const period of periods) {
1488
- let fromDate =
1489
- period === 'days'
1490
- ? moment().format('YYYY-MM-DD')
1491
- : period === 'months'
1492
- ? moment().subtract(1, 'days').subtract(1, period).format('YYYY-MM-DD')
1493
- : moment().add(1, 'months').startOf('month').subtract(1, period).format('YYYY-MM-DD');
1480
+ let periods = ['days', 'months', 'years'];
1494
1481
 
1495
- let toDate = period === 'years' ? moment().format('YYYY-MM-DD') : false;
1482
+ for (const period of periods) {
1483
+ let fromDate =
1484
+ period === 'days'
1485
+ ? moment().format('YYYY-MM-DD')
1486
+ : period === 'months'
1487
+ ? moment().subtract(1, 'days').subtract(1, period).format('YYYY-MM-DD')
1488
+ : moment().add(1, 'months').startOf('month').subtract(1, period).format('YYYY-MM-DD');
1496
1489
 
1497
- let time = period.substring(0, period.length - 1);
1490
+ let toDate = period === 'years' ? moment().format('YYYY-MM-DD') : false;
1498
1491
 
1499
- const runningTime = await tado.getRunningTime(config.homeId, time, fromDate, toDate);
1492
+ let time = period.substring(0, period.length - 1);
1500
1493
 
1501
- if (runningTime && runningTime.summary) {
1502
- let summaryInHours = runningTime.summary.totalRunningTimeInSeconds / 3600;
1494
+ const runningTime = await tado.getRunningTime(config.homeId, time, fromDate, toDate);
1503
1495
 
1504
- let serviceSwitch = centralSwitchAccessory[0].getServiceById(api.hap.Service.Switch, 'Central');
1505
- let characteristic =
1506
- period === 'years'
1507
- ? api.hap.Characteristic.OverallHeatYear
1508
- : period === 'months'
1509
- ? api.hap.Characteristic.OverallHeatMonth
1510
- : api.hap.Characteristic.OverallHeatDay;
1496
+ if (runningTime && runningTime.summary) {
1497
+ let summaryInHours = runningTime.summary.totalRunningTimeInSeconds / 3600;
1511
1498
 
1512
- serviceSwitch.getCharacteristic(characteristic).updateValue(summaryInHours);
1513
- }
1499
+ let serviceSwitch = centralSwitchAccessory[0].getServiceById(api.hap.Service.Switch, 'Central');
1500
+ let characteristic =
1501
+ period === 'years'
1502
+ ? api.hap.Characteristic.OverallHeatYear
1503
+ : period === 'months'
1504
+ ? api.hap.Characteristic.OverallHeatMonth
1505
+ : api.hap.Characteristic.OverallHeatDay;
1514
1506
 
1515
- await timeout(500);
1507
+ serviceSwitch.getCharacteristic(characteristic).updateValue(summaryInHours);
1516
1508
  }
1509
+
1510
+ await timeout(500);
1517
1511
  }
1518
1512
  }
1519
-
1520
- return;
1521
1513
  }
1522
1514
 
1523
1515
  async function updateDevices() {
1524
- if (!settingState) {
1525
- Logger.debug('Polling Devices...', config.homeName);
1516
+ if (settingState) return;
1526
1517
 
1527
- const devices = await tado.getDevices(config.homeId);
1518
+ Logger.debug('Polling Devices...', config.homeName);
1528
1519
 
1529
- const childLockAccessories = accessories.filter(
1530
- (acc) => acc && acc.context.config.subtype === 'extra-childswitch'
1531
- );
1520
+ const devices = await tado.getDevices(config.homeId);
1532
1521
 
1533
- devices.forEach((device) => {
1534
- childLockAccessories[0].services.forEach((service) => {
1535
- if (device.serialNo === service.subtype) {
1536
- let serviceChildLock = childLockAccessories[0].getServiceById(api.hap.Service.Switch, service.subtype);
1537
- let characteristic = api.hap.Characteristic.On;
1522
+ const childLockAccessories = accessories.filter(
1523
+ (acc) => acc && acc.context.config.subtype === 'extra-childswitch'
1524
+ );
1538
1525
 
1539
- let childLockEnabled = device.childLockEnabled || false;
1526
+ devices.forEach((device) => {
1527
+ childLockAccessories[0].services.forEach((service) => {
1528
+ if (device.serialNo === service.subtype) {
1529
+ let serviceChildLock = childLockAccessories[0].getServiceById(api.hap.Service.Switch, service.subtype);
1530
+ let characteristic = api.hap.Characteristic.On;
1540
1531
 
1541
- serviceChildLock.getCharacteristic(characteristic).updateValue(childLockEnabled);
1542
- }
1543
- });
1544
- });
1545
- }
1532
+ let childLockEnabled = device.childLockEnabled || false;
1546
1533
 
1547
- return;
1534
+ serviceChildLock.getCharacteristic(characteristic).updateValue(childLockEnabled);
1535
+ }
1536
+ });
1537
+ });
1548
1538
  }
1549
1539
 
1550
1540
  function errorHandler(err) {