From 98fa7196f25b45f56aca29ce3404c33fb524e7cf Mon Sep 17 00:00:00 2001 From: Marc Billow Date: Tue, 30 Jun 2026 15:09:23 -0500 Subject: [PATCH] feat: cleaner temperature entity names and remove redundant sensors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add strip_prefix_in_key to Capability so pattern caps can drop their href_prefix segments from key derivation; temp caps use it so /temperature/desired/cooler/0 → "Cooler Setpoint" and /temperature/current/cooler/0 → "Cooler Temperature" instead of the verbose "Temperature Desired Cooler Temp F" - Change TEMP_CURRENT key to 'temperature' and TEMP_SETPOINT to 'setpoint' to keep state keys distinct and names readable - Number entities now render as sliders instead of text boxes - Remove ICEMAKER_STATUS sensor (redundant with per-unit enabled switches) - Remove Cabinet light level sensor and Cabinet light on binary sensor (redundant with Cabinet light switch) --- custom_components/localthings/number.py | 2 +- .../ocf/registry/by_type/refrigerator.py | 1 - .../ocf/registry/capabilities/fridge.py | 24 ++++--------------- .../localthings/ocf/registry/capability.py | 1 + .../localthings/ocf/registry/discovery.py | 5 ++-- 5 files changed, 9 insertions(+), 24 deletions(-) diff --git a/custom_components/localthings/number.py b/custom_components/localthings/number.py index 5f6bdf5..0c1126b 100644 --- a/custom_components/localthings/number.py +++ b/custom_components/localthings/number.py @@ -28,7 +28,7 @@ async def async_setup_entry( class LocalThingsNumber(LocalThingsEntity, NumberEntity): - _attr_mode = NumberMode.BOX + _attr_mode = NumberMode.SLIDER def __init__(self, coordinator: LocalThingsCoordinator, bound) -> None: super().__init__(coordinator, bound) diff --git a/custom_components/localthings/ocf/registry/by_type/refrigerator.py b/custom_components/localthings/ocf/registry/by_type/refrigerator.py index 400242d..8597b19 100644 --- a/custom_components/localthings/ocf/registry/by_type/refrigerator.py +++ b/custom_components/localthings/ocf/registry/by_type/refrigerator.py @@ -12,7 +12,6 @@ REGISTRY = DeviceRegistry( common.ENERGY_METER, common.WATER_FILTER, fridge.DOORS_STATUS, - fridge.ICEMAKER_STATUS, fridge.REFRIGERATION, fridge.AUTOFILL, fridge.CABINET_LIGHT, diff --git a/custom_components/localthings/ocf/registry/capabilities/fridge.py b/custom_components/localthings/ocf/registry/capabilities/fridge.py index e70801b..95197ca 100644 --- a/custom_components/localthings/ocf/registry/capabilities/fridge.py +++ b/custom_components/localthings/ocf/registry/capabilities/fridge.py @@ -34,9 +34,10 @@ def _int(v): TEMP_CURRENT_GENERIC = Capability( href=None, href_prefix='/temperature/current/', + strip_prefix_in_key=True, poll_tier='warm', entities=( - SensorDesc(key='temp_f', field='temperature', + SensorDesc(key='temperature', field='temperature', name=None, icon='mdi:thermometer', device_class='temperature', unit='°F', state_class='measurement'), @@ -46,9 +47,10 @@ TEMP_CURRENT_GENERIC = Capability( TEMP_SETPOINT_GENERIC = Capability( href=None, href_prefix='/temperature/desired/', + strip_prefix_in_key=True, poll_tier='warm', entities=( - NumberDesc(key='temp_f', field='temperature', + NumberDesc(key='setpoint', field='temperature', name=None, device_class='temperature', unit='°F', native_min=-20.0, native_max=50.0, range_field='range', @@ -113,19 +115,6 @@ DOORS_STATUS = Capability( ), ) -# --------------------------------------------------------------------------- -# Ice maker status (exact-href — binds before ICEMAKER_GENERIC pattern) -# --------------------------------------------------------------------------- - -ICEMAKER_STATUS = Capability( - href='/icemaker/status/vs/0', - poll_tier='warm', - entities=( - SensorDesc(key='ice_maker_enabled', field='x.com.samsung.da.iceMaker', - name='Ice maker enabled', icon='mdi:snowflake'), - ), -) - # --------------------------------------------------------------------------- # Refrigeration modes (rapid cooling) # --------------------------------------------------------------------------- @@ -190,11 +179,6 @@ CABINET_LIGHT = Capability( href='/cabinet/light/total/vs/0', poll_tier='warm', entities=( - SensorDesc(key='cabinet_light', field='x.com.samsung.da.lightControl', - name='Cabinet light level', icon='mdi:fridge-outline'), - BinarySensorDesc(key='cabinet_light_on', field='x.com.samsung.da.lightControl', - name='Cabinet light on', icon='mdi:fridge-outline', - value_fn=lambda v: v == 'On'), SwitchDesc(key='cabinet_light_switch', field='x.com.samsung.da.lightControl', name='Cabinet light', icon='mdi:fridge-outline', value_fn=lambda v: v == 'On', diff --git a/custom_components/localthings/ocf/registry/capability.py b/custom_components/localthings/ocf/registry/capability.py index 346a9ed..9d44f85 100644 --- a/custom_components/localthings/ocf/registry/capability.py +++ b/custom_components/localthings/ocf/registry/capability.py @@ -14,6 +14,7 @@ class Capability: poll_tier: str = 'warm' # 'hot' | 'warm' | 'cold' rt_filter: Optional[str] = None # bind only if rt_filter in rep.get('rt', ()) href_prefix: Optional[str] = None # pattern caps only: bind only if href starts with this + strip_prefix_in_key: bool = False # strip href_prefix segs before building key_override match_fn: Optional[Callable[[dict, dict], bool]] = None # match_fn(rep, resources) -> bool # Rare optional hooks — only operational-state-style resources use these. active_when: Optional[Callable[[dict], bool]] = None diff --git a/custom_components/localthings/ocf/registry/discovery.py b/custom_components/localthings/ocf/registry/discovery.py index f742f25..66032f7 100644 --- a/custom_components/localthings/ocf/registry/discovery.py +++ b/custom_components/localthings/ocf/registry/discovery.py @@ -68,8 +68,9 @@ def discover( if cap.match_fn is not None and not cap.match_fn(rep, resources): continue inst = instance_suffix(href) - # Auto-derive key prefix from href: strip digits, join non-empty segs with '_' - segs = [s for s in href.strip('/').split('/') if s and not s.isdigit() and s != 'vs'] + # Auto-derive key prefix from href segments (skip digits and 'vs') + src = href[len(cap.href_prefix):] if (cap.strip_prefix_in_key and cap.href_prefix) else href + segs = [s for s in src.strip('/').split('/') if s and not s.isdigit() and s != 'vs'] for desc in cap.entities: key_override = '_'.join(segs) + '_' + desc.key out.append(BoundEntity(href=href, capability=cap, desc=desc,