fridge: give DEODOR_FILTER its own entity keys, not AIR_FILTER's (code review)
DEODOR_FILTER reused AIR_FILTER.entities verbatim, so both capabilities produced identically-keyed entities (air_filter_usage/air_filter_status) despite living at different hrefs. adapter.flatten()'s key derivation has no href component, so a unit reporting both /filter/airdustfilter/vs/0 and /filter/deodorfilter/vs/0 would silently clobber one filter's reading with the other's -- the exact collision AIR_FILTER's own 'air_' prefix was chosen to avoid against WATER_FILTER's filter_usage/filter_status. Gives DEODOR_FILTER its own deodor_filter_usage/deodor_filter_status keys (status still shares the filter_status translation_key, same as AIR_FILTER already does). Updated the winecellar fixture's golden and test, and added deodor_filter_usage to all seven translation catalogs.
This commit is contained in:
@@ -411,10 +411,35 @@ AUTO_DOOR_VARIANT = Capability(
|
||||
# comment). filterUsage reads '-1' on the only dump seen (filterStatus
|
||||
# 'normal'), relayed as-is rather than special-cased -- no second dump to
|
||||
# confirm whether that's a real sentinel or this unit just not tracking it.
|
||||
# Own 'deodor_'-prefixed keys rather than reusing AIR_FILTER.entities
|
||||
# verbatim -- same collision AIR_FILTER's own 'air_' prefix was chosen to
|
||||
# avoid against WATER_FILTER, and both filters are plausible on one unit
|
||||
# (this device's own board reports an internal air filter on other
|
||||
# TP1X_REF_21K variants).
|
||||
DEODOR_FILTER = Capability(
|
||||
href="/filter/deodorfilter/vs/0",
|
||||
poll_tier="cold",
|
||||
entities=AIR_FILTER.entities,
|
||||
entities=(
|
||||
SensorDesc(
|
||||
key="deodor_filter_usage",
|
||||
field="x.com.samsung.da.filterUsage",
|
||||
unit="%",
|
||||
state_class="measurement",
|
||||
icon="mdi:air-filter",
|
||||
entity_category="diagnostic",
|
||||
value_fn=int_or_none,
|
||||
),
|
||||
SensorDesc(
|
||||
key="deodor_filter_status",
|
||||
field="x.com.samsung.da.filterStatus",
|
||||
device_class="enum",
|
||||
options=("normal", "wash", "replace"),
|
||||
translation_key="filter_status",
|
||||
icon="mdi:air-filter",
|
||||
entity_category="diagnostic",
|
||||
value_fn=lambda v: v.lower() if isinstance(v, str) else v,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
# Wine-cellar multi-compartment pantry select (issue #328): same
|
||||
|
||||
@@ -761,6 +761,9 @@
|
||||
"air_filter_usage_hours": {
|
||||
"name": "Hodiny využití filtru"
|
||||
},
|
||||
"deodor_filter_usage": {
|
||||
"name": "Využití filtru"
|
||||
},
|
||||
"air_quality_standard": {
|
||||
"name": "Norma kvality vzduchu"
|
||||
},
|
||||
|
||||
@@ -761,6 +761,9 @@
|
||||
"air_filter_usage_hours": {
|
||||
"name": "Filternutzungsstunden"
|
||||
},
|
||||
"deodor_filter_usage": {
|
||||
"name": "Filternutzung"
|
||||
},
|
||||
"air_quality_standard": {
|
||||
"name": "Luftqualitätsstandard"
|
||||
},
|
||||
|
||||
@@ -761,6 +761,9 @@
|
||||
"air_filter_usage_hours": {
|
||||
"name": "Filter usage hours"
|
||||
},
|
||||
"deodor_filter_usage": {
|
||||
"name": "Filter usage"
|
||||
},
|
||||
"air_quality_standard": {
|
||||
"name": "Air quality standard"
|
||||
},
|
||||
|
||||
@@ -907,6 +907,9 @@
|
||||
"air_filter_usage_hours": {
|
||||
"name": "Horas de uso del filtro"
|
||||
},
|
||||
"deodor_filter_usage": {
|
||||
"name": "Uso del filtro"
|
||||
},
|
||||
"air_quality_standard": {
|
||||
"name": "Estándar de calidad del aire"
|
||||
},
|
||||
|
||||
@@ -761,6 +761,9 @@
|
||||
"air_filter_usage_hours": {
|
||||
"name": "Ore di utilizzo filtro"
|
||||
},
|
||||
"deodor_filter_usage": {
|
||||
"name": "Utilizzo filtro"
|
||||
},
|
||||
"air_quality_standard": {
|
||||
"name": "Standard qualità aria"
|
||||
},
|
||||
|
||||
@@ -761,6 +761,9 @@
|
||||
"air_filter_usage_hours": {
|
||||
"name": "필터 사용 시간"
|
||||
},
|
||||
"deodor_filter_usage": {
|
||||
"name": "필터 사용량"
|
||||
},
|
||||
"air_quality_standard": {
|
||||
"name": "공기질 기준"
|
||||
},
|
||||
|
||||
@@ -761,6 +761,9 @@
|
||||
"air_filter_usage_hours": {
|
||||
"name": "Filterverbruik (uren)"
|
||||
},
|
||||
"deodor_filter_usage": {
|
||||
"name": "Filterverbruik"
|
||||
},
|
||||
"air_quality_standard": {
|
||||
"name": "Luchtkwaliteitsnorm"
|
||||
},
|
||||
|
||||
+2
-2
@@ -1,7 +1,5 @@
|
||||
{
|
||||
"state_keys": [
|
||||
"air_filter_status",
|
||||
"air_filter_usage",
|
||||
"alarm_code",
|
||||
"auto_door_opener",
|
||||
"auto_door_sound_control",
|
||||
@@ -9,6 +7,8 @@
|
||||
"auto_door_voice_control",
|
||||
"cabinet_light_dim",
|
||||
"cabinet_light_switch",
|
||||
"deodor_filter_status",
|
||||
"deodor_filter_usage",
|
||||
"door_winecellar_open",
|
||||
"energy_kwh",
|
||||
"energy_saved_kwh",
|
||||
|
||||
@@ -48,15 +48,21 @@ def test_auto_door_sound_control_present_here_only():
|
||||
assert state["auto_door_voice_control"] is False
|
||||
|
||||
|
||||
def test_deodor_filter_reuses_air_filter_shape():
|
||||
"""Same entities as fridge.AIR_FILTER (see its own already-confirmed
|
||||
percentage-not-raw-count reasoning), bound at this variant's own href."""
|
||||
assert fridge.DEODOR_FILTER.entities is fridge.AIR_FILTER.entities
|
||||
def test_deodor_filter_has_its_own_keys_not_air_filters():
|
||||
"""Same shape/reasoning as fridge.AIR_FILTER (percentage-not-raw-count,
|
||||
see its own comment) but its own 'deodor_'-prefixed keys, not a shared
|
||||
tuple -- AIR_FILTER's own docstring picked 'air_' specifically to avoid
|
||||
colliding with WATER_FILTER's filter_usage/filter_status, and reusing
|
||||
AIR_FILTER.entities verbatim here would silently recreate that same
|
||||
collision if a unit ever reports both hrefs."""
|
||||
assert fridge.DEODOR_FILTER.entities != fridge.AIR_FILTER.entities
|
||||
state = _state()
|
||||
assert state["air_filter_status"] == "normal"
|
||||
assert state["deodor_filter_status"] == "normal"
|
||||
# The device's own sentinel, relayed as-is -- not a real 0-100 reading
|
||||
# on this unit, and no second dump to say what else -1 could mean.
|
||||
assert state["air_filter_usage"] == -1
|
||||
assert state["deodor_filter_usage"] == -1
|
||||
assert "air_filter_usage" not in state
|
||||
assert "air_filter_status" not in state
|
||||
|
||||
|
||||
def test_winecellar_pantry_zone_mode_options_and_write():
|
||||
|
||||
Reference in New Issue
Block a user