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:
parent
d5afd0afb3
commit
b4d39d517f
7 changed files with 103 additions and 23 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue