mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Add device-specific diagnostics to the LIFX integration (#79964)
This commit is contained in:
parent
3c170f7627
commit
6e453ae471
@ -12,6 +12,7 @@ MESSAGE_RETRIES = 5
|
|||||||
OVERALL_TIMEOUT = 9
|
OVERALL_TIMEOUT = 9
|
||||||
UNAVAILABLE_GRACE = 90
|
UNAVAILABLE_GRACE = 90
|
||||||
|
|
||||||
|
CONF_LABEL = "label"
|
||||||
CONF_SERIAL = "serial"
|
CONF_SERIAL = "serial"
|
||||||
|
|
||||||
IDENTIFY_WAVEFORM = {
|
IDENTIFY_WAVEFORM = {
|
||||||
|
@ -117,6 +117,44 @@ class LIFXUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
"""Return the current infrared brightness as a string."""
|
"""Return the current infrared brightness as a string."""
|
||||||
return infrared_brightness_value_to_option(self.device.infrared_brightness)
|
return infrared_brightness_value_to_option(self.device.infrared_brightness)
|
||||||
|
|
||||||
|
async def diagnostics(self) -> dict[str, Any]:
|
||||||
|
"""Return diagnostic information about the device."""
|
||||||
|
features = lifx_features(self.device)
|
||||||
|
device_data = {
|
||||||
|
"firmware": self.device.host_firmware_version,
|
||||||
|
"vendor": self.device.vendor,
|
||||||
|
"product_id": self.device.product,
|
||||||
|
"features": features,
|
||||||
|
"hue": self.device.color[0],
|
||||||
|
"saturation": self.device.color[1],
|
||||||
|
"brightness": self.device.color[2],
|
||||||
|
"kelvin": self.device.color[3],
|
||||||
|
"power": self.device.power_level,
|
||||||
|
}
|
||||||
|
|
||||||
|
if features["multizone"] is True:
|
||||||
|
zones = {"count": self.device.zones_count, "state": {}}
|
||||||
|
for index, zone_color in enumerate(self.device.color_zones):
|
||||||
|
zones["state"][index] = {
|
||||||
|
"hue": zone_color[0],
|
||||||
|
"saturation": zone_color[1],
|
||||||
|
"brightness": zone_color[2],
|
||||||
|
"kelvin": zone_color[3],
|
||||||
|
}
|
||||||
|
device_data["zones"] = zones
|
||||||
|
|
||||||
|
if features["hev"] is True:
|
||||||
|
device_data["hev"] = {
|
||||||
|
"hev_cycle": self.device.hev_cycle,
|
||||||
|
"hev_config": self.device.hev_cycle_configuration,
|
||||||
|
"last_result": self.device.last_hev_cycle_result,
|
||||||
|
}
|
||||||
|
|
||||||
|
if features["infrared"] is True:
|
||||||
|
device_data["infrared"] = {"brightness": self.device.infrared_brightness}
|
||||||
|
|
||||||
|
return device_data
|
||||||
|
|
||||||
def async_get_entity_id(self, platform: Platform, key: str) -> str | None:
|
def async_get_entity_id(self, platform: Platform, key: str) -> str | None:
|
||||||
"""Return the entity_id from the platform and key provided."""
|
"""Return the entity_id from the platform and key provided."""
|
||||||
ent_reg = er.async_get(self.hass)
|
ent_reg = er.async_get(self.hass)
|
||||||
|
28
homeassistant/components/lifx/diagnostics.py
Normal file
28
homeassistant/components/lifx/diagnostics.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
"""Diagnostics support for LIFX."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from homeassistant.components.diagnostics import async_redact_data
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import CONF_HOST, CONF_IP_ADDRESS, CONF_MAC
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from .const import CONF_LABEL, DOMAIN
|
||||||
|
from .coordinator import LIFXUpdateCoordinator
|
||||||
|
|
||||||
|
TO_REDACT = [CONF_LABEL, CONF_HOST, CONF_IP_ADDRESS, CONF_MAC]
|
||||||
|
|
||||||
|
|
||||||
|
async def async_get_config_entry_diagnostics(
|
||||||
|
hass: HomeAssistant, entry: ConfigEntry
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
"""Return diagnostics for a LIFX config entry."""
|
||||||
|
coordinator: LIFXUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
return {
|
||||||
|
"entry": {
|
||||||
|
"title": entry.title,
|
||||||
|
"data": async_redact_data(dict(entry.data), TO_REDACT),
|
||||||
|
},
|
||||||
|
"data": async_redact_data(await coordinator.diagnostics(), TO_REDACT),
|
||||||
|
}
|
@ -123,12 +123,15 @@ def _mocked_clean_bulb() -> Light:
|
|||||||
bulb = _mocked_bulb()
|
bulb = _mocked_bulb()
|
||||||
bulb.get_hev_cycle = MockLifxCommand(bulb)
|
bulb.get_hev_cycle = MockLifxCommand(bulb)
|
||||||
bulb.set_hev_cycle = MockLifxCommand(bulb)
|
bulb.set_hev_cycle = MockLifxCommand(bulb)
|
||||||
|
bulb.get_hev_configuration = MockLifxCommand(bulb)
|
||||||
|
bulb.get_last_hev_cycle_result = MockLifxCommand(bulb)
|
||||||
bulb.hev_cycle_configuration = {"duration": 7200, "indication": False}
|
bulb.hev_cycle_configuration = {"duration": 7200, "indication": False}
|
||||||
bulb.hev_cycle = {
|
bulb.hev_cycle = {
|
||||||
"duration": 7200,
|
"duration": 7200,
|
||||||
"remaining": 30,
|
"remaining": 30,
|
||||||
"last_power": False,
|
"last_power": False,
|
||||||
}
|
}
|
||||||
|
bulb.last_hev_cycle_result = 0
|
||||||
bulb.product = 90
|
bulb.product = 90
|
||||||
return bulb
|
return bulb
|
||||||
|
|
||||||
|
385
tests/components/lifx/test_diagnostics.py
Normal file
385
tests/components/lifx/test_diagnostics.py
Normal file
@ -0,0 +1,385 @@
|
|||||||
|
"""Test LIFX diagnostics."""
|
||||||
|
from homeassistant.components import lifx
|
||||||
|
from homeassistant.const import CONF_HOST
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
|
from . import (
|
||||||
|
DEFAULT_ENTRY_TITLE,
|
||||||
|
IP_ADDRESS,
|
||||||
|
MAC_ADDRESS,
|
||||||
|
_mocked_bulb,
|
||||||
|
_mocked_clean_bulb,
|
||||||
|
_mocked_infrared_bulb,
|
||||||
|
_mocked_light_strip,
|
||||||
|
_patch_config_flow_try_connect,
|
||||||
|
_patch_device,
|
||||||
|
_patch_discovery,
|
||||||
|
)
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||||
|
|
||||||
|
|
||||||
|
async def test_bulb_diagnostics(hass: HomeAssistant, hass_client) -> None:
|
||||||
|
"""Test diagnostics for a standard bulb."""
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
domain=lifx.DOMAIN,
|
||||||
|
title=DEFAULT_ENTRY_TITLE,
|
||||||
|
data={CONF_HOST: IP_ADDRESS},
|
||||||
|
unique_id=MAC_ADDRESS,
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
bulb = _mocked_bulb()
|
||||||
|
with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
|
||||||
|
device=bulb
|
||||||
|
), _patch_device(device=bulb):
|
||||||
|
await async_setup_component(hass, lifx.DOMAIN, {lifx.DOMAIN: {}})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
diag = await get_diagnostics_for_config_entry(hass, hass_client, config_entry)
|
||||||
|
assert diag == {
|
||||||
|
"data": {
|
||||||
|
"brightness": 3,
|
||||||
|
"features": {
|
||||||
|
"buttons": False,
|
||||||
|
"chain": False,
|
||||||
|
"color": True,
|
||||||
|
"extended_multizone": False,
|
||||||
|
"hev": False,
|
||||||
|
"infrared": False,
|
||||||
|
"matrix": False,
|
||||||
|
"max_kelvin": 9000,
|
||||||
|
"min_kelvin": 2500,
|
||||||
|
"multizone": False,
|
||||||
|
"relays": False,
|
||||||
|
},
|
||||||
|
"firmware": "3.00",
|
||||||
|
"hue": 1,
|
||||||
|
"kelvin": 4,
|
||||||
|
"power": 0,
|
||||||
|
"product_id": 1,
|
||||||
|
"saturation": 2,
|
||||||
|
"vendor": None,
|
||||||
|
},
|
||||||
|
"entry": {"data": {"host": "**REDACTED**"}, "title": "My Bulb"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_clean_bulb_diagnostics(hass: HomeAssistant, hass_client) -> None:
|
||||||
|
"""Test diagnostics for a standard bulb."""
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
domain=lifx.DOMAIN,
|
||||||
|
title=DEFAULT_ENTRY_TITLE,
|
||||||
|
data={CONF_HOST: IP_ADDRESS},
|
||||||
|
unique_id=MAC_ADDRESS,
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
bulb = _mocked_clean_bulb()
|
||||||
|
with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
|
||||||
|
device=bulb
|
||||||
|
), _patch_device(device=bulb):
|
||||||
|
await async_setup_component(hass, lifx.DOMAIN, {lifx.DOMAIN: {}})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
diag = await get_diagnostics_for_config_entry(hass, hass_client, config_entry)
|
||||||
|
assert diag == {
|
||||||
|
"data": {
|
||||||
|
"brightness": 3,
|
||||||
|
"features": {
|
||||||
|
"buttons": False,
|
||||||
|
"chain": False,
|
||||||
|
"color": True,
|
||||||
|
"extended_multizone": False,
|
||||||
|
"hev": True,
|
||||||
|
"infrared": False,
|
||||||
|
"matrix": False,
|
||||||
|
"max_kelvin": 9000,
|
||||||
|
"min_kelvin": 1500,
|
||||||
|
"multizone": False,
|
||||||
|
"relays": False,
|
||||||
|
},
|
||||||
|
"firmware": "3.00",
|
||||||
|
"hev": {
|
||||||
|
"hev_config": {"duration": 7200, "indication": False},
|
||||||
|
"hev_cycle": {"duration": 7200, "last_power": False, "remaining": 30},
|
||||||
|
"last_result": 0,
|
||||||
|
},
|
||||||
|
"hue": 1,
|
||||||
|
"kelvin": 4,
|
||||||
|
"power": 0,
|
||||||
|
"product_id": 90,
|
||||||
|
"saturation": 2,
|
||||||
|
"vendor": None,
|
||||||
|
},
|
||||||
|
"entry": {"data": {"host": "**REDACTED**"}, "title": "My Bulb"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_infrared_bulb_diagnostics(hass: HomeAssistant, hass_client) -> None:
|
||||||
|
"""Test diagnostics for a standard bulb."""
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
domain=lifx.DOMAIN,
|
||||||
|
title=DEFAULT_ENTRY_TITLE,
|
||||||
|
data={CONF_HOST: IP_ADDRESS},
|
||||||
|
unique_id=MAC_ADDRESS,
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
bulb = _mocked_infrared_bulb()
|
||||||
|
with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
|
||||||
|
device=bulb
|
||||||
|
), _patch_device(device=bulb):
|
||||||
|
await async_setup_component(hass, lifx.DOMAIN, {lifx.DOMAIN: {}})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
diag = await get_diagnostics_for_config_entry(hass, hass_client, config_entry)
|
||||||
|
assert diag == {
|
||||||
|
"data": {
|
||||||
|
"brightness": 3,
|
||||||
|
"features": {
|
||||||
|
"buttons": False,
|
||||||
|
"chain": False,
|
||||||
|
"color": True,
|
||||||
|
"extended_multizone": False,
|
||||||
|
"hev": False,
|
||||||
|
"infrared": True,
|
||||||
|
"matrix": False,
|
||||||
|
"max_kelvin": 9000,
|
||||||
|
"min_kelvin": 1500,
|
||||||
|
"multizone": False,
|
||||||
|
"relays": False,
|
||||||
|
},
|
||||||
|
"firmware": "3.00",
|
||||||
|
"hue": 1,
|
||||||
|
"infrared": {"brightness": 65535},
|
||||||
|
"kelvin": 4,
|
||||||
|
"power": 0,
|
||||||
|
"product_id": 29,
|
||||||
|
"saturation": 2,
|
||||||
|
"vendor": None,
|
||||||
|
},
|
||||||
|
"entry": {"data": {"host": "**REDACTED**"}, "title": "My Bulb"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_legacy_multizone_bulb_diagnostics(
|
||||||
|
hass: HomeAssistant, hass_client
|
||||||
|
) -> None:
|
||||||
|
"""Test diagnostics for a standard bulb."""
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
domain=lifx.DOMAIN,
|
||||||
|
title=DEFAULT_ENTRY_TITLE,
|
||||||
|
data={CONF_HOST: IP_ADDRESS},
|
||||||
|
unique_id=MAC_ADDRESS,
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
bulb = _mocked_light_strip()
|
||||||
|
bulb.zones_count = 8
|
||||||
|
bulb.color_zones = [
|
||||||
|
(54612, 65535, 65535, 3500),
|
||||||
|
(54612, 65535, 65535, 3500),
|
||||||
|
(54612, 65535, 65535, 3500),
|
||||||
|
(54612, 65535, 65535, 3500),
|
||||||
|
(46420, 65535, 65535, 3500),
|
||||||
|
(46420, 65535, 65535, 3500),
|
||||||
|
(46420, 65535, 65535, 3500),
|
||||||
|
(46420, 65535, 65535, 3500),
|
||||||
|
]
|
||||||
|
with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
|
||||||
|
device=bulb
|
||||||
|
), _patch_device(device=bulb):
|
||||||
|
await async_setup_component(hass, lifx.DOMAIN, {lifx.DOMAIN: {}})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
diag = await get_diagnostics_for_config_entry(hass, hass_client, config_entry)
|
||||||
|
assert diag == {
|
||||||
|
"data": {
|
||||||
|
"brightness": 3,
|
||||||
|
"features": {
|
||||||
|
"buttons": False,
|
||||||
|
"chain": False,
|
||||||
|
"color": True,
|
||||||
|
"extended_multizone": False,
|
||||||
|
"hev": False,
|
||||||
|
"infrared": False,
|
||||||
|
"matrix": False,
|
||||||
|
"max_kelvin": 9000,
|
||||||
|
"min_kelvin": 2500,
|
||||||
|
"multizone": True,
|
||||||
|
"relays": False,
|
||||||
|
},
|
||||||
|
"firmware": "3.00",
|
||||||
|
"hue": 1,
|
||||||
|
"kelvin": 4,
|
||||||
|
"power": 0,
|
||||||
|
"product_id": 31,
|
||||||
|
"saturation": 2,
|
||||||
|
"vendor": None,
|
||||||
|
"zones": {
|
||||||
|
"count": 8,
|
||||||
|
"state": {
|
||||||
|
"0": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 54612,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"1": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 54612,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 54612,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 54612,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 46420,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"5": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 46420,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"6": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 46420,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"7": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 46420,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"entry": {"data": {"host": "**REDACTED**"}, "title": "My Bulb"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_multizone_bulb_diagnostics(hass: HomeAssistant, hass_client) -> None:
|
||||||
|
"""Test diagnostics for a standard bulb."""
|
||||||
|
config_entry = MockConfigEntry(
|
||||||
|
domain=lifx.DOMAIN,
|
||||||
|
title=DEFAULT_ENTRY_TITLE,
|
||||||
|
data={CONF_HOST: IP_ADDRESS},
|
||||||
|
unique_id=MAC_ADDRESS,
|
||||||
|
)
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
bulb = _mocked_light_strip()
|
||||||
|
bulb.product = 38
|
||||||
|
bulb.zones_count = 8
|
||||||
|
bulb.color_zones = [
|
||||||
|
(54612, 65535, 65535, 3500),
|
||||||
|
(54612, 65535, 65535, 3500),
|
||||||
|
(54612, 65535, 65535, 3500),
|
||||||
|
(54612, 65535, 65535, 3500),
|
||||||
|
(46420, 65535, 65535, 3500),
|
||||||
|
(46420, 65535, 65535, 3500),
|
||||||
|
(46420, 65535, 65535, 3500),
|
||||||
|
(46420, 65535, 65535, 3500),
|
||||||
|
]
|
||||||
|
with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
|
||||||
|
device=bulb
|
||||||
|
), _patch_device(device=bulb):
|
||||||
|
await async_setup_component(hass, lifx.DOMAIN, {lifx.DOMAIN: {}})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
diag = await get_diagnostics_for_config_entry(hass, hass_client, config_entry)
|
||||||
|
assert diag == {
|
||||||
|
"data": {
|
||||||
|
"brightness": 3,
|
||||||
|
"features": {
|
||||||
|
"buttons": False,
|
||||||
|
"chain": False,
|
||||||
|
"color": True,
|
||||||
|
"extended_multizone": True,
|
||||||
|
"hev": False,
|
||||||
|
"infrared": False,
|
||||||
|
"matrix": False,
|
||||||
|
"max_kelvin": 9000,
|
||||||
|
"min_ext_mz_firmware": 1532997580,
|
||||||
|
"min_ext_mz_firmware_components": [2, 77],
|
||||||
|
"min_kelvin": 1500,
|
||||||
|
"multizone": True,
|
||||||
|
"relays": False,
|
||||||
|
},
|
||||||
|
"firmware": "3.00",
|
||||||
|
"hue": 1,
|
||||||
|
"kelvin": 4,
|
||||||
|
"power": 0,
|
||||||
|
"product_id": 38,
|
||||||
|
"saturation": 2,
|
||||||
|
"vendor": None,
|
||||||
|
"zones": {
|
||||||
|
"count": 8,
|
||||||
|
"state": {
|
||||||
|
"0": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 54612,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"1": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 54612,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 54612,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 54612,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 46420,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"5": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 46420,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"6": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 46420,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
"7": {
|
||||||
|
"brightness": 65535,
|
||||||
|
"hue": 46420,
|
||||||
|
"kelvin": 3500,
|
||||||
|
"saturation": 65535,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"entry": {"data": {"host": "**REDACTED**"}, "title": "My Bulb"},
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user