fix(fridge): translate enum select/sensor values in Python, not strings.json
hassfest rejects translation keys containing uppercase letters, but the raw Samsung enum values for flex zone, beverage zone, ice type, and ice making status are uppercase (e.g. CV_TTYPE_RF9000A_FREEZE). Follow the existing dryer-course pattern instead: map raw device values to human-readable names in Python via a new SelectDesc.option_names field (mirrored read/write in select.py) and a value_fn for the sensor, and drop the now-unused translation_key entries from strings.json/en.json.
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user