Populate suggested_area using the LIFX group name for each device (#83259)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Avi Miller 2022-12-05 13:31:08 +11:00 committed by GitHub
parent c70388869b
commit 88c8eef4eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 60 additions and 9 deletions

View File

@ -119,9 +119,10 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
assert self._discovered_device is not None assert self._discovered_device is not None
discovered = self._discovered_device discovered = self._discovered_device
_LOGGER.debug( _LOGGER.debug(
"Confirming discovery: %s with serial %s", "Confirming discovery of %s (%s) [%s]",
discovered.label, discovered.label,
self.unique_id, discovered.group,
discovered.mac_addr,
) )
if user_input is not None or self._async_discovered_pending_migration(): if user_input is not None or self._async_discovered_pending_migration():
return self._async_create_entry_from_device(discovered) return self._async_create_entry_from_device(discovered)
@ -130,8 +131,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self._set_confirm_only() self._set_confirm_only()
placeholders = { placeholders = {
"label": discovered.label, "label": discovered.label,
"host": discovered.ip_addr, "group": discovered.group,
"serial": self.unique_id,
} }
self.context["title_placeholders"] = placeholders self.context["title_placeholders"] = placeholders
return self.async_show_form( return self.async_show_form(
@ -224,11 +224,13 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
# get_hostfirmware required for MAC address offset # get_hostfirmware required for MAC address offset
# get_version required for lifx_features() # get_version required for lifx_features()
# get_label required to log the name of the device # get_label required to log the name of the device
# get_group required to populate suggested areas
messages = await asyncio.gather( messages = await asyncio.gather(
*[ *[
async_execute_lifx(device.get_hostfirmware), async_execute_lifx(device.get_hostfirmware),
async_execute_lifx(device.get_version), async_execute_lifx(device.get_version),
async_execute_lifx(device.get_label), async_execute_lifx(device.get_label),
async_execute_lifx(device.get_group),
] ]
) )
except asyncio.TimeoutError: except asyncio.TimeoutError:
@ -237,7 +239,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
connection.async_stop() connection.async_stop()
if ( if (
messages is None messages is None
or len(messages) != 3 or len(messages) != 4
or lifx_features(device)["relays"] is True or lifx_features(device)["relays"] is True
or device.host_firmware_version is None or device.host_firmware_version is None
): ):

View File

@ -173,6 +173,8 @@ class LIFXUpdateCoordinator(DataUpdateCoordinator):
self.device.get_hostfirmware() self.device.get_hostfirmware()
if self.device.product is None: if self.device.product is None:
self.device.get_version() self.device.get_version()
if self.device.group is None:
self.device.get_group()
response = await async_execute_lifx(self.device.get_color) response = await async_execute_lifx(self.device.get_color)

View File

@ -25,6 +25,7 @@ class LIFXEntity(CoordinatorEntity[LIFXUpdateCoordinator]):
name=coordinator.label, name=coordinator.label,
model=products.product_map.get(self.bulb.product, "LIFX Bulb"), model=products.product_map.get(self.bulb.product, "LIFX Bulb"),
sw_version=self.bulb.host_firmware_version, sw_version=self.bulb.host_firmware_version,
suggested_area=self.bulb.group,
) )
@ -42,4 +43,5 @@ class LIFXSensorEntity(CoordinatorEntity[LIFXSensorUpdateCoordinator]):
name=coordinator.parent.label, name=coordinator.parent.label,
model=products.product_map.get(self.bulb.product, "LIFX Bulb"), model=products.product_map.get(self.bulb.product, "LIFX Bulb"),
sw_version=self.bulb.host_firmware_version, sw_version=self.bulb.host_firmware_version,
suggested_area=self.bulb.group,
) )

View File

@ -1,6 +1,6 @@
{ {
"config": { "config": {
"flow_title": "{label} ({host}) {serial}", "flow_title": "{label} ({group})",
"step": { "step": {
"user": { "user": {
"description": "If you leave the host empty, discovery will be used to find devices.", "description": "If you leave the host empty, discovery will be used to find devices.",
@ -14,7 +14,7 @@
} }
}, },
"discovery_confirm": { "discovery_confirm": {
"description": "Do you want to setup {label} ({host}) {serial}?" "description": "Do you want to setup {label} ({group})?"
} }
}, },
"error": { "error": {

View File

@ -8,10 +8,10 @@
"error": { "error": {
"cannot_connect": "Failed to connect" "cannot_connect": "Failed to connect"
}, },
"flow_title": "{label} ({host}) {serial}", "flow_title": "{label} ({group})",
"step": { "step": {
"discovery_confirm": { "discovery_confirm": {
"description": "Do you want to setup {label} ({host}) {serial}?" "description": "Do you want to setup {label} ({group})?"
}, },
"pick_device": { "pick_device": {
"data": { "data": {

View File

@ -14,6 +14,7 @@ MODULE = "homeassistant.components.lifx"
MODULE_CONFIG_FLOW = "homeassistant.components.lifx.config_flow" MODULE_CONFIG_FLOW = "homeassistant.components.lifx.config_flow"
IP_ADDRESS = "127.0.0.1" IP_ADDRESS = "127.0.0.1"
LABEL = "My Bulb" LABEL = "My Bulb"
GROUP = "My Group"
SERIAL = "aa:bb:cc:dd:ee:cc" SERIAL = "aa:bb:cc:dd:ee:cc"
MAC_ADDRESS = "aa:bb:cc:dd:ee:cd" MAC_ADDRESS = "aa:bb:cc:dd:ee:cd"
DEFAULT_ENTRY_TITLE = LABEL DEFAULT_ENTRY_TITLE = LABEL
@ -81,6 +82,7 @@ def _mocked_bulb() -> Light:
bulb = Light(asyncio.get_running_loop(), SERIAL, IP_ADDRESS) bulb = Light(asyncio.get_running_loop(), SERIAL, IP_ADDRESS)
bulb.host_firmware_version = "3.00" bulb.host_firmware_version = "3.00"
bulb.label = LABEL bulb.label = LABEL
bulb.group = GROUP
bulb.color = [1, 2, 3, 4] bulb.color = [1, 2, 3, 4]
bulb.power_level = 0 bulb.power_level = 0
bulb.fire_and_forget = AsyncMock() bulb.fire_and_forget = AsyncMock()
@ -88,6 +90,7 @@ def _mocked_bulb() -> Light:
bulb.try_sending = AsyncMock() bulb.try_sending = AsyncMock()
bulb.set_infrared = MockLifxCommand(bulb) bulb.set_infrared = MockLifxCommand(bulb)
bulb.get_label = MockLifxCommand(bulb) bulb.get_label = MockLifxCommand(bulb)
bulb.get_group = MockLifxCommand(bulb)
bulb.get_color = MockLifxCommand(bulb) bulb.get_color = MockLifxCommand(bulb)
bulb.set_power = MockLifxCommand(bulb) bulb.set_power = MockLifxCommand(bulb)
bulb.set_color = MockLifxCommand(bulb) bulb.set_color = MockLifxCommand(bulb)

View File

@ -11,6 +11,8 @@ from homeassistant.components.lifx.const import CONF_SERIAL
from homeassistant.const import CONF_DEVICE, CONF_HOST from homeassistant.const import CONF_DEVICE, CONF_HOST
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
from . import ( from . import (
DEFAULT_ENTRY_TITLE, DEFAULT_ENTRY_TITLE,
@ -19,9 +21,11 @@ from . import (
MAC_ADDRESS, MAC_ADDRESS,
MODULE, MODULE,
SERIAL, SERIAL,
_mocked_bulb,
_mocked_failing_bulb, _mocked_failing_bulb,
_mocked_relay, _mocked_relay,
_patch_config_flow_try_connect, _patch_config_flow_try_connect,
_patch_device,
_patch_discovery, _patch_discovery,
) )
@ -523,3 +527,41 @@ async def test_refuse_relays(hass: HomeAssistant):
await hass.async_block_till_done() await hass.async_block_till_done()
assert result2["type"] == "form" assert result2["type"] == "form"
assert result2["errors"] == {"base": "cannot_connect"} assert result2["errors"] == {"base": "cannot_connect"}
async def test_suggested_area(hass: HomeAssistant) -> None:
"""Test suggested area is populated from lifx group label."""
class MockLifxCommandGetGroup:
"""Mock the get_group method that gets the group name from the bulb."""
def __init__(self, bulb, **kwargs):
"""Init command."""
self.bulb = bulb
self.lifx_group = kwargs.get("lifx_group")
def __call__(self, *args, **kwargs):
"""Call command."""
self.bulb.group = self.lifx_group
config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: "1.2.3.4"}, unique_id=SERIAL
)
config_entry.add_to_hass(hass)
bulb = _mocked_bulb()
bulb.group = None
bulb.get_group = MockLifxCommandGetGroup(bulb, lifx_group="My LIFX Group")
with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
device=bulb
), _patch_device(device=bulb):
await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
await hass.async_block_till_done()
entity_registry = er.async_get(hass)
entity_id = "light.my_bulb"
entity = entity_registry.async_get(entity_id)
device_registry = dr.async_get(hass)
device = device_registry.async_get(entity.device_id)
assert device.suggested_area == "My LIFX Group"