From b9e4d5988f0796f410e99631501a38065038ca24 Mon Sep 17 00:00:00 2001 From: badguy99 <61918526+badguy99@users.noreply.github.com> Date: Wed, 13 Jan 2021 14:14:15 +0000 Subject: [PATCH] Soma: fix battery drain issue caused by excess update requests (#45104) * split up update and throttle update on sensor * Update imports * Add blank lines for isort --- homeassistant/components/soma/__init__.py | 44 ----------------------- homeassistant/components/soma/cover.py | 22 ++++++++++++ homeassistant/components/soma/sensor.py | 37 +++++++++++++++++++ 3 files changed, 59 insertions(+), 44 deletions(-) diff --git a/homeassistant/components/soma/__init__.py b/homeassistant/components/soma/__init__.py index d4dbbced453..bd5695cb7ec 100644 --- a/homeassistant/components/soma/__init__.py +++ b/homeassistant/components/soma/__init__.py @@ -1,9 +1,7 @@ """Support for Soma Smartshades.""" import asyncio -import logging from api.soma_api import SomaApi -from requests import RequestException import voluptuous as vol from homeassistant import config_entries @@ -17,8 +15,6 @@ from .const import API, DOMAIN, HOST, PORT DEVICES = "devices" -_LOGGER = logging.getLogger(__name__) - CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema( @@ -113,43 +109,3 @@ class SomaEntity(Entity): "name": self.name, "manufacturer": "Wazombi Labs", } - - async def async_update(self): - """Update the device with the latest data.""" - try: - response = await self.hass.async_add_executor_job( - self.api.get_shade_state, self.device["mac"] - ) - except RequestException: - _LOGGER.error("Connection to SOMA Connect failed") - self.is_available = False - return - if response["result"] != "success": - _LOGGER.error( - "Unable to reach device %s (%s)", self.device["name"], response["msg"] - ) - self.is_available = False - return - self.current_position = 100 - response["position"] - try: - response = await self.hass.async_add_executor_job( - self.api.get_battery_level, self.device["mac"] - ) - except RequestException: - _LOGGER.error("Connection to SOMA Connect failed") - self.is_available = False - return - if response["result"] != "success": - _LOGGER.error( - "Unable to reach device %s (%s)", self.device["name"], response["msg"] - ) - self.is_available = False - return - # https://support.somasmarthome.com/hc/en-us/articles/360026064234-HTTP-API - # battery_level response is expected to be min = 360, max 410 for - # 0-100% levels above 410 are consider 100% and below 360, 0% as the - # device considers 360 the minimum to move the motor. - _battery = round(2 * (response["battery_level"] - 360)) - battery = max(min(100, _battery), 0) - self.battery_state = battery - self.is_available = True diff --git a/homeassistant/components/soma/cover.py b/homeassistant/components/soma/cover.py index f2929dd8ddd..1005bf32f20 100644 --- a/homeassistant/components/soma/cover.py +++ b/homeassistant/components/soma/cover.py @@ -2,6 +2,8 @@ import logging +from requests import RequestException + from homeassistant.components.cover import ATTR_POSITION, CoverEntity from homeassistant.components.soma import API, DEVICES, DOMAIN, SomaEntity @@ -67,3 +69,23 @@ class SomaCover(SomaEntity, CoverEntity): def is_closed(self): """Return if the cover is closed.""" return self.current_position == 0 + + async def async_update(self): + """Update the cover with the latest data.""" + try: + _LOGGER.debug("Soma Cover Update") + response = await self.hass.async_add_executor_job( + self.api.get_shade_state, self.device["mac"] + ) + except RequestException: + _LOGGER.error("Connection to SOMA Connect failed") + self.is_available = False + return + if response["result"] != "success": + _LOGGER.error( + "Unable to reach device %s (%s)", self.device["name"], response["msg"] + ) + self.is_available = False + return + self.current_position = 100 - response["position"] + self.is_available = True diff --git a/homeassistant/components/soma/sensor.py b/homeassistant/components/soma/sensor.py index 2d37a0b0dce..9430a929e1e 100644 --- a/homeassistant/components/soma/sensor.py +++ b/homeassistant/components/soma/sensor.py @@ -1,10 +1,20 @@ """Support for Soma sensors.""" +from datetime import timedelta +import logging + +from requests import RequestException + from homeassistant.const import DEVICE_CLASS_BATTERY, PERCENTAGE from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle from . import DEVICES, SomaEntity from .const import API, DOMAIN +MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=30) + +_LOGGER = logging.getLogger(__name__) + async def async_setup_entry(hass, config_entry, async_add_entities): """Set up the Soma sensor platform.""" @@ -38,3 +48,30 @@ class SomaSensor(SomaEntity, Entity): def unit_of_measurement(self): """Return the unit of measurement this sensor expresses itself in.""" return PERCENTAGE + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + async def async_update(self): + """Update the sensor with the latest data.""" + try: + _LOGGER.debug("Soma Sensor Update") + response = await self.hass.async_add_executor_job( + self.api.get_battery_level, self.device["mac"] + ) + except RequestException: + _LOGGER.error("Connection to SOMA Connect failed") + self.is_available = False + return + if response["result"] != "success": + _LOGGER.error( + "Unable to reach device %s (%s)", self.device["name"], response["msg"] + ) + self.is_available = False + return + # https://support.somasmarthome.com/hc/en-us/articles/360026064234-HTTP-API + # battery_level response is expected to be min = 360, max 410 for + # 0-100% levels above 410 are consider 100% and below 360, 0% as the + # device considers 360 the minimum to move the motor. + _battery = round(2 * (response["battery_level"] - 360)) + battery = max(min(100, _battery), 0) + self.battery_state = battery + self.is_available = True