diff --git a/custom_components/localthings/registry/capabilities/fridge.py b/custom_components/localthings/registry/capabilities/fridge.py index 4de4582..fe79b0b 100644 --- a/custom_components/localthings/registry/capabilities/fridge.py +++ b/custom_components/localthings/registry/capabilities/fridge.py @@ -20,7 +20,32 @@ from ..entities import ( ) # Beverage zone flex modes. -_BZONE_MODES = ('SP_TTYPE_BEER_DRINKS', 'SP_TTYPE_WINE_DESSERT') +_BZONE_MODE_NAMES = { + 'SP_TTYPE_BEER_DRINKS': 'Beverage', + 'SP_TTYPE_WINE_DESSERT': 'Wine and Dessert', +} +_BZONE_MODES = tuple(_BZONE_MODE_NAMES) + +# Flex zone (convertible drawer) modes. +_FLEX_ZONE_MODE_NAMES = { + 'CV_TTYPE_RF9000A_FREEZE': 'Freeze', + 'CV_TTYPE_RF9000A_SOFTFREEZE': 'Soft Freeze', + 'CV_TTYPE_RF9000A_MEAT_FISH': 'Meat/Fish', + 'CV_TTYPE_RF9000A_FRUIT_VEGGIES': 'Fruit & Veggies', + 'CV_TTYPE_RF9000A_BEVERAGE': 'Beverage', +} + +# Icemaker ball-production rate options (whiskey icemaker models). +_ICE_TYPE_NAMES = { + 'WHISKEY_ICEBALL_3': '3 Balls/Day', + 'WHISKEY_ICEBALL_6': '6 Balls/Day', + 'WHISKEY_ICEBALL_9': '9 Balls/Day', +} + +_ICE_MAKING_STATUS_NAMES = { + 'ICESTATUS_STOP': 'Idle', + 'ICESTATUS_RUN': 'Making ice', +} def _int(v): @@ -102,17 +127,17 @@ ICEMAKER_GENERIC = Capability( entities=( SensorDesc(key='making_status', field='x.com.samsung.da.iceMaker.iceMakingStatus', - name=None, icon='mdi:cube-outline', - translation_key='ice_making_status'), + name='Making status', icon='mdi:cube-outline', + value_fn=lambda v: _ICE_MAKING_STATUS_NAMES.get(v, v)), SwitchDesc(key='enabled', field='x.com.samsung.da.iceMaker.state', name=None, icon='mdi:cube-outline', value_fn=lambda v: v == 'On', write_fn=_icemaker_write('x.com.samsung.da.iceMaker.state')), SelectDesc(key='type', field='x.com.samsung.da.iceType.desired', - name=None, icon='mdi:cube-outline', - translation_key='ice_type', + name='Ice type', icon='mdi:cube-outline', entity_category='config', options_field='x.com.samsung.da.iceType.supported', + option_names=_ICE_TYPE_NAMES, exists_fn=lambda rep: bool(rep.get('x.com.samsung.da.iceType.supported')), write_fn=_icemaker_write('x.com.samsung.da.iceType.desired')), ), @@ -468,9 +493,9 @@ BEVERAGE_ZONE = Capability( entities=( SelectDesc(key='beverage_zone_mode', field='roomDesiredMode', name='Beverage zone mode', icon='mdi:glass-wine', - translation_key='beverage_zone_mode', entity_category='config', - options=_BZONE_MODES, write_fn=_bzone_write), + options=_BZONE_MODES, option_names=_BZONE_MODE_NAMES, + write_fn=_bzone_write), ), ) @@ -496,9 +521,9 @@ FLEX_ZONE = Capability( SelectDesc(key='flex_zone_mode', field='x.com.samsung.da.modes', name='Flex zone mode', icon='mdi:thermostat', - translation_key='flex_zone_mode', entity_category='config', options_field='x.com.samsung.da.supportedOptions', + option_names=_FLEX_ZONE_MODE_NAMES, exists_fn=lambda rep: bool( rep.get('x.com.samsung.da.supportedOptions')), value_fn=lambda modes: next( diff --git a/custom_components/localthings/registry/entities.py b/custom_components/localthings/registry/entities.py index f606742..564c216 100644 --- a/custom_components/localthings/registry/entities.py +++ b/custom_components/localthings/registry/entities.py @@ -46,6 +46,7 @@ class BinarySensorDesc(SamsungEntityDescription): class SelectDesc(SamsungEntityDescription): options: Any = () # tuple[str,...] | Callable[[dict], list[str]] options_field: Optional[str] = None # resource field that contains the live options list + option_names: Optional[dict] = None # raw device value -> human-readable name write_fn: WriteFn = None diff --git a/custom_components/localthings/select.py b/custom_components/localthings/select.py index 8ffe47a..aa2829a 100644 --- a/custom_components/localthings/select.py +++ b/custom_components/localthings/select.py @@ -39,12 +39,24 @@ class LocalThingsSelect(LocalThingsEntity, SelectEntity): desc: SelectDesc = self._bound.desc if desc.options_field: rep = self.coordinator.last_resources.get(self._bound.href) or {} - return list(rep.get(desc.options_field) or []) - return self._attr_options + raw = list(rep.get(desc.options_field) or []) + else: + raw = self._attr_options + if desc.option_names: + return [desc.option_names.get(o, o) for o in raw] + return raw @property def current_option(self): - return (self.coordinator.data or {}).get(self._state_key) + desc: SelectDesc = self._bound.desc + raw = (self.coordinator.data or {}).get(self._state_key) + if desc.option_names: + return desc.option_names.get(raw, raw) + return raw async def async_select_option(self, option: str) -> None: + desc: SelectDesc = self._bound.desc + if desc.option_names: + reverse = {v: k for k, v in desc.option_names.items()} + option = reverse.get(option, option) await self.coordinator.async_send_command(self._bound, option) diff --git a/custom_components/localthings/strings.json b/custom_components/localthings/strings.json index 0eb9952..b09c50c 100644 --- a/custom_components/localthings/strings.json +++ b/custom_components/localthings/strings.json @@ -1,13 +1,5 @@ { "entity": { - "sensor": { - "ice_making_status": { - "state": { - "ICESTATUS_STOP": "Idle", - "ICESTATUS_RUN": "Making ice" - } - } - }, "select": { "door_alert": { "state": { @@ -23,28 +15,6 @@ "66": "Medium", "100": "High" } - }, - "ice_type": { - "state": { - "WHISKEY_ICEBALL_3": "3 Balls/Day", - "WHISKEY_ICEBALL_6": "6 Balls/Day", - "WHISKEY_ICEBALL_9": "9 Balls/Day" - } - }, - "beverage_zone_mode": { - "state": { - "SP_TTYPE_BEER_DRINKS": "Beverage", - "SP_TTYPE_WINE_DESSERT": "Wine and Dessert" - } - }, - "flex_zone_mode": { - "state": { - "CV_TTYPE_RF9000A_FREEZE": "Freeze", - "CV_TTYPE_RF9000A_SOFTFREEZE": "Soft Freeze", - "CV_TTYPE_RF9000A_MEAT_FISH": "Meat/Fish", - "CV_TTYPE_RF9000A_FRUIT_VEGGIES": "Fruit & Veggies", - "CV_TTYPE_RF9000A_BEVERAGE": "Beverage" - } } } }, diff --git a/custom_components/localthings/translations/en.json b/custom_components/localthings/translations/en.json index 0eb9952..b09c50c 100644 --- a/custom_components/localthings/translations/en.json +++ b/custom_components/localthings/translations/en.json @@ -1,13 +1,5 @@ { "entity": { - "sensor": { - "ice_making_status": { - "state": { - "ICESTATUS_STOP": "Idle", - "ICESTATUS_RUN": "Making ice" - } - } - }, "select": { "door_alert": { "state": { @@ -23,28 +15,6 @@ "66": "Medium", "100": "High" } - }, - "ice_type": { - "state": { - "WHISKEY_ICEBALL_3": "3 Balls/Day", - "WHISKEY_ICEBALL_6": "6 Balls/Day", - "WHISKEY_ICEBALL_9": "9 Balls/Day" - } - }, - "beverage_zone_mode": { - "state": { - "SP_TTYPE_BEER_DRINKS": "Beverage", - "SP_TTYPE_WINE_DESSERT": "Wine and Dessert" - } - }, - "flex_zone_mode": { - "state": { - "CV_TTYPE_RF9000A_FREEZE": "Freeze", - "CV_TTYPE_RF9000A_SOFTFREEZE": "Soft Freeze", - "CV_TTYPE_RF9000A_MEAT_FISH": "Meat/Fish", - "CV_TTYPE_RF9000A_FRUIT_VEGGIES": "Fruit & Veggies", - "CV_TTYPE_RF9000A_BEVERAGE": "Beverage" - } } } },