Add retry for unavailable static tplink devices after HA starts (#42247)
parent
2893972c69
commit
93e71ef218
|
@ -13,6 +13,8 @@ from pyHS100 import (
|
||||||
|
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
|
||||||
|
from .const import DOMAIN as TPLINK_DOMAIN
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,3 +129,31 @@ def get_static_devices(config_data) -> SmartDevices:
|
||||||
"Failed to setup device %s due to %s; not retrying", host, sde
|
"Failed to setup device %s due to %s; not retrying", host, sde
|
||||||
)
|
)
|
||||||
return SmartDevices(lights, switches)
|
return SmartDevices(lights, switches)
|
||||||
|
|
||||||
|
|
||||||
|
def add_available_devices(hass, device_type, device_class, async_add_entities):
|
||||||
|
"""Get sysinfo for all devices."""
|
||||||
|
|
||||||
|
devices = hass.data[TPLINK_DOMAIN][device_type]
|
||||||
|
|
||||||
|
if f"{device_type}_remaining" in hass.data[TPLINK_DOMAIN]:
|
||||||
|
devices = hass.data[TPLINK_DOMAIN][f"{device_type}_remaining"]
|
||||||
|
|
||||||
|
entities_ready = []
|
||||||
|
entities_unavailable = []
|
||||||
|
for device in devices:
|
||||||
|
try:
|
||||||
|
device.get_sysinfo()
|
||||||
|
entities_ready.append(device_class(device))
|
||||||
|
except SmartDeviceException as ex:
|
||||||
|
entities_unavailable.append(device)
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Unable to communicate with device %s: %s",
|
||||||
|
device.host,
|
||||||
|
ex,
|
||||||
|
)
|
||||||
|
|
||||||
|
hass.data[TPLINK_DOMAIN][f"{device_type}_remaining"] = entities_unavailable
|
||||||
|
|
||||||
|
if entities_ready:
|
||||||
|
async_add_entities(entities_ready, update_before_add=True)
|
||||||
|
|
|
@ -16,7 +16,7 @@ from homeassistant.components.light import (
|
||||||
SUPPORT_COLOR_TEMP,
|
SUPPORT_COLOR_TEMP,
|
||||||
LightEntity,
|
LightEntity,
|
||||||
)
|
)
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError, PlatformNotReady
|
||||||
import homeassistant.helpers.device_registry as dr
|
import homeassistant.helpers.device_registry as dr
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
from homeassistant.util.color import (
|
from homeassistant.util.color import (
|
||||||
|
@ -26,6 +26,7 @@ from homeassistant.util.color import (
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from . import CONF_LIGHT, DOMAIN as TPLINK_DOMAIN
|
from . import CONF_LIGHT, DOMAIN as TPLINK_DOMAIN
|
||||||
|
from .common import add_available_devices
|
||||||
|
|
||||||
PARALLEL_UPDATES = 0
|
PARALLEL_UPDATES = 0
|
||||||
SCAN_INTERVAL = timedelta(seconds=5)
|
SCAN_INTERVAL = timedelta(seconds=5)
|
||||||
|
@ -60,20 +61,12 @@ SLEEP_TIME = 2
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistantType, config_entry, async_add_entities):
|
async def async_setup_entry(hass: HomeAssistantType, config_entry, async_add_entities):
|
||||||
"""Set up lights."""
|
"""Set up lights."""
|
||||||
devices = hass.data[TPLINK_DOMAIN][CONF_LIGHT]
|
await hass.async_add_executor_job(
|
||||||
entities = []
|
add_available_devices, hass, CONF_LIGHT, TPLinkSmartBulb, async_add_entities
|
||||||
|
)
|
||||||
|
|
||||||
await hass.async_add_executor_job(get_devices_sysinfo, devices)
|
if hass.data[TPLINK_DOMAIN][f"{CONF_LIGHT}_remaining"]:
|
||||||
for device in devices:
|
raise PlatformNotReady
|
||||||
entities.append(TPLinkSmartBulb(device))
|
|
||||||
|
|
||||||
async_add_entities(entities, update_before_add=True)
|
|
||||||
|
|
||||||
|
|
||||||
def get_devices_sysinfo(devices):
|
|
||||||
"""Get sysinfo for all devices."""
|
|
||||||
for device in devices:
|
|
||||||
device.get_sysinfo()
|
|
||||||
|
|
||||||
|
|
||||||
def brightness_to_percentage(byt):
|
def brightness_to_percentage(byt):
|
||||||
|
|
|
@ -11,10 +11,12 @@ from homeassistant.components.switch import (
|
||||||
SwitchEntity,
|
SwitchEntity,
|
||||||
)
|
)
|
||||||
from homeassistant.const import ATTR_VOLTAGE
|
from homeassistant.const import ATTR_VOLTAGE
|
||||||
|
from homeassistant.exceptions import PlatformNotReady
|
||||||
import homeassistant.helpers.device_registry as dr
|
import homeassistant.helpers.device_registry as dr
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
|
||||||
from . import CONF_SWITCH, DOMAIN as TPLINK_DOMAIN
|
from . import CONF_SWITCH, DOMAIN as TPLINK_DOMAIN
|
||||||
|
from .common import add_available_devices
|
||||||
|
|
||||||
PARALLEL_UPDATES = 0
|
PARALLEL_UPDATES = 0
|
||||||
|
|
||||||
|
@ -29,20 +31,12 @@ SLEEP_TIME = 2
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistantType, config_entry, async_add_entities):
|
async def async_setup_entry(hass: HomeAssistantType, config_entry, async_add_entities):
|
||||||
"""Set up switches."""
|
"""Set up switches."""
|
||||||
devices = hass.data[TPLINK_DOMAIN][CONF_SWITCH]
|
await hass.async_add_executor_job(
|
||||||
entities = []
|
add_available_devices, hass, CONF_SWITCH, SmartPlugSwitch, async_add_entities
|
||||||
|
)
|
||||||
|
|
||||||
await hass.async_add_executor_job(get_devices_sysinfo, devices)
|
if hass.data[TPLINK_DOMAIN][f"{CONF_SWITCH}_remaining"]:
|
||||||
for device in devices:
|
raise PlatformNotReady
|
||||||
entities.append(SmartPlugSwitch(device))
|
|
||||||
|
|
||||||
async_add_entities(entities, update_before_add=True)
|
|
||||||
|
|
||||||
|
|
||||||
def get_devices_sysinfo(devices):
|
|
||||||
"""Get sysinfo for all devices."""
|
|
||||||
for device in devices:
|
|
||||||
device.get_sysinfo()
|
|
||||||
|
|
||||||
|
|
||||||
class SmartPlugSwitch(SwitchEntity):
|
class SmartPlugSwitch(SwitchEntity):
|
||||||
|
|
|
@ -577,3 +577,33 @@ async def test_update_failure(
|
||||||
in caplog.text
|
in caplog.text
|
||||||
)
|
)
|
||||||
assert "Device 123.123.123.123|light1 responded after " in caplog.text
|
assert "Device 123.123.123.123|light1 responded after " in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
async def test_async_setup_entry_unavailable(
|
||||||
|
hass: HomeAssistant, light_mock_data: LightMockData, caplog
|
||||||
|
):
|
||||||
|
"""Test unavailable devices trigger a later retry."""
|
||||||
|
caplog.clear()
|
||||||
|
caplog.set_level(logging.WARNING)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.tplink.common.SmartDevice.get_sysinfo",
|
||||||
|
side_effect=SmartDeviceException,
|
||||||
|
):
|
||||||
|
await async_setup_component(hass, HA_DOMAIN, {})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
await async_setup_component(
|
||||||
|
hass,
|
||||||
|
tplink.DOMAIN,
|
||||||
|
{
|
||||||
|
tplink.DOMAIN: {
|
||||||
|
CONF_DISCOVERY: False,
|
||||||
|
CONF_LIGHT: [{CONF_HOST: "123.123.123.123"}],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert "Unable to communicate with device 123.123.123.123" in caplog.text
|
||||||
|
assert len(hass.data[tplink.DOMAIN][f"{CONF_LIGHT}_remaining"]) == 1
|
||||||
|
|
Loading…
Reference in New Issue