From 9011f84787166db1bdff9551f4f3f66096e9e43a Mon Sep 17 00:00:00 2001 From: Marc Billow Date: Tue, 28 Jul 2026 02:29:01 +0000 Subject: [PATCH] Model after_run_progress as a percentage, fix Dutch after-run-progress name runningProgress's own field name states its domain, so restore unit='%' and state_class='measurement' rather than leaving it an opaque passthrough -- that hedge made sense for activationState (no supported-values list, no write contract to invent) but not here, where the name itself is the evidence. "Nadraaien voortgang" also wasn't idiomatic Dutch (nouns don't stack that way); "Voortgang nadraaien" matches how the rest of the catalog compounds these names. --- .../localthings/registry/capabilities/range_hood.py | 12 +++++++----- custom_components/localthings/translations/nl.json | 2 +- tests/test_range_hood_capabilities.py | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/custom_components/localthings/registry/capabilities/range_hood.py b/custom_components/localthings/registry/capabilities/range_hood.py index 8854dc4..70a7732 100644 --- a/custom_components/localthings/registry/capabilities/range_hood.py +++ b/custom_components/localthings/registry/capabilities/range_hood.py @@ -188,11 +188,10 @@ HOOD_FILTER = Capability( # read-only (monitoring, not an invented "enable" write) per the 'don't # guess' rule; runningCancel's only observed value is the command name # itself ('Cancel'), the same self-describing command-field shape as -# operational.STOP_BUTTON. runningProgress is left a bare passthrough for the -# same 'don't guess' reason -- the only observed sample is "0", with no -# range or supported-values field to confirm it's a percentage rather than a -# minutes/seconds count, and unit + state_class='measurement' would commit -# it to long-term statistics under a possibly-wrong unit. +# operational.STOP_BUTTON. runningProgress's own name states its domain +# (a percentage of the cycle completed), so it's modeled as one rather than +# left an opaque passthrough -- unlike activationState/runningCancel, there's +# no ambiguous field name or missing-write-contract question here to hedge on. AFTER_RUN = Capability( href='/afterrun/vs/0', poll_tier='warm', @@ -206,7 +205,10 @@ AFTER_RUN = Capability( SensorDesc( key='after_run_progress', field='x.com.samsung.da.runningProgress', + unit='%', + state_class='measurement', icon='mdi:fan-clock', + value_fn=int_or_none, ), ButtonDesc( key='after_run_cancel', diff --git a/custom_components/localthings/translations/nl.json b/custom_components/localthings/translations/nl.json index 5cd0181..cdfca45 100644 --- a/custom_components/localthings/translations/nl.json +++ b/custom_components/localthings/translations/nl.json @@ -536,7 +536,7 @@ }, "sensor": { "after_run_progress": { - "name": "Nadraaien voortgang" + "name": "Voortgang nadraaien" }, "air_filter_usage": { "name": "Filterverbruik" diff --git a/tests/test_range_hood_capabilities.py b/tests/test_range_hood_capabilities.py index bca96fa..7727d49 100644 --- a/tests/test_range_hood_capabilities.py +++ b/tests/test_range_hood_capabilities.py @@ -62,7 +62,7 @@ def test_range_hood_fixture_values(): assert state['air_sensing_state'] == 'NonProcessing' assert state['last_air_sensing_level'] == 'Kr2' assert state['after_run_active'] is False - assert state['after_run_progress'] == '0' + assert state['after_run_progress'] == 0 def test_one_composite_fan_is_bound():