@homebridge-plugins/homebridge-tado 9.3.0 → 9.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ # v9.3.2 - 2026-06-21
4
+ - Fix: Add a defensive `CurrentTemperature` fallback for `HOT_WATER` HeaterCooler accessories when tado does not provide `sensorDataPoints.insideTemperature` (#169)
5
+
6
+ # v9.3.1 - 2026-06-19
7
+ - Fix: Preserve previous update buffer behaviour for default `preferSiriTemperature` handling while keeping the `HOT_WATER` range safeguards (#169)
8
+ - Fix: Improve HeaterCooler threshold value correction during startup
9
+
3
10
  # v9.3.0 - 2026-06-18
4
11
  - Fix: Treat tado zone id `0` as a valid zone id when resolving and updating configured zones (#169)
5
12
  - Fix: Resolve missing `HOT_WATER` zone ids for temperature-controlled boiler `HeaterCooler` accessories before sending overlays (#169)
@@ -215,9 +222,9 @@
215
222
  ## v6.0.9 - 2021-03-22
216
223
  - Added "Dummy Switch" option to Central Switch
217
224
  - Added new accessory type option (LightSensor) to Solar Intensity Accessory
218
- - Added new mode (CUSTOM) to HOT_WATER devices
225
+ - Added new mode (CUSTOM) to `HOT_WATER` devices
219
226
  - Fixed current state of HeaterCooler if temperature is reached
220
- - Fixed AUTO mode for HOT_WATER devices
227
+ - Fixed AUTO mode for `HOT_WATER` devices
221
228
  - Bugfixes
222
229
  - Bump deps
223
230
 
@@ -229,7 +236,7 @@
229
236
 
230
237
  ## v6.0.6 - 2021-03-16
231
238
  - Added minValue, maxValue, minStep options to config
232
- - Fixed target temperature for HOT_WATER if power = "ON"
239
+ - Fixed target temperature for `HOT_WATER` if power = "ON"
233
240
  - Other little bugfixes & improvements
234
241
 
235
242
  ## v6.0.5 - 2021-03-16
@@ -247,7 +254,7 @@
247
254
 
248
255
  ## v6.0.1 - 2021-03-15
249
256
  - Fixed a bug with faucet accessory appearing as air quality sensor
250
- - Fixed a bug for HOT_WATER devices without temperature support
257
+ - Fixed a bug for `HOT_WATER` devices without temperature support
251
258
  - Improvements
252
259
 
253
260
  **Note:**
@@ -256,7 +263,7 @@ Hot water devices show 0° when they are first started in Apple Home if they are
256
263
 
257
264
  **IMPORTANT:**
258
265
 
259
- If you previously used your "HOT_WATER" device/zone as a faucet, then disable the zone after the update and restart Homebridge pls. After the restart, you can enable the zone with the faucet again.
266
+ If you previously used your "`HOT_WATER`" device/zone as a faucet, then disable the zone after the update and restart Homebridge pls. After the restart, you can enable the zone with the faucet again.
260
267
 
261
268
  ## v6.0.0 - 2021-03-14
262
269
  **<u>NOTE:</u>** Updating from **<= v5.x** to **v6.x** will crash your homebridge, please **REMOVE** the old version first and check also the new [example-config.json](https://github.com/homebridge-plugins/homebridge-tado/blob/latest/example-config.json)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebridge-plugins/homebridge-tado",
3
- "version": "9.3.0",
3
+ "version": "9.3.2",
4
4
  "description": "Homebridge plugin for controlling tado° devices.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,6 +1,6 @@
1
1
  import Logger from '../helper/logger.js';
2
2
  import moment from 'moment';
3
- import { TadoUpdateBuffer } from '../helper/update-buffer.js'
3
+ import { TadoUpdateBuffer } from '../helper/update-buffer.js';
4
4
 
5
5
  const timeout = (ms) => new Promise((res) => setTimeout(res, ms));
6
6
 
@@ -255,12 +255,11 @@ export default class HeaterCoolerAccessory {
255
255
  });
256
256
 
257
257
  let heatingThresholdValue = Number(heatingThreshold.value);
258
-
259
- if (!Number.isFinite(heatingThresholdValue) || heatingThresholdValue < minValue)
258
+ if (!Number.isFinite(heatingThresholdValue) || heatingThresholdValue < minValue) {
260
259
  heatingThreshold.updateValue(minValue);
261
-
262
- if (Number.isFinite(heatingThresholdValue) && heatingThresholdValue > maxValue)
260
+ } else if (heatingThresholdValue > maxValue) {
263
261
  heatingThreshold.updateValue(maxValue);
262
+ }
264
263
 
265
264
  if (this.accessory.context.config.type === 'HEATING') {
266
265
  const coolingThreshold = service.getCharacteristic(this.api.hap.Characteristic.CoolingThresholdTemperature);
@@ -272,12 +271,11 @@ export default class HeaterCoolerAccessory {
272
271
  });
273
272
 
274
273
  let coolingThresholdValue = Number(coolingThreshold.value);
275
-
276
- if (!Number.isFinite(coolingThresholdValue) || coolingThresholdValue < minValue)
274
+ if (!Number.isFinite(coolingThresholdValue) || coolingThresholdValue < minValue) {
277
275
  coolingThreshold.updateValue(minValue);
278
-
279
- if (Number.isFinite(coolingThresholdValue) && coolingThresholdValue > maxValue)
276
+ } else if (coolingThresholdValue > maxValue) {
280
277
  coolingThreshold.updateValue(maxValue);
278
+ }
281
279
  }
282
280
 
283
281
  if (!service.testCharacteristic(this.api.hap.Characteristic.ValvePosition))
@@ -129,6 +129,14 @@ export default (api, accessories, config, tado, telegram) => {
129
129
  return { min, max };
130
130
  }
131
131
 
132
+ function _getTemperatureValue(temperature) {
133
+ if (!temperature) return undefined;
134
+
135
+ return config.temperatureUnit === 'FAHRENHEIT'
136
+ ? temperature.fahrenheit
137
+ : temperature.celsius;
138
+ }
139
+
132
140
  function _normalizeTemperatureForAccessory(accessory, temp) {
133
141
  if (temp === null || temp === undefined) return temp;
134
142
 
@@ -1091,16 +1099,10 @@ export default (api, accessories, config, tado, telegram) => {
1091
1099
 
1092
1100
  //HEATING
1093
1101
  if (zoneState.sensorDataPoints.insideTemperature) {
1094
- currentTemp =
1095
- config.temperatureUnit === 'FAHRENHEIT'
1096
- ? zoneState.sensorDataPoints.insideTemperature.fahrenheit
1097
- : zoneState.sensorDataPoints.insideTemperature.celsius;
1102
+ currentTemp = _getTemperatureValue(zoneState.sensorDataPoints.insideTemperature);
1098
1103
 
1099
1104
  if (zoneState.setting.power === 'ON') {
1100
- targetTemp =
1101
- config.temperatureUnit === 'FAHRENHEIT'
1102
- ? zoneState.setting.temperature.fahrenheit
1103
- : zoneState.setting.temperature.celsius;
1105
+ targetTemp = _getTemperatureValue(zoneState.setting.temperature);
1104
1106
 
1105
1107
  tempEqual = Math.round(currentTemp) === Math.round(targetTemp);
1106
1108
 
@@ -1230,28 +1232,22 @@ export default (api, accessories, config, tado, telegram) => {
1230
1232
  // Non-HEATING zones (AIR_CONDITIONING, HOT_WATER, etc.)
1231
1233
  battery = zone.battery === 'NORMAL' ? 100 : 10;
1232
1234
 
1233
- if (zoneState.sensorDataPoints.humidity) {
1235
+ if (zoneState.sensorDataPoints && zoneState.sensorDataPoints.humidity) {
1234
1236
  humidity = zoneState.sensorDataPoints.humidity.percentage;
1235
1237
  }
1236
1238
 
1237
- // Get current temperature from sensor data (same as HEATING zones)
1238
- if (zoneState.sensorDataPoints.insideTemperature) {
1239
- currentTemp =
1240
- config.temperatureUnit === 'FAHRENHEIT'
1241
- ? zoneState.sensorDataPoints.insideTemperature.fahrenheit
1242
- : zoneState.sensorDataPoints.insideTemperature.celsius;
1239
+ // Get current temperature from sensor data if tado provides it.
1240
+ // HOT_WATER zones often do not expose sensorDataPoints.insideTemperature;
1241
+ // the HeaterCooler service applies a fallback below when needed.
1242
+ if (zoneState.sensorDataPoints && zoneState.sensorDataPoints.insideTemperature) {
1243
+ currentTemp = _getTemperatureValue(zoneState.sensorDataPoints.insideTemperature);
1243
1244
  }
1244
1245
 
1245
1246
  if (zoneState.setting.power === 'ON') {
1246
1247
  active = 1;
1247
1248
 
1248
1249
  // Get target temperature from setting
1249
- targetTemp =
1250
- zoneState.setting.temperature !== null && zoneState.setting.temperature
1251
- ? config.temperatureUnit === 'FAHRENHEIT'
1252
- ? zoneState.setting.temperature.fahrenheit
1253
- : zoneState.setting.temperature.celsius
1254
- : undefined;
1250
+ targetTemp = _getTemperatureValue(zoneState.setting.temperature);
1255
1251
 
1256
1252
  // Enhanced AC state handling
1257
1253
  if (zone.type === 'AIR_CONDITIONING') {
@@ -1309,11 +1305,30 @@ export default (api, accessories, config, tado, telegram) => {
1309
1305
 
1310
1306
  service.getCharacteristic(characteristicTargetState).updateValue(targetState);
1311
1307
 
1312
- // Set current temperature from sensor data
1313
- if (!isNaN(currentTemp) || acc.context.currentTemp) {
1314
- if (!isNaN(currentTemp)) acc.context.currentTemp = currentTemp; //store current temp in config
1308
+ // Set current temperature from sensor data when available.
1309
+ // HOT_WATER zones can have no sensorDataPoints.insideTemperature in the tado API.
1310
+ // In that case, keep the last known value; if none exists, fall back to the
1311
+ // configured hot-water target temperature and finally the configured minimum.
1312
+ let homeKitCurrentTemp = currentTemp;
1313
+ const isValidTemperature = (value) => value !== undefined && value !== null && !isNaN(value);
1314
+
1315
+ if (zone.type === 'HOT_WATER' && !isValidTemperature(homeKitCurrentTemp)) {
1316
+ if (isValidTemperature(acc.context.currentTemp)) {
1317
+ homeKitCurrentTemp = acc.context.currentTemp;
1318
+ } else if (isValidTemperature(targetTemp)) {
1319
+ homeKitCurrentTemp = targetTemp;
1320
+ } else if (isValidTemperature(zone.minValue)) {
1321
+ homeKitCurrentTemp = zone.minValue;
1322
+ } else if (acc.context.config && isValidTemperature(acc.context.config.minValue)) {
1323
+ homeKitCurrentTemp = acc.context.config.minValue;
1324
+ } else {
1325
+ homeKitCurrentTemp = 30;
1326
+ }
1327
+ }
1315
1328
 
1316
- service.getCharacteristic(characteristicCurrentTemp).updateValue(acc.context.currentTemp);
1329
+ if (!isNaN(homeKitCurrentTemp)) {
1330
+ acc.context.currentTemp = homeKitCurrentTemp; //store current temp in config
1331
+ service.getCharacteristic(characteristicCurrentTemp).updateValue(homeKitCurrentTemp);
1317
1332
  }
1318
1333
 
1319
1334
  // Set target temperature for both heating and cooling
@@ -1569,12 +1584,10 @@ export default (api, accessories, config, tado, telegram) => {
1569
1584
  const weather = await tado.getWeather(config.homeId);
1570
1585
 
1571
1586
  if (weatherTemperatureAccessory.length && weather.outsideTemperature) {
1572
- let tempUnit = config.temperatureUnit;
1573
1587
  let service = weatherTemperatureAccessory[0].getService(api.hap.Service.TemperatureSensor);
1574
1588
  let characteristic = api.hap.Characteristic.CurrentTemperature;
1575
1589
 
1576
- let temp =
1577
- tempUnit === 'FAHRENHEIT' ? weather.outsideTemperature.fahrenheit : weather.outsideTemperature.celsius;
1590
+ let temp = _getTemperatureValue(weather.outsideTemperature);
1578
1591
 
1579
1592
  service.getCharacteristic(characteristic).updateValue(temp);
1580
1593
  }
@@ -54,7 +54,7 @@ export class TadoUpdateBuffer {
54
54
  const tempSet = temp !== null;
55
55
  this.pendingState = null;
56
56
  this.pendingTemperature = null;
57
- if (tempSet && !siriAutoTemperature) this.lastTemperature = temp;
57
+ if (tempSet && (!siriAutoTemperature || !this.preferSiriTemperature)) this.lastTemperature = temp;
58
58
 
59
59
  //Siri temperature heuristic
60
60
  if (this.preferSiriTemperature && state === 3 && tempSet) {