Update in 1 minute on unavailable Motion blinds (#47800)

* if unavailable request update in 1 minute

* fix styling

* improve changing update interval

* remove unused import

* try to fix

* remove unused pass

* add const

* fix missing timedelta

* update to motionblinds 0.4.10

* improve update coordinator

* fix linting errors

* remove unused import

* move update functions within the DataUpdateCoordinator

* fix white space
This commit is contained in:
starkillerOG 2021-03-26 04:06:40 +01:00 committed by GitHub
parent d5afd0afb3
commit b4d39d517f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 103 additions and 23 deletions

View file

@ -1,11 +1,11 @@
"""The motion_blinds component.""" """The motion_blinds component."""
import asyncio import asyncio
from contextlib import suppress
from datetime import timedelta from datetime import timedelta
import logging import logging
from socket import timeout from socket import timeout
from motionblinds import MotionMulticast from motionblinds import MotionMulticast
from motionblinds.motion_blinds import ParseException
from homeassistant import config_entries, core from homeassistant import config_entries, core
from homeassistant.const import CONF_API_KEY, CONF_HOST, EVENT_HOMEASSISTANT_STOP from homeassistant.const import CONF_API_KEY, CONF_HOST, EVENT_HOMEASSISTANT_STOP
@ -14,18 +14,87 @@ from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .const import ( from .const import (
ATTR_AVAILABLE,
DOMAIN, DOMAIN,
KEY_COORDINATOR, KEY_COORDINATOR,
KEY_GATEWAY, KEY_GATEWAY,
KEY_MULTICAST_LISTENER, KEY_MULTICAST_LISTENER,
MANUFACTURER, MANUFACTURER,
PLATFORMS, PLATFORMS,
UPDATE_INTERVAL,
UPDATE_INTERVAL_FAST,
) )
from .gateway import ConnectMotionGateway from .gateway import ConnectMotionGateway
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
class DataUpdateCoordinatorMotionBlinds(DataUpdateCoordinator):
"""Class to manage fetching data from single endpoint."""
def __init__(
self,
hass,
logger,
gateway,
*,
name,
update_interval=None,
update_method=None,
):
"""Initialize global data updater."""
super().__init__(
hass,
logger,
name=name,
update_method=update_method,
update_interval=update_interval,
)
self._gateway = gateway
def update_gateway(self):
"""Call all updates using one async_add_executor_job."""
data = {}
try:
self._gateway.Update()
except (timeout, ParseException):
# let the error be logged and handled by the motionblinds library
data[KEY_GATEWAY] = {ATTR_AVAILABLE: False}
return data
else:
data[KEY_GATEWAY] = {ATTR_AVAILABLE: True}
for blind in self._gateway.device_list.values():
try:
blind.Update()
except (timeout, ParseException):
# let the error be logged and handled by the motionblinds library
data[blind.mac] = {ATTR_AVAILABLE: False}
else:
data[blind.mac] = {ATTR_AVAILABLE: True}
return data
async def _async_update_data(self):
"""Fetch the latest data from the gateway and blinds."""
data = await self.hass.async_add_executor_job(self.update_gateway)
all_available = True
for device in data.values():
if not device[ATTR_AVAILABLE]:
all_available = False
break
if all_available:
self.update_interval = timedelta(seconds=UPDATE_INTERVAL)
else:
self.update_interval = timedelta(seconds=UPDATE_INTERVAL_FAST)
return data
def setup(hass: core.HomeAssistant, config: dict): def setup(hass: core.HomeAssistant, config: dict):
"""Set up the Motion Blinds component.""" """Set up the Motion Blinds component."""
return True return True
@ -61,26 +130,14 @@ async def async_setup_entry(
raise ConfigEntryNotReady raise ConfigEntryNotReady
motion_gateway = connect_gateway_class.gateway_device motion_gateway = connect_gateway_class.gateway_device
def update_gateway(): coordinator = DataUpdateCoordinatorMotionBlinds(
"""Call all updates using one async_add_executor_job."""
motion_gateway.Update()
for blind in motion_gateway.device_list.values():
with suppress(timeout):
blind.Update()
async def async_update_data():
"""Fetch data from the gateway and blinds."""
with suppress(timeout): # Let the error be handled by the motionblinds
await hass.async_add_executor_job(update_gateway)
coordinator = DataUpdateCoordinator(
hass, hass,
_LOGGER, _LOGGER,
motion_gateway,
# Name of the data. For logging purposes. # Name of the data. For logging purposes.
name=entry.title, name=entry.title,
update_method=async_update_data,
# Polling interval. Will only be polled if there are subscribers. # Polling interval. Will only be polled if there are subscribers.
update_interval=timedelta(seconds=600), update_interval=timedelta(seconds=UPDATE_INTERVAL),
) )
# Fetch initial data so we have data when entities subscribe # Fetch initial data so we have data when entities subscribe

View file

@ -11,5 +11,9 @@ KEY_MULTICAST_LISTENER = "multicast_listener"
ATTR_WIDTH = "width" ATTR_WIDTH = "width"
ATTR_ABSOLUTE_POSITION = "absolute_position" ATTR_ABSOLUTE_POSITION = "absolute_position"
ATTR_AVAILABLE = "available"
SERVICE_SET_ABSOLUTE_POSITION = "set_absolute_position" SERVICE_SET_ABSOLUTE_POSITION = "set_absolute_position"
UPDATE_INTERVAL = 600
UPDATE_INTERVAL_FAST = 60

View file

@ -21,6 +21,7 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import ( from .const import (
ATTR_ABSOLUTE_POSITION, ATTR_ABSOLUTE_POSITION,
ATTR_AVAILABLE,
ATTR_WIDTH, ATTR_WIDTH,
DOMAIN, DOMAIN,
KEY_COORDINATOR, KEY_COORDINATOR,
@ -160,7 +161,13 @@ class MotionPositionDevice(CoordinatorEntity, CoverEntity):
@property @property
def available(self): def available(self):
"""Return True if entity is available.""" """Return True if entity is available."""
return self._blind.available if self.coordinator.data is None:
return False
if not self.coordinator.data[KEY_GATEWAY][ATTR_AVAILABLE]:
return False
return self.coordinator.data[self._blind.mac][ATTR_AVAILABLE]
@property @property
def current_cover_position(self): def current_cover_position(self):

View file

@ -3,6 +3,6 @@
"name": "Motion Blinds", "name": "Motion Blinds",
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/motion_blinds", "documentation": "https://www.home-assistant.io/integrations/motion_blinds",
"requirements": ["motionblinds==0.4.8"], "requirements": ["motionblinds==0.4.10"],
"codeowners": ["@starkillerOG"] "codeowners": ["@starkillerOG"]
} }

View file

@ -10,7 +10,7 @@ from homeassistant.const import (
) )
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN, KEY_COORDINATOR, KEY_GATEWAY from .const import ATTR_AVAILABLE, DOMAIN, KEY_COORDINATOR, KEY_GATEWAY
ATTR_BATTERY_VOLTAGE = "battery_voltage" ATTR_BATTERY_VOLTAGE = "battery_voltage"
TYPE_BLIND = "blind" TYPE_BLIND = "blind"
@ -70,7 +70,13 @@ class MotionBatterySensor(CoordinatorEntity, SensorEntity):
@property @property
def available(self): def available(self):
"""Return True if entity is available.""" """Return True if entity is available."""
return self._blind.available if self.coordinator.data is None:
return False
if not self.coordinator.data[KEY_GATEWAY][ATTR_AVAILABLE]:
return False
return self.coordinator.data[self._blind.mac][ATTR_AVAILABLE]
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
@ -174,7 +180,13 @@ class MotionSignalStrengthSensor(CoordinatorEntity, SensorEntity):
@property @property
def available(self): def available(self):
"""Return True if entity is available.""" """Return True if entity is available."""
return self._device.available if self.coordinator.data is None:
return False
if not self.coordinator.data[KEY_GATEWAY][ATTR_AVAILABLE]:
return False
return self.coordinator.data[self._device.mac][ATTR_AVAILABLE]
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):

View file

@ -946,7 +946,7 @@ minio==4.0.9
mitemp_bt==0.0.3 mitemp_bt==0.0.3
# homeassistant.components.motion_blinds # homeassistant.components.motion_blinds
motionblinds==0.4.8 motionblinds==0.4.10
# homeassistant.components.mullvad # homeassistant.components.mullvad
mullvad-api==1.0.0 mullvad-api==1.0.0

View file

@ -491,7 +491,7 @@ millheater==0.4.0
minio==4.0.9 minio==4.0.9
# homeassistant.components.motion_blinds # homeassistant.components.motion_blinds
motionblinds==0.4.8 motionblinds==0.4.10
# homeassistant.components.mullvad # homeassistant.components.mullvad
mullvad-api==1.0.0 mullvad-api==1.0.0