Add zeroconf support for yeelight (#56758)

This commit is contained in:
João Pedro Hickmann 2021-09-28 22:53:43 -03:00 committed by GitHub
parent 8e91e6e97e
commit 4513a46248
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 97 additions and 3 deletions

View File

@ -60,6 +60,17 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self._discovered_ip = discovery_info[IP_ADDRESS]
return await self._async_handle_discovery()
async def async_step_zeroconf(self, discovery_info):
"""Handle discovery from zeroconf."""
self._discovered_ip = discovery_info["host"]
await self.async_set_unique_id(
"{0:#0{1}x}".format(int(discovery_info["name"][-26:-18]), 18)
)
self._abort_if_unique_id_configured(
updates={CONF_HOST: self._discovered_ip}, reload_on_update=False
)
return await self._async_handle_discovery()
async def async_step_ssdp(self, discovery_info):
"""Handle discovery from ssdp."""
self._discovered_ip = urlparse(discovery_info["location"]).hostname

View File

@ -8,9 +8,12 @@
"dependencies": ["network"],
"quality_scale": "platinum",
"iot_class": "local_push",
"dhcp": [{
"dhcp": [
{
"hostname": "yeelink-*"
}],
}
],
"zeroconf": [{ "type": "_miio._udp.local.", "name": "yeelink-*" }],
"homekit": {
"models": ["YL*"]
}

View File

@ -168,6 +168,10 @@ ZEROCONF = {
},
{
"domain": "xiaomi_miio"
},
{
"domain": "yeelight",
"name": "yeelink-*"
}
],
"_nanoleafapi._tcp.local.": [

View File

@ -37,6 +37,17 @@ CAPABILITIES = {
"name": "",
}
ID_DECIMAL = f"{int(ID, 16):08d}"
ZEROCONF_DATA = {
"host": IP_ADDRESS,
"port": 54321,
"hostname": f"yeelink-light-strip1_miio{ID_DECIMAL}.local.",
"type": "_miio._udp.local.",
"name": f"yeelink-light-strip1_miio{ID_DECIMAL}._miio._udp.local.",
"properties": {"epoch": "1", "mac": "000000000000"},
}
NAME = "name"
SHORT_ID = hex(int("0x000000000015243f", 16))
UNIQUE_NAME = f"yeelight_{MODEL}_{SHORT_ID}"

View File

@ -33,6 +33,7 @@ from . import (
MODULE_CONFIG_FLOW,
NAME,
UNIQUE_FRIENDLY_NAME,
ZEROCONF_DATA,
_mocked_bulb,
_patch_discovery,
_patch_discovery_interval,
@ -576,3 +577,67 @@ async def test_discovered_ssdp(hass):
assert result["type"] == RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"
async def test_discovered_zeroconf(hass):
"""Test we can setup when discovered from zeroconf."""
await setup.async_setup_component(hass, "persistent_notification", {})
mocked_bulb = _mocked_bulb()
with _patch_discovery(), _patch_discovery_interval(), patch(
f"{MODULE_CONFIG_FLOW}.AsyncBulb", return_value=mocked_bulb
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_ZEROCONF},
data=ZEROCONF_DATA,
)
await hass.async_block_till_done()
assert result["type"] == RESULT_TYPE_FORM
assert result["errors"] is None
with _patch_discovery(), _patch_discovery_interval(), patch(
f"{MODULE}.async_setup", return_value=True
) as mock_async_setup, patch(
f"{MODULE}.async_setup_entry", return_value=True
) as mock_async_setup_entry:
result2 = await hass.config_entries.flow.async_configure(result["flow_id"], {})
await hass.async_block_till_done()
assert result2["type"] == "create_entry"
assert result2["data"] == {
CONF_HOST: IP_ADDRESS,
CONF_ID: "0x000000000015243f",
CONF_MODEL: MODEL,
}
assert mock_async_setup.called
assert mock_async_setup_entry.called
mocked_bulb = _mocked_bulb()
with _patch_discovery(), _patch_discovery_interval(), patch(
f"{MODULE_CONFIG_FLOW}.AsyncBulb", return_value=mocked_bulb
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_ZEROCONF},
data=ZEROCONF_DATA,
)
await hass.async_block_till_done()
assert result["type"] == RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"
mocked_bulb = _mocked_bulb()
with _patch_discovery(), _patch_discovery_interval(), patch(
f"{MODULE_CONFIG_FLOW}.AsyncBulb", return_value=mocked_bulb
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_SSDP},
data=CAPABILITIES,
)
await hass.async_block_till_done()
assert result["type"] == RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"