From 3bc45eacfc14e52815190ef9cc7e2a3f8d160e29 Mon Sep 17 00:00:00 2001 From: Teemu R Date: Wed, 18 Aug 2021 01:29:40 +0200 Subject: [PATCH] Fix tplink doing I/O in event loop and optimize (#54570) * Optimize tplink i/o * Cache has_emeter reduceing the number of i/o requests on hs300 by 5 * Use the state from the sysinfo dict for non-strips reducing required requests by one * Remove I/O from __init__, read has_emeter from sysinfo * Cleanup __init__ to avoid I/O * Re-use the sysinfo response for has_emeter * Use async_add_executor_job() to execute the synchronous I/O ops. * use the device alias instead of host for coordinator, use executor for unavailable_devices * Remove unnecessary self.hass assignment Co-authored-by: Martin Hjelmare Co-authored-by: Martin Hjelmare --- homeassistant/components/tplink/__init__.py | 26 ++++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/tplink/__init__.py b/homeassistant/components/tplink/__init__.py index 5c69247eea8..aad934b2600 100644 --- a/homeassistant/components/tplink/__init__.py +++ b/homeassistant/components/tplink/__init__.py @@ -154,7 +154,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: for device in unavailable_devices: try: - device.get_sysinfo() + await hass.async_add_executor_job(device.get_sysinfo) except SmartDeviceException: continue _LOGGER.debug( @@ -168,7 +168,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: for switch in switches: try: - await hass.async_add_executor_job(switch.get_sysinfo) + info = await hass.async_add_executor_job(switch.get_sysinfo) except SmartDeviceException: _LOGGER.warning( "Device at '%s' not reachable during setup, will retry later", @@ -179,7 +179,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass_data[COORDINATORS][ switch.context or switch.mac - ] = coordinator = SmartPlugDataUpdateCoordinator(hass, switch) + ] = coordinator = SmartPlugDataUpdateCoordinator(hass, switch, info["alias"]) await coordinator.async_config_entry_first_refresh() if unavailable_devices: @@ -215,16 +215,20 @@ class SmartPlugDataUpdateCoordinator(DataUpdateCoordinator): self, hass: HomeAssistant, smartplug: SmartPlug, + alias: str, ) -> None: """Initialize DataUpdateCoordinator to gather data for specific SmartPlug.""" self.smartplug = smartplug update_interval = timedelta(seconds=30) super().__init__( - hass, _LOGGER, name=smartplug.alias, update_interval=update_interval + hass, + _LOGGER, + name=alias, + update_interval=update_interval, ) - async def _async_update_data(self) -> dict: + def _update_data(self) -> dict: """Fetch all device and sensor data from api.""" try: info = self.smartplug.sys_info @@ -237,9 +241,7 @@ class SmartPlugDataUpdateCoordinator(DataUpdateCoordinator): if self.smartplug.context is None: data[CONF_ALIAS] = info["alias"] data[CONF_DEVICE_ID] = info["mac"] - data[CONF_STATE] = ( - self.smartplug.state == self.smartplug.SWITCH_STATE_ON - ) + data[CONF_STATE] = bool(info["relay_state"]) else: plug_from_context = next( c @@ -249,7 +251,9 @@ class SmartPlugDataUpdateCoordinator(DataUpdateCoordinator): data[CONF_ALIAS] = plug_from_context["alias"] data[CONF_DEVICE_ID] = self.smartplug.context data[CONF_STATE] = plug_from_context["state"] == 1 - if self.smartplug.has_emeter: + + # Check if the device has emeter + if "ENE" in info["feature"]: emeter_readings = self.smartplug.get_emeter_realtime() data[CONF_EMETER_PARAMS] = { ATTR_CURRENT_POWER_W: round(float(emeter_readings["power"]), 2), @@ -270,3 +274,7 @@ class SmartPlugDataUpdateCoordinator(DataUpdateCoordinator): self.name = data[CONF_ALIAS] return data + + async def _async_update_data(self) -> dict: + """Fetch all device and sensor data from api.""" + return await self.hass.async_add_executor_job(self._update_data)