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."""
import asyncio
from contextlib import suppress
from datetime import timedelta
import logging
from socket import timeout
from motionblinds import MotionMulticast
from motionblinds.motion_blinds import ParseException
from homeassistant import config_entries, core
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 .const import (
ATTR_AVAILABLE,
DOMAIN,
KEY_COORDINATOR,
KEY_GATEWAY,
KEY_MULTICAST_LISTENER,
MANUFACTURER,
PLATFORMS,
UPDATE_INTERVAL,
UPDATE_INTERVAL_FAST,
)
from .gateway import ConnectMotionGateway
_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):
"""Set up the Motion Blinds component."""
return True
@ -61,26 +130,14 @@ async def async_setup_entry(
raise ConfigEntryNotReady
motion_gateway = connect_gateway_class.gateway_device
def update_gateway():
"""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(
coordinator = DataUpdateCoordinatorMotionBlinds(
hass,
_LOGGER,
motion_gateway,
# Name of the data. For logging purposes.
name=entry.title,
update_method=async_update_data,
# 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

View File

@ -11,5 +11,9 @@ KEY_MULTICAST_LISTENER = "multicast_listener"
ATTR_WIDTH = "width"
ATTR_ABSOLUTE_POSITION = "absolute_position"
ATTR_AVAILABLE = "available"
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 (
ATTR_ABSOLUTE_POSITION,
ATTR_AVAILABLE,
ATTR_WIDTH,
DOMAIN,
KEY_COORDINATOR,
@ -160,7 +161,13 @@ class MotionPositionDevice(CoordinatorEntity, CoverEntity):
@property
def available(self):
"""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
def current_cover_position(self):

View File

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

View File

@ -10,7 +10,7 @@ from homeassistant.const import (
)
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"
TYPE_BLIND = "blind"
@ -70,7 +70,13 @@ class MotionBatterySensor(CoordinatorEntity, SensorEntity):
@property
def available(self):
"""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
def unit_of_measurement(self):
@ -174,7 +180,13 @@ class MotionSignalStrengthSensor(CoordinatorEntity, SensorEntity):
@property
def available(self):
"""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
def unit_of_measurement(self):

View File

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

View File

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