Add sw_version and model to flux_led device info (#56958)

This commit is contained in:
J. Nick Koston 2021-10-05 14:53:39 -10:00 committed by GitHub
parent 286ffb2d71
commit 7e5dfadc27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 32 deletions

View File

@ -140,3 +140,6 @@ class FluxLedUpdateCoordinator(DataUpdateCoordinator):
await self.hass.async_add_executor_job(self.device.update_state)
except FLUX_LED_EXCEPTIONS as ex:
raise UpdateFailed(ex) from ex
if not self.device.raw_state:
raise UpdateFailed("The device failed to update")

View File

@ -28,11 +28,11 @@ from homeassistant.components.light import (
LightEntity,
)
from homeassistant.const import (
ATTR_IDENTIFIERS,
ATTR_MANUFACTURER,
ATTR_MODE,
ATTR_MODEL,
ATTR_NAME,
ATTR_SW_VERSION,
CONF_DEVICES,
CONF_HOST,
CONF_MAC,
@ -41,9 +41,8 @@ from homeassistant.const import (
CONF_PROTOCOL,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_platform
from homeassistant.helpers import device_registry as dr, entity_platform
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.helpers.update_coordinator import CoordinatorEntity
@ -271,23 +270,22 @@ class FluxLight(CoordinatorEntity, LightEntity):
"""Initialize the light."""
super().__init__(coordinator)
self._bulb: WifiLedBulb = coordinator.device
self._name = name
self._unique_id = unique_id
self._attr_name = name
self._attr_unique_id = unique_id
self._ip_address = coordinator.host
self._mode = mode
self._custom_effect_colors = custom_effect_colors
self._custom_effect_speed_pct = custom_effect_speed_pct
self._custom_effect_transition = custom_effect_transition
@property
def unique_id(self) -> str | None:
"""Return the unique ID of the light."""
return self._unique_id
@property
def name(self) -> str:
"""Return the name of the device."""
return self._name
old_protocol = self._bulb.protocol == "LEDENET_ORIGINAL"
if self.unique_id:
self._attr_device_info = {
"connections": {(dr.CONNECTION_NETWORK_MAC, self.unique_id)},
ATTR_MODEL: f"0x{self._bulb.raw_state[1]:02X}",
ATTR_SW_VERSION: "1" if old_protocol else str(self._bulb.raw_state[10]),
ATTR_NAME: self.name,
ATTR_MANUFACTURER: "FluxLED/Magic Home",
}
@property
def is_on(self) -> bool:
@ -341,17 +339,6 @@ class FluxLight(CoordinatorEntity, LightEntity):
"ip_address": self._ip_address,
}
@property
def device_info(self) -> DeviceInfo:
"""Return the device information."""
assert self._unique_id is not None
return {
ATTR_IDENTIFIERS: {(DOMAIN, self._unique_id)},
ATTR_NAME: self._name,
ATTR_MANUFACTURER: "FluxLED/Magic Home",
ATTR_MODEL: "LED Lights",
}
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the specified or all lights on."""
await self.hass.async_add_executor_job(partial(self._turn_on, **kwargs))
@ -464,7 +451,7 @@ class FluxLight(CoordinatorEntity, LightEntity):
self._mode = MODE_RGB
_LOGGER.debug(
"Detected mode for %s (%s) with raw_state=%s rgbwcapable=%s is %s",
self._name,
self.name,
self.unique_id,
self._bulb.raw_state,
self._bulb.rgbwcapable,

View File

@ -36,6 +36,7 @@ def _mocked_bulb() -> WifiLedBulb:
bulb.getRgbw = MagicMock(return_value=[255, 0, 0, 50])
bulb.brightness = 128
bulb.rgbwcapable = True
bulb.raw_state = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
return bulb

View File

@ -11,7 +11,14 @@ from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from homeassistant.util.dt import utcnow
from . import FLUX_DISCOVERY, IP_ADDRESS, MAC_ADDRESS, _patch_discovery, _patch_wifibulb
from . import (
FLUX_DISCOVERY,
IP_ADDRESS,
MAC_ADDRESS,
_mocked_bulb,
_patch_discovery,
_patch_wifibulb,
)
from tests.common import MockConfigEntry, async_fire_time_changed
@ -56,3 +63,17 @@ async def test_config_entry_retry(hass: HomeAssistant) -> None:
await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}})
await hass.async_block_till_done()
assert config_entry.state == ConfigEntryState.SETUP_RETRY
async def test_config_entry_retry_when_state_missing(hass: HomeAssistant) -> None:
"""Test that a config entry is retried when state is missing."""
config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: IP_ADDRESS}, unique_id=MAC_ADDRESS
)
config_entry.add_to_hass(hass)
bulb = _mocked_bulb()
bulb.raw_state = None
with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb):
await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}})
await hass.async_block_till_done()
assert config_entry.state == ConfigEntryState.SETUP_RETRY

View File

@ -39,7 +39,7 @@ from homeassistant.const import (
STATE_ON,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from homeassistant.util.dt import utcnow
@ -93,6 +93,35 @@ async def test_light_no_unique_id(hass: HomeAssistant) -> None:
assert state.state == STATE_ON
@pytest.mark.parametrize(
"protocol,sw_version,model", [("LEDENET_ORIGINAL", 1, 0x35), ("LEDENET", 8, 0x33)]
)
async def test_light_device_registry(
hass: HomeAssistant, protocol: str, sw_version: int, model: int
) -> None:
"""Test a light device registry entry."""
config_entry = MockConfigEntry(
domain=DOMAIN,
data={CONF_HOST: IP_ADDRESS, CONF_NAME: DEFAULT_ENTRY_TITLE},
unique_id=MAC_ADDRESS,
)
config_entry.add_to_hass(hass)
bulb = _mocked_bulb()
bulb.protocol = protocol
bulb.raw_state[1] = model
bulb.raw_state[10] = sw_version
with _patch_discovery(no_device=True), _patch_wifibulb(device=bulb):
await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}})
await hass.async_block_till_done()
device_registry = dr.async_get(hass)
device = device_registry.async_get_device(
identifiers={}, connections={(dr.CONNECTION_NETWORK_MAC, MAC_ADDRESS)}
)
assert device.sw_version == str(sw_version)
assert device.model == f"0x{model:02X}"
async def test_rgb_light(hass: HomeAssistant) -> None:
"""Test an rgb light."""
config_entry = MockConfigEntry(
@ -276,7 +305,6 @@ async def test_rgbcw_light(hass: HomeAssistant) -> None:
)
config_entry.add_to_hass(hass)
bulb = _mocked_bulb()
bulb.raw_state = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
bulb.raw_state[9] = 1
bulb.raw_state[11] = 2
@ -466,7 +494,7 @@ async def test_rgb_light_custom_effects(
)
bulb.setCustomPattern.assert_called_with([[0, 0, 255], [255, 0, 0]], 88, "jump")
bulb.setCustomPattern.reset_mock()
bulb.raw_state = [0, 0, 0, EFFECT_CUSTOM_CODE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
bulb.raw_state[3] = EFFECT_CUSTOM_CODE
bulb.is_on = True
async_fire_time_changed(hass, utcnow() + timedelta(seconds=20))
await hass.async_block_till_done()
@ -484,7 +512,7 @@ async def test_rgb_light_custom_effects(
)
bulb.setCustomPattern.assert_called_with([[0, 0, 255], [255, 0, 0]], 88, "jump")
bulb.setCustomPattern.reset_mock()
bulb.raw_state = [0, 0, 0, EFFECT_CUSTOM_CODE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
bulb.raw_state[3] = EFFECT_CUSTOM_CODE
bulb.is_on = True
async_fire_time_changed(hass, utcnow() + timedelta(seconds=20))
await hass.async_block_till_done()