From 2fd8ff8260da2fd5526ccaca1e80db9a2bc085ed Mon Sep 17 00:00:00 2001 From: vmvarga Date: Sun, 26 Jul 2026 11:05:13 +0200 Subject: [PATCH] merge temp_setpoint --- custom_components/localthings/coordinator.py | 5 +- .../registry/by_type/refrigerator.py | 3 +- .../registry/capabilities/fridge.py | 61 ++++++++----------- tests/test_fridge_capabilities.py | 4 +- 4 files changed, 31 insertions(+), 42 deletions(-) diff --git a/custom_components/localthings/coordinator.py b/custom_components/localthings/coordinator.py index 9e65827..58635ff 100644 --- a/custom_components/localthings/coordinator.py +++ b/custom_components/localthings/coordinator.py @@ -564,7 +564,10 @@ class LocalThingsCoordinator(DataUpdateCoordinator[dict[str, Any]]): translation_domain=DOMAIN, translation_key=error, ) - result = write_fn(payload, rep, href) + try: + result = write_fn(payload, rep, href, resources) + except TypeError: + result = write_fn(payload, rep, href) if result is None: self._log.warning("write_fn rejected payload %r for %s", payload, href) return diff --git a/custom_components/localthings/registry/by_type/refrigerator.py b/custom_components/localthings/registry/by_type/refrigerator.py index 9d70ebd..43e776b 100644 --- a/custom_components/localthings/registry/by_type/refrigerator.py +++ b/custom_components/localthings/registry/by_type/refrigerator.py @@ -33,8 +33,7 @@ REGISTRY = DeviceRegistry( ]), pattern_capabilities=[ fridge.TEMP_CURRENT_GENERIC, - fridge.TEMP_SETPOINT_VENDOR, - fridge.TEMP_SETPOINT_GENERIC, + fridge.TEMP_SETPOINT, fridge.ICEMAKER_GENERIC, fridge.DOOR_GENERIC, ], diff --git a/custom_components/localthings/registry/capabilities/fridge.py b/custom_components/localthings/registry/capabilities/fridge.py index 14ff82a..855f3b5 100644 --- a/custom_components/localthings/registry/capabilities/fridge.py +++ b/custom_components/localthings/registry/capabilities/fridge.py @@ -62,48 +62,38 @@ TEMP_CURRENT_GENERIC = Capability( ), ) -def _temp_setpoint_vendor_write(p, rep, href=None): - """Write temperature via the vendor /temperatures/vs/0 resource. +def _temp_setpoint_write(p, rep, href=None, resources=None): + """Write temperature — prefer vendor /temperatures/vs/0 when available, + fall back to direct OCF /temperature/desired/ write otherwise. - Samsung fridges expose both OCF-standard /temperature/desired/* (readable) - and vendor /temperatures/vs/0 (writable). The OCF resource ACKs POSTs but - ignores them; only the vendor path actually commits the setpoint change. + Samsung fridges expose both OCF-standard /temperature/desired/* and vendor + /temperatures/vs/0. On some models only the vendor path commits the change; + on others both work. Using the vendor path when present is always correct. Item IDs follow the Samsung convention: "0" = Freezer, "1" = Fridge/Cooler. """ if not href: return None - if '/cooler/' in href: - item_id = '1' - elif '/freezer/' in href: - item_id = '0' - else: - return None + if resources and '/temperatures/vs/0' in resources: + if '/cooler/' in href: + item_id = '1' + elif '/freezer/' in href: + item_id = '0' + else: + return None + return ( + ['temperatures', 'vs', '0'], + {'x.com.samsung.da.items': [ + {'x.com.samsung.da.id': item_id, + 'x.com.samsung.da.desired': str(int(round(float(p))))} + ]} + ) return ( - ['temperatures', 'vs', '0'], - {'x.com.samsung.da.items': [ - {'x.com.samsung.da.id': item_id, - 'x.com.samsung.da.desired': str(int(round(float(p))))} - ]} + [s for s in href.strip('/').split('/') if s], + {'temperature': int(round(float(p)))} ) -TEMP_SETPOINT_VENDOR = Capability( - href=None, - href_prefix='/temperature/desired/', - strip_prefix_in_key=True, - match_fn=lambda rep, resources: '/temperatures/vs/0' in resources, - poll_tier='warm', - entities=( - NumberDesc(key='setpoint', field='temperature', - translation_key='instance_setpoint', - use_instance_name=True, device_class='temperature', unit_fn=_temp_unit, - native_min=-20.0, native_max=50.0, - range_field='range', entity_category='config', - write_fn=_temp_setpoint_vendor_write), - ), -) - -TEMP_SETPOINT_GENERIC = Capability( +TEMP_SETPOINT = Capability( href=None, href_prefix='/temperature/desired/', strip_prefix_in_key=True, @@ -114,10 +104,7 @@ TEMP_SETPOINT_GENERIC = Capability( use_instance_name=True, device_class='temperature', unit_fn=_temp_unit, native_min=-20.0, native_max=50.0, range_field='range', entity_category='config', - write_fn=lambda p, rep, href=None: ( - [s for s in href.strip('/').split('/') if s], - {'temperature': int(round(float(p)))} - ) if href else None), + write_fn=_temp_setpoint_write), ), ) diff --git a/tests/test_fridge_capabilities.py b/tests/test_fridge_capabilities.py index d35f5d4..d2bd4c5 100644 --- a/tests/test_fridge_capabilities.py +++ b/tests/test_fridge_capabilities.py @@ -20,9 +20,9 @@ class TestTempCurrentGeneric: assert desc.unit_fn({'temperature': 5.0}) == '°F' -class TestTempSetpointGeneric: +class TestTempSetpoint: def test_unit_reads_celsius(self): - desc = fridge.TEMP_SETPOINT_GENERIC.entities[0] + desc = fridge.TEMP_SETPOINT.entities[0] assert desc.unit_fn({'temperature': -19.0, 'units': 'C'}) == '°C'