feat(microwave): add filter reminder / end signal reminder switches (#181)

Both FilterRemind_*/RemindBeep_* option-array tokens are already
present -- and both On and Off already confirmed -- on the existing
ME7500D fixtures (issue #152), so this is a straight sibling of the
Sound/Lamp switches rather than new discovery work. Gated with
exists_fn like Lamp since the MW7300B combi dump has neither token.

Doesn't address the rest of issue #181 (power-level slider,
non-reported cooking modes, 3-level light, child lock, send-to-
microwave) -- those need write-contract confirmation this dump
doesn't carry.
This commit is contained in:
Marc Billow committed 2026-07-29 02:55:47 +00:00
1 parent 90d79f117a
commit a6eb1c62d4
6 files changed
+131

No files matched your search

@@ -27,6 +27,10 @@ different from an oven, and defined fresh here:
(a brightness level, not literally 'On') -- the switch now treats any
non-Off/non-None value as "on" for reads, and writes back 'High'/'Off'
(the two confirmed tokens) rather than the never-confirmed 'On'.
* Filter reminder / end signal reminder: bare 'FilterRemind'/'RemindBeep'
option-array tokens (issue #181), both with On and Off observed live
(issue #152's ME7500D fixtures) -- gated with exists_fn like Lamp since
the MW7300B combi dump has neither.
Note: cooking-mode writes are unproven here, same caveat as oven.py's
OVEN_MODE -- exposed as a SelectDesc for fidelity, first real-world write
@@ -145,6 +149,14 @@ def _lamp_exists(rep, resources):
return option_value(rep.get('x.com.samsung.da.options'), 'Lamp') is not None
def _filter_remind_exists(rep, resources):
return option_value(rep.get('x.com.samsung.da.options'), 'FilterRemind') is not None
def _remind_beep_exists(rep, resources):
return option_value(rep.get('x.com.samsung.da.options'), 'RemindBeep') is not None
def _lamp_write(p, rep, href=None):
if p not in ('On', 'Off'):
return None
@@ -159,6 +171,26 @@ def _lamp_write(p, rep, href=None):
}
def _filter_remind_write(p, rep, href=None):
if p not in ('On', 'Off'):
return None
if not rep.get('x.com.samsung.da.options'):
return None
return ['mode', 'vs', '0'], {
'x.com.samsung.da.options': option_write('FilterRemind', p),
}
def _remind_beep_write(p, rep, href=None):
if p not in ('On', 'Off'):
return None
if not rep.get('x.com.samsung.da.options'):
return None
return ['mode', 'vs', '0'], {
'x.com.samsung.da.options': option_write('RemindBeep', p),
}
# ---------------------------------------------------------------------------
# Capabilities
# ---------------------------------------------------------------------------
@@ -213,5 +245,22 @@ MICROWAVE_MODE = Capability(
exists_fn=_lamp_exists,
value_fn=lambda opts: option_value(opts, 'Lamp') not in (None, 'Off'),
write_fn=_lamp_write),
# issue #181: Filter Reminder / End Signal Reminder toggles,
# confirmed present (both On and Off observed across dumps -- see
# issue #152's ME7500D fixtures) but only on boards that carry the
# FilterRemind_*/RemindBeep_* tokens; gated off elsewhere (e.g. the
# MW7300B combi dump has neither) rather than assumed universal.
SwitchDesc(key='filter_remind', field='x.com.samsung.da.options',
icon='mdi:air-filter',
entity_category='config',
exists_fn=_filter_remind_exists,
value_fn=lambda opts: option_value(opts, 'FilterRemind') == 'On',
write_fn=_filter_remind_write),
SwitchDesc(key='remind_beep', field='x.com.samsung.da.options',
icon='mdi:bell-ring',
entity_category='config',
exists_fn=_remind_beep_exists,
value_fn=lambda opts: option_value(opts, 'RemindBeep') == 'On',
write_fn=_remind_beep_write),
),
)
@@ -985,6 +985,9 @@
"favorite_coffee_enabled": {
"name": "Favorite coffee"
},
"filter_remind": {
"name": "Filter reminder"
},
"fridge_sound": {
"name": "Sound"
},
@@ -1027,6 +1030,9 @@
"rapid_fridge": {
"name": "Rapid fridge"
},
"remind_beep": {
"name": "End signal reminder"
},
"sabbath_mode": {
"name": "Sabbath mode"
},
@@ -985,6 +985,9 @@
"favorite_coffee_enabled": {
"name": "Favoriete koffie"
},
"filter_remind": {
"name": "Filterherinnering"
},
"fridge_sound": {
"name": "Geluid"
},
@@ -1027,6 +1030,9 @@
"rapid_fridge": {
"name": "Snelkoelen"
},
"remind_beep": {
"name": "Eindsignaal herinnering"
},
"sabbath_mode": {
"name": "Sabbatmodus"
},
+2
View File
@@ -10,6 +10,7 @@
"door_open",
"energy_kwh",
"fan",
"filter_remind",
"finish_time",
"firmware_update",
"lamp",
@@ -17,6 +18,7 @@
"operation_time_minutes",
"power_level",
"progress_percentage",
"remind_beep",
"sound"
]
}
@@ -10,6 +10,7 @@
"door_open",
"energy_kwh",
"fan",
"filter_remind",
"finish_time",
"firmware_update",
"lamp",
@@ -17,6 +18,7 @@
"operation_time_minutes",
"power_level",
"progress_percentage",
"remind_beep",
"sound"
]
}
+66
View File
@@ -217,3 +217,69 @@ def test_lamp_reads_any_non_off_level_as_true():
just a literal 'On'."""
desc = next(e for e in microwave.MICROWAVE_MODE.entities if e.key == 'lamp')
assert desc.value_fn(['Lamp_High']) is True
# ---------------------------------------------------------------------------
# MICROWAVE_MODE — filter_remind/remind_beep options-array writes (issue #181)
# ---------------------------------------------------------------------------
def test_filter_remind_gated_absent_when_no_option():
desc = next(e for e in microwave.MICROWAVE_MODE.entities if e.key == 'filter_remind')
rep = {'x.com.samsung.da.options': ['DeviceType_MW7300B-/EU1', 'Sound_Off']}
assert desc.exists_fn(rep, {}) is False
def test_filter_remind_gated_present_when_option_reported():
desc = next(e for e in microwave.MICROWAVE_MODE.entities if e.key == 'filter_remind')
rep = {'x.com.samsung.da.options': ['FilterRemind_Off']}
assert desc.exists_fn(rep, {}) is True
def test_filter_remind_reads_on_off():
desc = next(e for e in microwave.MICROWAVE_MODE.entities if e.key == 'filter_remind')
assert desc.value_fn(['FilterRemind_On']) is True
assert desc.value_fn(['FilterRemind_Off']) is False
def test_filter_remind_write_is_single_token():
desc = next(e for e in microwave.MICROWAVE_MODE.entities if e.key == 'filter_remind')
rep = {'x.com.samsung.da.options': ['FilterRemind_Off']}
path, body = desc.write_fn('On', rep)
assert path == ['mode', 'vs', '0']
assert body == {'x.com.samsung.da.options': ['FilterRemind_On']}
def test_filter_remind_write_requires_existing_options():
desc = next(e for e in microwave.MICROWAVE_MODE.entities if e.key == 'filter_remind')
assert desc.write_fn('On', {}) is None
def test_remind_beep_gated_absent_when_no_option():
desc = next(e for e in microwave.MICROWAVE_MODE.entities if e.key == 'remind_beep')
rep = {'x.com.samsung.da.options': ['DeviceType_MW7300B-/EU1', 'Sound_Off']}
assert desc.exists_fn(rep, {}) is False
def test_remind_beep_gated_present_when_option_reported():
desc = next(e for e in microwave.MICROWAVE_MODE.entities if e.key == 'remind_beep')
rep = {'x.com.samsung.da.options': ['RemindBeep_On']}
assert desc.exists_fn(rep, {}) is True
def test_remind_beep_reads_on_off():
desc = next(e for e in microwave.MICROWAVE_MODE.entities if e.key == 'remind_beep')
assert desc.value_fn(['RemindBeep_On']) is True
assert desc.value_fn(['RemindBeep_Off']) is False
def test_remind_beep_write_is_single_token():
desc = next(e for e in microwave.MICROWAVE_MODE.entities if e.key == 'remind_beep')
rep = {'x.com.samsung.da.options': ['RemindBeep_On']}
path, body = desc.write_fn('Off', rep)
assert path == ['mode', 'vs', '0']
assert body == {'x.com.samsung.da.options': ['RemindBeep_Off']}
def test_remind_beep_write_requires_existing_options():
desc = next(e for e in microwave.MICROWAVE_MODE.entities if e.key == 'remind_beep')
assert desc.write_fn('On', {}) is None