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 <marhje52@gmail.com>

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Teemu R 2021-08-18 01:29:40 +02:00 committed by GitHub
parent 67e9035e4e
commit 3bc45eacfc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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)