Add entity translations to WLED (#99056)

This commit is contained in:
Joost Lekkerkerker 2023-09-12 20:19:45 +02:00 committed by GitHub
parent 70c6bceaee
commit 9672cdf3a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 101 additions and 49 deletions

View File

@ -28,7 +28,6 @@ class WLEDRestartButton(WLEDEntity, ButtonEntity):
_attr_device_class = ButtonDeviceClass.RESTART
_attr_entity_category = EntityCategory.CONFIG
_attr_name = "Restart"
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
"""Initialize the button entity."""

View File

@ -46,7 +46,7 @@ class WLEDDataUpdateCoordinator(DataUpdateCoordinator[WLEDDevice]):
@property
def has_master_light(self) -> bool:
"""Return if the coordinated device has an master light."""
"""Return if the coordinated device has a master light."""
return self.keep_master_light or (
self.data is not None and len(self.data.state.segments) > 1
)

View File

@ -52,7 +52,7 @@ class WLEDMasterLight(WLEDEntity, LightEntity):
_attr_color_mode = ColorMode.BRIGHTNESS
_attr_icon = "mdi:led-strip-variant"
_attr_name = "Master"
_attr_translation_key = "main"
_attr_supported_features = LightEntityFeature.TRANSITION
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
@ -200,7 +200,7 @@ class WLEDSegmentLight(WLEDEntity, LightEntity):
# WLED uses 100ms per unit, so 10 = 1 second.
transition = round(kwargs[ATTR_TRANSITION] * 10)
# If there is no master control, and only 1 segment, handle the
# If there is no master control, and only 1 segment, handle the master
if not self.coordinator.has_master_light:
await self.coordinator.wled.master(on=False, transition=transition)
return

View File

@ -50,7 +50,6 @@ class WLEDLiveOverrideSelect(WLEDEntity, SelectEntity):
_attr_entity_category = EntityCategory.CONFIG
_attr_icon = "mdi:theater"
_attr_name = "Live override"
_attr_translation_key = "live_override"
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
@ -75,7 +74,7 @@ class WLEDPresetSelect(WLEDEntity, SelectEntity):
"""Defined a WLED Preset select."""
_attr_icon = "mdi:playlist-play"
_attr_name = "Preset"
_attr_translation_key = "preset"
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
"""Initialize WLED ."""
@ -106,7 +105,7 @@ class WLEDPlaylistSelect(WLEDEntity, SelectEntity):
"""Define a WLED Playlist select."""
_attr_icon = "mdi:play-speed"
_attr_name = "Playlist"
_attr_translation_key = "playlist"
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
"""Initialize WLED playlist."""

View File

@ -50,7 +50,7 @@ class WLEDSensorEntityDescription(
SENSORS: tuple[WLEDSensorEntityDescription, ...] = (
WLEDSensorEntityDescription(
key="estimated_current",
name="Estimated current",
translation_key="estimated_current",
native_unit_of_measurement=UnitOfElectricCurrent.MILLIAMPERE,
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
@ -60,13 +60,13 @@ SENSORS: tuple[WLEDSensorEntityDescription, ...] = (
),
WLEDSensorEntityDescription(
key="info_leds_count",
name="LED count",
translation_key="info_leds_count",
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda device: device.info.leds.count,
),
WLEDSensorEntityDescription(
key="info_leds_max_power",
name="Max current",
translation_key="info_leds_max_power",
native_unit_of_measurement=UnitOfElectricCurrent.MILLIAMPERE,
entity_category=EntityCategory.DIAGNOSTIC,
device_class=SensorDeviceClass.CURRENT,
@ -75,7 +75,7 @@ SENSORS: tuple[WLEDSensorEntityDescription, ...] = (
),
WLEDSensorEntityDescription(
key="uptime",
name="Uptime",
translation_key="uptime",
device_class=SensorDeviceClass.TIMESTAMP,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
@ -83,7 +83,7 @@ SENSORS: tuple[WLEDSensorEntityDescription, ...] = (
),
WLEDSensorEntityDescription(
key="free_heap",
name="Free memory",
translation_key="free_heap",
icon="mdi:memory",
native_unit_of_measurement=UnitOfInformation.BYTES,
state_class=SensorStateClass.MEASUREMENT,
@ -94,7 +94,7 @@ SENSORS: tuple[WLEDSensorEntityDescription, ...] = (
),
WLEDSensorEntityDescription(
key="wifi_signal",
name="Wi-Fi signal",
translation_key="wifi_signal",
icon="mdi:wifi",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
@ -104,7 +104,7 @@ SENSORS: tuple[WLEDSensorEntityDescription, ...] = (
),
WLEDSensorEntityDescription(
key="wifi_rssi",
name="Wi-Fi RSSI",
translation_key="wifi_rssi",
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
state_class=SensorStateClass.MEASUREMENT,
@ -114,7 +114,7 @@ SENSORS: tuple[WLEDSensorEntityDescription, ...] = (
),
WLEDSensorEntityDescription(
key="wifi_channel",
name="Wi-Fi channel",
translation_key="wifi_channel",
icon="mdi:wifi",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
@ -122,7 +122,7 @@ SENSORS: tuple[WLEDSensorEntityDescription, ...] = (
),
WLEDSensorEntityDescription(
key="wifi_bssid",
name="Wi-Fi BSSID",
translation_key="wifi_bssid",
icon="mdi:wifi",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
@ -130,7 +130,7 @@ SENSORS: tuple[WLEDSensorEntityDescription, ...] = (
),
WLEDSensorEntityDescription(
key="ip",
name="IP",
translation_key="ip",
icon="mdi:ip-network",
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda device: device.info.ip,

View File

@ -32,13 +32,68 @@
}
},
"entity": {
"light": {
"main": {
"name": "Main"
}
},
"select": {
"live_override": {
"name": "Live override",
"state": {
"0": "[%key:common::state::off%]",
"1": "[%key:common::state::on%]",
"2": "Until device restarts"
}
},
"preset": {
"name": "Preset"
},
"playlist": {
"name": "Playlist"
}
},
"sensor": {
"estimated_current": {
"name": "Estimated current"
},
"info_leds_count": {
"name": "LED count"
},
"info_leds_max_power": {
"name": "Max current"
},
"uptime": {
"name": "Uptime"
},
"free_heap": {
"name": "Free memory"
},
"wifi_signal": {
"name": "Wi-Fi signal"
},
"wifi_rssi": {
"name": "Wi-Fi RSSI"
},
"wifi_channel": {
"name": "Wi-Fi channel"
},
"wifi_bssid": {
"name": "Wi-Fi BSSID"
},
"ip": {
"name": "IP"
}
},
"switch": {
"nightlight": {
"name": "Nightlight"
},
"sync_send": {
"name": "Sync send"
},
"sync_receive": {
"name": "Sync receive"
}
}
},

View File

@ -55,7 +55,7 @@ class WLEDNightlightSwitch(WLEDEntity, SwitchEntity):
_attr_icon = "mdi:weather-night"
_attr_entity_category = EntityCategory.CONFIG
_attr_name = "Nightlight"
_attr_translation_key = "nightlight"
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
"""Initialize WLED nightlight switch."""
@ -93,7 +93,7 @@ class WLEDSyncSendSwitch(WLEDEntity, SwitchEntity):
_attr_icon = "mdi:upload-network-outline"
_attr_entity_category = EntityCategory.CONFIG
_attr_name = "Sync send"
_attr_translation_key = "sync_send"
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
"""Initialize WLED sync send switch."""
@ -126,7 +126,7 @@ class WLEDSyncReceiveSwitch(WLEDEntity, SwitchEntity):
_attr_icon = "mdi:download-network-outline"
_attr_entity_category = EntityCategory.CONFIG
_attr_name = "Sync receive"
_attr_translation_key = "sync_receive"
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
"""Initialize WLED sync receive switch."""

View File

@ -36,7 +36,6 @@ class WLEDUpdateEntity(WLEDEntity, UpdateEntity):
UpdateEntityFeature.INSTALL | UpdateEntityFeature.SPECIFIC_VERSION
)
_attr_title = "WLED"
_attr_name = "Firmware"
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
"""Initialize the update entity."""

View File

@ -310,7 +310,7 @@
'original_name': 'Playlist',
'platform': 'wled',
'supported_features': 0,
'translation_key': None,
'translation_key': 'playlist',
'unique_id': 'aabbccddee11_playlist',
'unit_of_measurement': None,
})
@ -393,7 +393,7 @@
'original_name': 'Preset',
'platform': 'wled',
'supported_features': 0,
'translation_key': None,
'translation_key': 'preset',
'unique_id': 'aabbccddee11_preset',
'unit_of_measurement': None,
})

View File

@ -40,7 +40,7 @@
'original_name': 'Nightlight',
'platform': 'wled',
'supported_features': 0,
'translation_key': None,
'translation_key': 'nightlight',
'unique_id': 'aabbccddeeff_nightlight',
'unit_of_measurement': None,
})
@ -189,7 +189,7 @@
'original_name': 'Sync receive',
'platform': 'wled',
'supported_features': 0,
'translation_key': None,
'translation_key': 'sync_receive',
'unique_id': 'aabbccddeeff_sync_receive',
'unit_of_measurement': None,
})
@ -264,7 +264,7 @@
'original_name': 'Sync send',
'platform': 'wled',
'supported_features': 0,
'translation_key': None,
'translation_key': 'sync_send',
'unique_id': 'aabbccddeeff_sync_send',
'unit_of_measurement': None,
})

View File

@ -60,12 +60,12 @@ async def test_rgb_light_state(
assert (entry := entity_registry.async_get("light.wled_rgb_light_segment_1"))
assert entry.unique_id == "aabbccddeeff_1"
# Test master control of the lightstrip
assert (state := hass.states.get("light.wled_rgb_light_master"))
# Test main control of the lightstrip
assert (state := hass.states.get("light.wled_rgb_light_main"))
assert state.attributes.get(ATTR_BRIGHTNESS) == 127
assert state.state == STATE_ON
assert (entry := entity_registry.async_get("light.wled_rgb_light_master"))
assert (entry := entity_registry.async_get("light.wled_rgb_light_main"))
assert entry.unique_id == "aabbccddeeff"
@ -110,15 +110,15 @@ async def test_segment_change_state(
)
async def test_master_change_state(
async def test_main_change_state(
hass: HomeAssistant,
mock_wled: MagicMock,
) -> None:
"""Test the change of state of the WLED master light control."""
"""Test the change of state of the WLED main light control."""
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "light.wled_rgb_light_master", ATTR_TRANSITION: 5},
{ATTR_ENTITY_ID: "light.wled_rgb_light_main", ATTR_TRANSITION: 5},
blocking=True,
)
assert mock_wled.master.call_count == 1
@ -132,7 +132,7 @@ async def test_master_change_state(
SERVICE_TURN_ON,
{
ATTR_BRIGHTNESS: 42,
ATTR_ENTITY_ID: "light.wled_rgb_light_master",
ATTR_ENTITY_ID: "light.wled_rgb_light_main",
ATTR_TRANSITION: 5,
},
blocking=True,
@ -147,7 +147,7 @@ async def test_master_change_state(
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "light.wled_rgb_light_master", ATTR_TRANSITION: 5},
{ATTR_ENTITY_ID: "light.wled_rgb_light_main", ATTR_TRANSITION: 5},
blocking=True,
)
assert mock_wled.master.call_count == 3
@ -161,7 +161,7 @@ async def test_master_change_state(
SERVICE_TURN_ON,
{
ATTR_BRIGHTNESS: 42,
ATTR_ENTITY_ID: "light.wled_rgb_light_master",
ATTR_ENTITY_ID: "light.wled_rgb_light_main",
ATTR_TRANSITION: 5,
},
blocking=True,
@ -183,7 +183,7 @@ async def test_dynamically_handle_segments(
"""Test if a new/deleted segment is dynamically added/removed."""
assert (segment0 := hass.states.get("light.wled_rgb_light"))
assert segment0.state == STATE_ON
assert not hass.states.get("light.wled_rgb_light_master")
assert not hass.states.get("light.wled_rgb_light_main")
assert not hass.states.get("light.wled_rgb_light_segment_1")
return_value = mock_wled.update.return_value
@ -195,21 +195,21 @@ async def test_dynamically_handle_segments(
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert (master := hass.states.get("light.wled_rgb_light_master"))
assert master.state == STATE_ON
assert (main := hass.states.get("light.wled_rgb_light_main"))
assert main.state == STATE_ON
assert (segment0 := hass.states.get("light.wled_rgb_light"))
assert segment0.state == STATE_ON
assert (segment1 := hass.states.get("light.wled_rgb_light_segment_1"))
assert segment1.state == STATE_ON
# Test adding if segment shows up again, including the master entity
# Test adding if segment shows up again, including the main entity
mock_wled.update.return_value = return_value
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert (master := hass.states.get("light.wled_rgb_light_master"))
assert master.state == STATE_UNAVAILABLE
assert (main := hass.states.get("light.wled_rgb_light_main"))
assert main.state == STATE_UNAVAILABLE
assert (segment0 := hass.states.get("light.wled_rgb_light"))
assert segment0.state == STATE_ON
assert (segment1 := hass.states.get("light.wled_rgb_light_segment_1"))
@ -225,11 +225,11 @@ async def test_single_segment_behavior(
"""Test the behavior of the integration with a single segment."""
device = mock_wled.update.return_value
assert not hass.states.get("light.wled_rgb_light_master")
assert not hass.states.get("light.wled_rgb_light_main")
assert (state := hass.states.get("light.wled_rgb_light"))
assert state.state == STATE_ON
# Test segment brightness takes master into account
# Test segment brightness takes main into account
device.state.brightness = 100
device.state.segments[0].brightness = 255
freezer.tick(SCAN_INTERVAL)
@ -239,7 +239,7 @@ async def test_single_segment_behavior(
assert (state := hass.states.get("light.wled_rgb_light"))
assert state.attributes.get(ATTR_BRIGHTNESS) == 100
# Test segment is off when master is off
# Test segment is off when main is off
device.state.on = False
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
@ -248,7 +248,7 @@ async def test_single_segment_behavior(
assert state
assert state.state == STATE_OFF
# Test master is turned off when turning off a single segment
# Test main is turned off when turning off a single segment
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
@ -261,7 +261,7 @@ async def test_single_segment_behavior(
transition=50,
)
# Test master is turned on when turning on a single segment, and segment
# Test main is turned on when turning on a single segment, and segment
# brightness is set to 255.
await hass.services.async_call(
LIGHT_DOMAIN,
@ -346,18 +346,18 @@ async def test_rgbw_light(hass: HomeAssistant, mock_wled: MagicMock) -> None:
@pytest.mark.parametrize("device_fixture", ["rgb_single_segment"])
async def test_single_segment_with_keep_master_light(
async def test_single_segment_with_keep_main_light(
hass: HomeAssistant,
init_integration: MockConfigEntry,
mock_wled: MagicMock,
) -> None:
"""Test the behavior of the integration with a single segment."""
assert not hass.states.get("light.wled_rgb_light_master")
assert not hass.states.get("light.wled_rgb_light_main")
hass.config_entries.async_update_entry(
init_integration, options={CONF_KEEP_MASTER_LIGHT: True}
)
await hass.async_block_till_done()
assert (state := hass.states.get("light.wled_rgb_light_master"))
assert (state := hass.states.get("light.wled_rgb_light_main"))
assert state.state == STATE_ON