Add entity translations to Flux led (#95355)
This commit is contained in:
parent
90854df5b2
commit
e19b29d6ae
8 changed files with 104 additions and 53 deletions
|
@ -10,7 +10,7 @@ from homeassistant.components.button import (
|
|||
ButtonEntity,
|
||||
ButtonEntityDescription,
|
||||
)
|
||||
from homeassistant.const import CONF_NAME, EntityCategory
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
|
@ -22,10 +22,13 @@ _RESTART_KEY = "restart"
|
|||
_UNPAIR_REMOTES_KEY = "unpair_remotes"
|
||||
|
||||
RESTART_BUTTON_DESCRIPTION = ButtonEntityDescription(
|
||||
key=_RESTART_KEY, name="Restart", device_class=ButtonDeviceClass.RESTART
|
||||
key=_RESTART_KEY,
|
||||
device_class=ButtonDeviceClass.RESTART,
|
||||
)
|
||||
UNPAIR_REMOTES_DESCRIPTION = ButtonEntityDescription(
|
||||
key=_UNPAIR_REMOTES_KEY, name="Unpair Remotes", icon="mdi:remote-off"
|
||||
key=_UNPAIR_REMOTES_KEY,
|
||||
translation_key="unpair_remotes",
|
||||
icon="mdi:remote-off",
|
||||
)
|
||||
|
||||
|
||||
|
@ -62,7 +65,6 @@ class FluxButton(FluxBaseEntity, ButtonEntity):
|
|||
"""Initialize the button."""
|
||||
self.entity_description = description
|
||||
super().__init__(device, entry)
|
||||
self._attr_name = f"{entry.data.get(CONF_NAME, entry.title)} {description.name}"
|
||||
base_unique_id = entry.unique_id or entry.entry_id
|
||||
self._attr_unique_id = f"{base_unique_id}_{description.key}"
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ def _async_device_info(
|
|||
class FluxBaseEntity(Entity):
|
||||
"""Representation of a Flux entity without a coordinator."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
_attr_should_poll = False
|
||||
|
||||
def __init__(
|
||||
|
@ -70,18 +71,18 @@ class FluxBaseEntity(Entity):
|
|||
class FluxEntity(CoordinatorEntity[FluxLedUpdateCoordinator]):
|
||||
"""Representation of a Flux entity with a coordinator."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: FluxLedUpdateCoordinator,
|
||||
base_unique_id: str,
|
||||
name: str,
|
||||
key: str | None,
|
||||
) -> None:
|
||||
"""Initialize the light."""
|
||||
super().__init__(coordinator)
|
||||
self._device: AIOWifiLedBulb = coordinator.device
|
||||
self._responding = True
|
||||
self._attr_name = name
|
||||
if key:
|
||||
self._attr_unique_id = f"{base_unique_id}_{key}"
|
||||
else:
|
||||
|
|
|
@ -22,7 +22,6 @@ from homeassistant.components.light import (
|
|||
LightEntity,
|
||||
LightEntityFeature,
|
||||
)
|
||||
from homeassistant.const import CONF_NAME
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import entity_platform
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
@ -177,7 +176,6 @@ async def async_setup_entry(
|
|||
FluxLight(
|
||||
coordinator,
|
||||
entry.unique_id or entry.entry_id,
|
||||
entry.data.get(CONF_NAME, entry.title),
|
||||
list(custom_effect_colors),
|
||||
options.get(CONF_CUSTOM_EFFECT_SPEED_PCT, DEFAULT_EFFECT_SPEED),
|
||||
options.get(CONF_CUSTOM_EFFECT_TRANSITION, TRANSITION_GRADUAL),
|
||||
|
@ -191,19 +189,20 @@ class FluxLight(
|
|||
):
|
||||
"""Representation of a Flux light."""
|
||||
|
||||
_attr_name = None
|
||||
|
||||
_attr_supported_features = LightEntityFeature.TRANSITION | LightEntityFeature.EFFECT
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: FluxLedUpdateCoordinator,
|
||||
base_unique_id: str,
|
||||
name: str,
|
||||
custom_effect_colors: list[tuple[int, int, int]],
|
||||
custom_effect_speed_pct: int,
|
||||
custom_effect_transition: str,
|
||||
) -> None:
|
||||
"""Initialize the light."""
|
||||
super().__init__(coordinator, base_unique_id, name, None)
|
||||
super().__init__(coordinator, base_unique_id, None)
|
||||
self._attr_min_mireds = color_temperature_kelvin_to_mired(self._device.max_temp)
|
||||
self._attr_max_mireds = color_temperature_kelvin_to_mired(self._device.min_temp)
|
||||
self._attr_supported_color_modes = _hass_color_modes(self._device)
|
||||
|
|
|
@ -18,7 +18,7 @@ from flux_led.protocol import (
|
|||
from homeassistant import config_entries
|
||||
from homeassistant.components.light import EFFECT_RANDOM
|
||||
from homeassistant.components.number import NumberEntity, NumberMode
|
||||
from homeassistant.const import CONF_NAME, EntityCategory
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.debounce import Debouncer
|
||||
|
@ -50,7 +50,6 @@ async def async_setup_entry(
|
|||
| FluxMusicPixelsPerSegmentNumber
|
||||
| FluxMusicSegmentsNumber
|
||||
] = []
|
||||
name = entry.data.get(CONF_NAME, entry.title)
|
||||
base_unique_id = entry.unique_id or entry.entry_id
|
||||
|
||||
if device.pixels_per_segment is not None:
|
||||
|
@ -58,35 +57,25 @@ async def async_setup_entry(
|
|||
FluxPixelsPerSegmentNumber(
|
||||
coordinator,
|
||||
base_unique_id,
|
||||
f"{name} Pixels Per Segment",
|
||||
"pixels_per_segment",
|
||||
)
|
||||
)
|
||||
if device.segments is not None:
|
||||
entities.append(
|
||||
FluxSegmentsNumber(
|
||||
coordinator, base_unique_id, f"{name} Segments", "segments"
|
||||
)
|
||||
)
|
||||
entities.append(FluxSegmentsNumber(coordinator, base_unique_id, "segments"))
|
||||
if device.music_pixels_per_segment is not None:
|
||||
entities.append(
|
||||
FluxMusicPixelsPerSegmentNumber(
|
||||
coordinator,
|
||||
base_unique_id,
|
||||
f"{name} Music Pixels Per Segment",
|
||||
"music_pixels_per_segment",
|
||||
)
|
||||
)
|
||||
if device.music_segments is not None:
|
||||
entities.append(
|
||||
FluxMusicSegmentsNumber(
|
||||
coordinator, base_unique_id, f"{name} Music Segments", "music_segments"
|
||||
)
|
||||
FluxMusicSegmentsNumber(coordinator, base_unique_id, "music_segments")
|
||||
)
|
||||
if device.effect_list and device.effect_list != [EFFECT_RANDOM]:
|
||||
entities.append(
|
||||
FluxSpeedNumber(coordinator, base_unique_id, f"{name} Effect Speed", None)
|
||||
)
|
||||
entities.append(FluxSpeedNumber(coordinator, base_unique_id, None))
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
@ -101,6 +90,7 @@ class FluxSpeedNumber(
|
|||
_attr_native_step = 1
|
||||
_attr_mode = NumberMode.SLIDER
|
||||
_attr_icon = "mdi:speedometer"
|
||||
_attr_translation_key = "effect_speed"
|
||||
|
||||
@property
|
||||
def native_value(self) -> float:
|
||||
|
@ -137,11 +127,10 @@ class FluxConfigNumber(
|
|||
self,
|
||||
coordinator: FluxLedUpdateCoordinator,
|
||||
base_unique_id: str,
|
||||
name: str,
|
||||
key: str | None,
|
||||
) -> None:
|
||||
"""Initialize the flux number."""
|
||||
super().__init__(coordinator, base_unique_id, name, key)
|
||||
super().__init__(coordinator, base_unique_id, key)
|
||||
self._debouncer: Debouncer[Coroutine[Any, Any, None]] | None = None
|
||||
self._pending_value: int | None = None
|
||||
|
||||
|
@ -185,6 +174,7 @@ class FluxConfigNumber(
|
|||
class FluxPixelsPerSegmentNumber(FluxConfigNumber):
|
||||
"""Defines a flux_led pixels per segment number."""
|
||||
|
||||
_attr_translation_key = "pixels_per_segment"
|
||||
_attr_icon = "mdi:dots-grid"
|
||||
|
||||
@property
|
||||
|
@ -211,6 +201,7 @@ class FluxPixelsPerSegmentNumber(FluxConfigNumber):
|
|||
class FluxSegmentsNumber(FluxConfigNumber):
|
||||
"""Defines a flux_led segments number."""
|
||||
|
||||
_attr_translation_key = "segments"
|
||||
_attr_icon = "mdi:segment"
|
||||
|
||||
@property
|
||||
|
@ -245,6 +236,7 @@ class FluxMusicNumber(FluxConfigNumber):
|
|||
class FluxMusicPixelsPerSegmentNumber(FluxMusicNumber):
|
||||
"""Defines a flux_led music pixels per segment number."""
|
||||
|
||||
_attr_translation_key = "music_pixels_per_segment"
|
||||
_attr_icon = "mdi:dots-grid"
|
||||
|
||||
@property
|
||||
|
@ -273,6 +265,7 @@ class FluxMusicPixelsPerSegmentNumber(FluxMusicNumber):
|
|||
class FluxMusicSegmentsNumber(FluxMusicNumber):
|
||||
"""Defines a flux_led music segments number."""
|
||||
|
||||
_attr_translation_key = "music_segments"
|
||||
_attr_icon = "mdi:segment"
|
||||
|
||||
@property
|
||||
|
|
|
@ -52,30 +52,22 @@ async def async_setup_entry(
|
|||
| FluxRemoteConfigSelect
|
||||
| FluxWhiteChannelSelect
|
||||
] = []
|
||||
name = entry.data.get(CONF_NAME, entry.title)
|
||||
entry.data.get(CONF_NAME, entry.title)
|
||||
base_unique_id = entry.unique_id or entry.entry_id
|
||||
|
||||
if device.device_type == DeviceType.Switch:
|
||||
entities.append(FluxPowerStateSelect(coordinator.device, entry))
|
||||
if device.operating_modes:
|
||||
entities.append(
|
||||
FluxOperatingModesSelect(
|
||||
coordinator, base_unique_id, f"{name} Operating Mode", "operating_mode"
|
||||
)
|
||||
FluxOperatingModesSelect(coordinator, base_unique_id, "operating_mode")
|
||||
)
|
||||
if device.wirings and device.wiring is not None:
|
||||
entities.append(
|
||||
FluxWiringsSelect(coordinator, base_unique_id, f"{name} Wiring", "wiring")
|
||||
)
|
||||
entities.append(FluxWiringsSelect(coordinator, base_unique_id, "wiring"))
|
||||
if device.ic_types:
|
||||
entities.append(
|
||||
FluxICTypeSelect(coordinator, base_unique_id, f"{name} IC Type", "ic_type")
|
||||
)
|
||||
entities.append(FluxICTypeSelect(coordinator, base_unique_id, "ic_type"))
|
||||
if device.remote_config:
|
||||
entities.append(
|
||||
FluxRemoteConfigSelect(
|
||||
coordinator, base_unique_id, f"{name} Remote Config", "remote_config"
|
||||
)
|
||||
FluxRemoteConfigSelect(coordinator, base_unique_id, "remote_config")
|
||||
)
|
||||
if FLUX_COLOR_MODE_RGBW in device.color_modes:
|
||||
entities.append(FluxWhiteChannelSelect(coordinator.device, entry))
|
||||
|
@ -98,6 +90,7 @@ class FluxConfigSelect(FluxEntity, SelectEntity):
|
|||
class FluxPowerStateSelect(FluxConfigAtStartSelect, SelectEntity):
|
||||
"""Representation of a Flux power restore state option."""
|
||||
|
||||
_attr_translation_key = "power_restored"
|
||||
_attr_icon = "mdi:transmission-tower-off"
|
||||
_attr_options = list(NAME_TO_POWER_RESTORE_STATE)
|
||||
|
||||
|
@ -108,7 +101,6 @@ class FluxPowerStateSelect(FluxConfigAtStartSelect, SelectEntity):
|
|||
) -> None:
|
||||
"""Initialize the power state select."""
|
||||
super().__init__(device, entry)
|
||||
self._attr_name = f"{entry.data.get(CONF_NAME, entry.title)} Power Restored"
|
||||
base_unique_id = entry.unique_id or entry.entry_id
|
||||
self._attr_unique_id = f"{base_unique_id}_power_restored"
|
||||
self._async_set_current_option_from_device()
|
||||
|
@ -134,6 +126,7 @@ class FluxICTypeSelect(FluxConfigSelect):
|
|||
"""Representation of Flux ic type."""
|
||||
|
||||
_attr_icon = "mdi:chip"
|
||||
_attr_translation_key = "ic_type"
|
||||
|
||||
@property
|
||||
def options(self) -> list[str]:
|
||||
|
@ -156,6 +149,7 @@ class FluxWiringsSelect(FluxConfigSelect):
|
|||
"""Representation of Flux wirings."""
|
||||
|
||||
_attr_icon = "mdi:led-strip-variant"
|
||||
_attr_translation_key = "wiring"
|
||||
|
||||
@property
|
||||
def options(self) -> list[str]:
|
||||
|
@ -176,6 +170,8 @@ class FluxWiringsSelect(FluxConfigSelect):
|
|||
class FluxOperatingModesSelect(FluxConfigSelect):
|
||||
"""Representation of Flux operating modes."""
|
||||
|
||||
_attr_translation_key = "operating_mode"
|
||||
|
||||
@property
|
||||
def options(self) -> list[str]:
|
||||
"""Return the current operating mode."""
|
||||
|
@ -196,15 +192,16 @@ class FluxOperatingModesSelect(FluxConfigSelect):
|
|||
class FluxRemoteConfigSelect(FluxConfigSelect):
|
||||
"""Representation of Flux remote config type."""
|
||||
|
||||
_attr_translation_key = "remote_config"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: FluxLedUpdateCoordinator,
|
||||
base_unique_id: str,
|
||||
name: str,
|
||||
key: str,
|
||||
) -> None:
|
||||
"""Initialize the remote config type select."""
|
||||
super().__init__(coordinator, base_unique_id, name, key)
|
||||
super().__init__(coordinator, base_unique_id, key)
|
||||
assert self._device.remote_config is not None
|
||||
self._name_to_state = {
|
||||
_human_readable_option(option.name): option for option in RemoteConfig
|
||||
|
@ -226,6 +223,8 @@ class FluxRemoteConfigSelect(FluxConfigSelect):
|
|||
class FluxWhiteChannelSelect(FluxConfigAtStartSelect):
|
||||
"""Representation of Flux white channel."""
|
||||
|
||||
_attr_translation_key = "white_channel"
|
||||
|
||||
_attr_options = [_human_readable_option(option.name) for option in WhiteChannelType]
|
||||
|
||||
def __init__(
|
||||
|
@ -235,7 +234,6 @@ class FluxWhiteChannelSelect(FluxConfigAtStartSelect):
|
|||
) -> None:
|
||||
"""Initialize the white channel select."""
|
||||
super().__init__(device, entry)
|
||||
self._attr_name = f"{entry.data.get(CONF_NAME, entry.title)} White Channel"
|
||||
base_unique_id = entry.unique_id or entry.entry_id
|
||||
self._attr_unique_id = f"{base_unique_id}_white_channel"
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.sensor import SensorEntity
|
||||
from homeassistant.const import CONF_NAME, EntityCategory
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
|
@ -25,7 +25,6 @@ async def async_setup_entry(
|
|||
FluxPairedRemotes(
|
||||
coordinator,
|
||||
entry.unique_id or entry.entry_id,
|
||||
f"{entry.data.get(CONF_NAME, entry.title)} Paired Remotes",
|
||||
"paired_remotes",
|
||||
)
|
||||
]
|
||||
|
@ -37,6 +36,7 @@ class FluxPairedRemotes(FluxEntity, SensorEntity):
|
|||
|
||||
_attr_icon = "mdi:remote"
|
||||
_attr_entity_category = EntityCategory.DIAGNOSTIC
|
||||
_attr_translation_key = "paired_remotes"
|
||||
|
||||
@property
|
||||
def native_value(self) -> int:
|
||||
|
|
|
@ -32,5 +32,62 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"button": {
|
||||
"unpair_remotes": {
|
||||
"name": "Unpair remotes"
|
||||
}
|
||||
},
|
||||
"number": {
|
||||
"pixels_per_segment": {
|
||||
"name": "Pixels per segment"
|
||||
},
|
||||
"segments": {
|
||||
"name": "Segments"
|
||||
},
|
||||
"music_pixels_per_segment": {
|
||||
"name": "Music pixels per segment"
|
||||
},
|
||||
"music_segments": {
|
||||
"name": "Music segments"
|
||||
},
|
||||
"effect_speed": {
|
||||
"name": "Effect speed"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"operating_mode": {
|
||||
"name": "Operating mode"
|
||||
},
|
||||
"wiring": {
|
||||
"name": "Wiring"
|
||||
},
|
||||
"ic_type": {
|
||||
"name": "IC type"
|
||||
},
|
||||
"remote_config": {
|
||||
"name": "Remote config"
|
||||
},
|
||||
"white_channel": {
|
||||
"name": "White channel"
|
||||
},
|
||||
"power_restored": {
|
||||
"name": "Power restored"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"paired_remotes": {
|
||||
"name": "Paired remotes"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"remote_access": {
|
||||
"name": "Remote access"
|
||||
},
|
||||
"music": {
|
||||
"name": "Music"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ from flux_led.const import MODE_MUSIC
|
|||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.switch import SwitchEntity
|
||||
from homeassistant.const import CONF_NAME, EntityCategory
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
@ -34,18 +34,15 @@ async def async_setup_entry(
|
|||
coordinator: FluxLedUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
entities: list[FluxSwitch | FluxRemoteAccessSwitch | FluxMusicSwitch] = []
|
||||
base_unique_id = entry.unique_id or entry.entry_id
|
||||
name = entry.data.get(CONF_NAME, entry.title)
|
||||
|
||||
if coordinator.device.device_type == DeviceType.Switch:
|
||||
entities.append(FluxSwitch(coordinator, base_unique_id, name, None))
|
||||
entities.append(FluxSwitch(coordinator, base_unique_id, None))
|
||||
|
||||
if entry.data.get(CONF_REMOTE_ACCESS_HOST):
|
||||
entities.append(FluxRemoteAccessSwitch(coordinator.device, entry))
|
||||
|
||||
if coordinator.device.microphone:
|
||||
entities.append(
|
||||
FluxMusicSwitch(coordinator, base_unique_id, f"{name} Music", "music")
|
||||
)
|
||||
entities.append(FluxMusicSwitch(coordinator, base_unique_id, "music"))
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
@ -55,6 +52,8 @@ class FluxSwitch(
|
|||
):
|
||||
"""Representation of a Flux switch."""
|
||||
|
||||
_attr_name = None
|
||||
|
||||
async def _async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the device on."""
|
||||
if not self.is_on:
|
||||
|
@ -65,6 +64,7 @@ class FluxRemoteAccessSwitch(FluxBaseEntity, SwitchEntity):
|
|||
"""Representation of a Flux remote access switch."""
|
||||
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
_attr_translation_key = "remote_access"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -73,7 +73,6 @@ class FluxRemoteAccessSwitch(FluxBaseEntity, SwitchEntity):
|
|||
) -> None:
|
||||
"""Initialize the light."""
|
||||
super().__init__(device, entry)
|
||||
self._attr_name = f"{entry.data.get(CONF_NAME, entry.title)} Remote Access"
|
||||
base_unique_id = entry.unique_id or entry.entry_id
|
||||
self._attr_unique_id = f"{base_unique_id}_remote_access"
|
||||
|
||||
|
@ -113,6 +112,8 @@ class FluxRemoteAccessSwitch(FluxBaseEntity, SwitchEntity):
|
|||
class FluxMusicSwitch(FluxEntity, SwitchEntity):
|
||||
"""Representation of a Flux music switch."""
|
||||
|
||||
_attr_translation_key = "music"
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the microphone on."""
|
||||
await self._async_ensure_device_on()
|
||||
|
|
Loading…
Add table
Reference in a new issue