fix(water_purifier): read favorite-temp options from showList (#196)

favorite_hotwater_temperature's options_field read
favorite.supportedList, which is only the four fixed presets. The
SmartThings app also lets the user add one custom value to their own
display list via its "temperatures to display" editor (bounded by
/setting/waterpurifier/vs/0's hotwaterRange), and that value shows up
in favorite.showList but never in supportedList. A unit whose current
default was that custom value rendered as HA's "unknown" state, since
current_option wasn't among the (too-narrow) options list.

showList is a superset of supportedList that always includes whatever
the current default actually is. /setting/waterpurifier/vs/0's own
hot_water_temperature select is untouched -- its write contract for
values off the old preset list still isn't confirmed, so it stays
gated off on boards that don't report supportedHotTemperatures.
This commit is contained in:
Marc Billow
2026-07-31 02:14:09 +00:00
parent e46e935ba0
commit 4d4de23fbb
2 changed files with 41 additions and 3 deletions
@@ -175,11 +175,23 @@ FAVORITE_HOTWATER = Capability(
write_fn=lambda p, rep, href=None: (
['favorite', 'hotwater', 'vs', '0'],
{'x.com.samsung.da.switchHotwater': 'Locked' if p == 'On' else 'Unlocked'})),
# Issue #196: `supportedList` is only the four *fixed* presets
# (e.g. ['40', '75', '85', '90']) -- the SmartThings app also lets
# the user add one custom value to their own display list via its
# "temperatures to display" editor (a wheel picker bounded by
# /setting/waterpurifier/vs/0's hotwaterRange, separate resource),
# and that custom value shows up in `showList`
# (['40', '50', '75', '85', '90'] here) but never in
# `supportedList`. Reading options from `supportedList` meant a
# unit whose current default *was* that custom value rendered as
# "unknown" -- not a coverage gap, just the wrong field. `showList`
# is a superset of `supportedList` that always includes whatever
# the current default actually is, custom or not.
SelectDesc(key='favorite_hotwater_temperature',
field='x.com.samsung.da.favorite.defaultTemperature',
icon='mdi:thermometer',
entity_category='config',
options_field='x.com.samsung.da.favorite.supportedList',
options_field='x.com.samsung.da.favorite.showList',
write_fn=lambda p, rep, href=None: (
['favorite', 'hotwater', 'vs', '0'],
{'x.com.samsung.da.favorite.defaultTemperature': p})),
+28 -2
View File
@@ -281,9 +281,17 @@ def test_hotwater_lock_fallback_gating_across_status_lock_states():
assert fallback.exists_fn({}, {}) is False
def test_favorite_hotwater_temperature_options_come_from_live_supported_list():
def test_favorite_hotwater_temperature_options_come_from_live_show_list():
"""`supportedList` is only the four fixed presets -- `showList` is a
superset that also carries the one custom value (if any) the
SmartThings app's "temperatures to display" editor let the user add,
and always includes whatever the current default actually is. Reading
`supportedList` meant a unit whose default *was* that custom value
rendered as 'unknown' in HA (issue #196) -- see the ailite fixture's
version of this test below for the case that actually exercises it
(this fixture's showList == supportedList, no custom value set)."""
desc = _desc_coffee('favorite_hotwater_temperature')
assert desc.options_field == 'x.com.samsung.da.favorite.supportedList'
assert desc.options_field == 'x.com.samsung.da.favorite.showList'
def test_coffee_recipe_hrefs_are_ignored_not_guessed():
@@ -361,6 +369,24 @@ def test_ailite_hot_water_temperature_gated_off_without_supported_list():
assert 'hot_water_temperature' not in state
def test_ailite_favorite_hotwater_temperature_options_include_the_custom_value():
"""This board's real dump (issue #196) is the concrete case: the user
added a custom 50C value via the SmartThings app's "temperatures to
display" editor, so favorite.showList is
['40', '50', '75', '85', '90'] while favorite.supportedList stays the
fixed ['40', '75', '85', '90'] -- '50' only ever appears in showList.
Whichever of the two the descriptor reads from, a default temperature
of '50' would render as HA's 'unknown' state unless that field's raw
option list actually contains '50'."""
desc = _desc_ailite('favorite_hotwater_temperature')
assert desc.options_field == 'x.com.samsung.da.favorite.showList'
_, resources = _water_purifier_ailite()
rep = resources['/favorite/hotwater/vs/0']
assert rep['x.com.samsung.da.favorite.defaultTemperature'] in rep[desc.options_field]
assert '50' not in rep['x.com.samsung.da.favorite.supportedList']
assert '50' in rep['x.com.samsung.da.favorite.showList']
def test_ailite_sound_mode_options_come_from_live_supported_modes():
"""This board's supportedModes (voice/fixedTone/mute) differs from both
laundry.SOUND_MODE's hardcoded voice/tone/mute and air_purifier.SOUND_MODE's