Skip to content

Commit 1c46a08

Browse files
Revert cloud temperature sync — keep humidity-only
Cloud-sync was injecting temperature values with different precision than local HomeKit reads, causing 171 spurious blips across 10 zones over 33 hours (deltas up to 1.98°C). Always-on HomeKit polling (60-120s) already provides timely local temperature for silent devices like Smart AC Control V3+, making the cloud fallback unnecessary. Reverts the temperature portion of e90907e; humidity sync retained.
1 parent c526480 commit 1c46a08

2 files changed

Lines changed: 21 additions & 31 deletions

File tree

tado_local/sync.py

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -293,12 +293,13 @@ def sync_zones(self, zones_data: List[Dict[str, Any]], home_id: int) -> bool:
293293

294294
def sync_zone_states_data(self, zone_states_data: List[Dict[str, Any]], home_id: int, tado_api: TadoLocalAPI) -> bool:
295295
"""
296-
Sync zone states from Tado Cloud API to update temperature and humidity.
296+
Sync zone states from Tado Cloud API to update humidity.
297297
298-
The zoneStates endpoint provides authoritative sensor data that supplements
299-
HomeKit readings. Standalone accessories (e.g. Smart AC Control V3+) may
300-
not fire HomeKit temperature events reliably, so cloud values act as a
301-
correction layer.
298+
Tado devices only fire HomeKit humidity events when the delta exceeds
299+
~5%, so cloud values fill the gap between those infrequent updates.
300+
Temperature is intentionally excluded here -- always-on HomeKit polling
301+
(every 60-120s) provides timely local reads without the precision
302+
mismatch that cloud values would introduce.
302303
303304
Args:
304305
zone_states_data: Zone state response from Tado Cloud API
@@ -313,7 +314,7 @@ def sync_zone_states_data(self, zone_states_data: List[Dict[str, Any]], home_id:
313314
conn = sqlite3.connect(self.db_path)
314315
cursor = conn.cursor()
315316

316-
sensor_updates = 0
317+
humidity_updates = 0
317318

318319
zones = zone_states_data.get('zoneStates', {})
319320
for zone_id, zone_state in zones.items():
@@ -324,35 +325,27 @@ def sync_zone_states_data(self, zone_states_data: List[Dict[str, Any]], home_id:
324325

325326
sensor_data = zone_state.get('sensorDataPoints', {})
326327
humidity = sensor_data.get('humidity', {}).get('percentage')
327-
temperature = sensor_data.get('insideTemperature', {}).get('celsius')
328328

329-
if humidity is None and temperature is None:
329+
if humidity is None:
330330
continue
331331

332-
logger.debug(f"Cloud sensor data for zone {zone_id}: temp={temperature}, hum={humidity}")
332+
logger.debug(f"Cloud humidity for zone {zone_id}: {humidity}%")
333333
cursor.execute("SELECT aid FROM devices WHERE tado_zone_id = ?", (str(zone_id),))
334334

335335
for device in cursor.fetchall():
336336
aid = device[0]
337337
if not aid:
338338
continue
339339

340-
if humidity is not None:
341-
iid = tado_api.get_iid_from_characteristics(aid, "CurrentRelativeHumidity")
342-
if iid:
343-
asyncio.create_task(tado_api.handle_change(aid, iid, {'value': humidity}, source="POLLING"))
344-
sensor_updates += 1
345-
346-
if temperature is not None:
347-
iid = tado_api.get_iid_from_characteristics(aid, "CurrentTemperature")
348-
if iid:
349-
asyncio.create_task(tado_api.handle_change(aid, iid, {'value': temperature}, source="POLLING"))
350-
sensor_updates += 1
340+
iid = tado_api.get_iid_from_characteristics(aid, "CurrentRelativeHumidity")
341+
if iid:
342+
asyncio.create_task(tado_api.handle_change(aid, iid, {'value': humidity}, source="POLLING"))
343+
humidity_updates += 1
351344

352345
conn.commit()
353346
conn.close()
354347

355-
logger.info(f"Cloud zone states: {sensor_updates} sensor updates applied")
348+
logger.info(f"Cloud zone states: {humidity_updates} humidity updates applied")
356349
return True
357350

358351
except Exception as e:

tests/test_sync.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ def test_sync_zone_states_data_creates_humidity_tasks(self, syncer):
209209
tado_api.get_iid_from_characteristics.assert_any_call(11, "CurrentRelativeHumidity")
210210
assert create_task.call_count >= 1
211211

212-
def test_sync_zone_states_data_creates_temperature_tasks(self, syncer):
212+
def test_sync_zone_states_data_ignores_temperature_only(self, syncer):
213+
"""Temperature-only zones should be skipped -- temp is handled by HomeKit polling."""
213214
conn = sqlite3.connect(syncer.db_path)
214215
conn.execute("INSERT INTO devices (serial_number, aid, tado_zone_id, name)" "VALUES ('SU001', 22, '5', 'ac_ctrl')")
215216
conn.commit()
@@ -227,15 +228,14 @@ def test_sync_zone_states_data_creates_temperature_tasks(self, syncer):
227228
}
228229

229230
tado_api = MagicMock()
230-
tado_api.get_iid_from_characteristics.return_value = 300
231231

232232
with patch("tado_local.sync.asyncio.create_task") as create_task:
233233
assert syncer.sync_zone_states_data(zone_states_data, home_id=1, tado_api=tado_api) is True
234234

235-
tado_api.get_iid_from_characteristics.assert_any_call(22, "CurrentTemperature")
236-
create_task.assert_called_once()
235+
create_task.assert_not_called()
237236

238-
def test_sync_zone_states_data_syncs_both_temp_and_humidity(self, syncer):
237+
def test_sync_zone_states_data_syncs_only_humidity_when_both_present(self, syncer):
238+
"""When both temp and humidity are present, only humidity should be synced."""
239239
conn = sqlite3.connect(syncer.db_path)
240240
conn.execute("INSERT INTO devices (serial_number, aid, tado_zone_id, name)" "VALUES ('RU002', 33, '7', 'thermostat')")
241241
conn.commit()
@@ -259,11 +259,8 @@ def test_sync_zone_states_data_syncs_both_temp_and_humidity(self, syncer):
259259
with patch("tado_local.sync.asyncio.create_task") as create_task:
260260
assert syncer.sync_zone_states_data(zone_states_data, home_id=1, tado_api=tado_api) is True
261261

262-
calls = tado_api.get_iid_from_characteristics.call_args_list
263-
char_names = [c[0][1] for c in calls]
264-
assert "CurrentRelativeHumidity" in char_names
265-
assert "CurrentTemperature" in char_names
266-
assert create_task.call_count == 2
262+
tado_api.get_iid_from_characteristics.assert_called_once_with(33, "CurrentRelativeHumidity")
263+
create_task.assert_called_once()
267264

268265
def test_sync_zone_states_data_skips_when_no_sensor_data(self, syncer):
269266
zone_states_data = {

0 commit comments

Comments
 (0)