diff --git a/custom_components/localthings/registry/capabilities/fridge.py b/custom_components/localthings/registry/capabilities/fridge.py index 2f2589c..accde1c 100644 --- a/custom_components/localthings/registry/capabilities/fridge.py +++ b/custom_components/localthings/registry/capabilities/fridge.py @@ -92,7 +92,7 @@ ICEMAKER_NIGHTTIME = Capability( value_fn=lambda v: v == 'On', write_fn=lambda p, rep, href=None: ( ['icemaker', 'nighttime', 'vs', '0'], - {'ice.night.status': 'On' if p else 'Off'})), + {'ice.night.status': 'On' if p == 'On' else 'Off'})), ), ) @@ -168,7 +168,7 @@ DOOR_ALERT = Capability( def _status_lock_write(field): return lambda p, rep, href=None: ( ['status', 'lock', 'vs', '0'], - {field: 'On' if p else 'Off'} + {field: 'On' if p == 'On' else 'Off'} ) @@ -212,7 +212,7 @@ DEFROST_DELAY = Capability( value_fn=lambda v: v == 'On', write_fn=lambda p, rep, href=None: ( ['defrost', 'delay', 'vs', '0'], - {'x.com.samsung.da.delayDefrost': 'On' if p else 'Off'})), + {'x.com.samsung.da.delayDefrost': 'On' if p == 'On' else 'Off'})), ), ) @@ -300,7 +300,7 @@ WELCOME_LIGHTING = Capability( value_fn=lambda v: v == 'On', write_fn=lambda p, rep, href=None: ( ['proximity', 'vs', '0'], - {'status': 'On' if p else 'Off'})), + {'status': 'On' if p == 'On' else 'Off'})), ), ) @@ -440,7 +440,7 @@ CABINET_LIGHT = Capability( value_fn=lambda v: v == 'On', write_fn=lambda p, rep, href=None: ( ['cabinet', 'light', 'total', 'vs', '0'], - {'light.dimming.status': 'On' if p else 'Off'})), + {'light.dimming.status': 'On' if p == 'On' else 'Off'})), ), ) @@ -669,7 +669,7 @@ ICEMAKER_STATUS_FALLBACK = Capability( value_fn=lambda v: v == 'On', write_fn=lambda p, rep, href=None: ( ['icemaker', 'status', 'vs', '0'], - {'x.com.samsung.da.iceMaker': 'On' if p else 'Off'})), + {'x.com.samsung.da.iceMaker': 'On' if p == 'On' else 'Off'})), ), ) diff --git a/tests/test_fridge_capabilities.py b/tests/test_fridge_capabilities.py index 11dc501..d35f5d4 100644 --- a/tests/test_fridge_capabilities.py +++ b/tests/test_fridge_capabilities.py @@ -258,3 +258,39 @@ class TestRefrigeratorAiEnergyLevelFixtureCoverage: assert unbound == [] state = flatten(bound, resources) assert state['ai_energy_level'] == '1' + + +class TestSwitchOffIsNotInverted: + """Regression: several fridge SwitchDesc write_fns used ``'On' if p else 'Off'``. + + The switch platform passes the literal string ``'Off'`` on turn-off (and + ``'On'`` on turn-on). ``'Off'`` is a non-empty, truthy string, so + ``'On' if p else 'Off'`` always evaluated to ``'On'`` — turning the switch + OFF silently re-sent ``On`` and the switch could never be turned off. The + guard must compare ``p == 'On'`` (as the other capability files already do). + """ + + # (switch descriptor, payload key it writes) + CASES = [ + (fridge.ICEMAKER_NIGHTTIME.entities[0], 'ice.night.status'), + (fridge.STATUS_LOCK.entities[0], 'x.com.samsung.da.ado.devicecontrol'), + (fridge.STATUS_LOCK.entities[1], 'x.com.samsung.da.device.sound'), + (fridge.DEFROST_DELAY.entities[0], 'x.com.samsung.da.delayDefrost'), + (fridge.WELCOME_LIGHTING.entities[0], 'status'), + (fridge.CABINET_LIGHT.entities[1], 'light.dimming.status'), + (fridge.ICEMAKER_STATUS_FALLBACK.entities[0], 'x.com.samsung.da.iceMaker'), + ] + + def test_turning_off_sends_off(self): + for desc, key in self.CASES: + _segs, payload = desc.write_fn('Off', {}) + assert payload[key] == 'Off', ( + f"{desc.key}: OFF must send 'Off', got {payload[key]!r} (inverted)" + ) + + def test_turning_on_sends_on(self): + for desc, key in self.CASES: + _segs, payload = desc.write_fn('On', {}) + assert payload[key] == 'On', ( + f"{desc.key}: ON must send 'On', got {payload[key]!r}" + )