mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Convert somfy to use DataUpdateCoordinator (#42434)
This commit is contained in:
parent
f3a15eab6e
commit
df25feab37
@ -4,7 +4,6 @@ from datetime import timedelta
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from pymfy.api.devices.category import Category
|
from pymfy.api.devices.category import Category
|
||||||
from requests import HTTPError
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.somfy import config_flow
|
from homeassistant.components.somfy import config_flow
|
||||||
@ -17,22 +16,19 @@ from homeassistant.helpers import (
|
|||||||
)
|
)
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.helpers.update_coordinator import (
|
||||||
|
CoordinatorEntity,
|
||||||
|
DataUpdateCoordinator,
|
||||||
|
)
|
||||||
|
|
||||||
from . import api
|
from . import api
|
||||||
from .const import DOMAIN
|
from .const import API, CONF_OPTIMISTIC, COORDINATOR, DOMAIN
|
||||||
|
|
||||||
API = "api"
|
|
||||||
|
|
||||||
DEVICES = "devices"
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
SCAN_INTERVAL = timedelta(minutes=1)
|
SCAN_INTERVAL = timedelta(minutes=1)
|
||||||
|
|
||||||
|
|
||||||
CONF_OPTIMISTIC = "optimistic"
|
|
||||||
|
|
||||||
SOMFY_AUTH_CALLBACK_PATH = "/auth/somfy/callback"
|
SOMFY_AUTH_CALLBACK_PATH = "/auth/somfy/callback"
|
||||||
SOMFY_AUTH_START = "/auth/somfy"
|
SOMFY_AUTH_START = "/auth/somfy"
|
||||||
|
|
||||||
@ -88,15 +84,32 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
hass.data[DOMAIN][API] = api.ConfigEntrySomfyApi(hass, entry, implementation)
|
data = hass.data[DOMAIN]
|
||||||
hass.data[DOMAIN][DEVICES] = []
|
data[API] = api.ConfigEntrySomfyApi(hass, entry, implementation)
|
||||||
|
|
||||||
await update_all_devices(hass)
|
async def _update_all_devices():
|
||||||
|
"""Update all the devices."""
|
||||||
|
devices = await hass.async_add_executor_job(data[API].get_devices)
|
||||||
|
return {dev.id: dev for dev in devices}
|
||||||
|
|
||||||
|
coordinator = DataUpdateCoordinator(
|
||||||
|
hass,
|
||||||
|
_LOGGER,
|
||||||
|
name="somfy device update",
|
||||||
|
update_method=_update_all_devices,
|
||||||
|
update_interval=SCAN_INTERVAL,
|
||||||
|
)
|
||||||
|
data[COORDINATOR] = coordinator
|
||||||
|
|
||||||
|
await coordinator.async_refresh()
|
||||||
|
|
||||||
device_registry = await dr.async_get_registry(hass)
|
device_registry = await dr.async_get_registry(hass)
|
||||||
|
|
||||||
devices = hass.data[DOMAIN][DEVICES]
|
hubs = [
|
||||||
hubs = [device for device in devices if Category.HUB.value in device.categories]
|
device
|
||||||
|
for device in coordinator.data.values()
|
||||||
|
if Category.HUB.value in device.categories
|
||||||
|
]
|
||||||
|
|
||||||
for hub in hubs:
|
for hub in hubs:
|
||||||
device_registry.async_get_or_create(
|
device_registry.async_get_or_create(
|
||||||
@ -127,18 +140,24 @@ async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class SomfyEntity(Entity):
|
class SomfyEntity(CoordinatorEntity, Entity):
|
||||||
"""Representation of a generic Somfy device."""
|
"""Representation of a generic Somfy device."""
|
||||||
|
|
||||||
def __init__(self, device, somfy_api):
|
def __init__(self, coordinator, device_id, somfy_api):
|
||||||
"""Initialize the Somfy device."""
|
"""Initialize the Somfy device."""
|
||||||
self.device = device
|
super().__init__(coordinator)
|
||||||
|
self._id = device_id
|
||||||
self.api = somfy_api
|
self.api = somfy_api
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device(self):
|
||||||
|
"""Return data for the device id."""
|
||||||
|
return self.coordinator.data[self._id]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unique_id(self):
|
def unique_id(self):
|
||||||
"""Return the unique id base on the id returned by Somfy."""
|
"""Return the unique id base on the id returned by Somfy."""
|
||||||
return self.device.id
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
@ -160,12 +179,6 @@ class SomfyEntity(Entity):
|
|||||||
"manufacturer": "Somfy",
|
"manufacturer": "Somfy",
|
||||||
}
|
}
|
||||||
|
|
||||||
async def async_update(self):
|
|
||||||
"""Update the device with the latest data."""
|
|
||||||
await update_all_devices(self.hass)
|
|
||||||
devices = self.hass.data[DOMAIN][DEVICES]
|
|
||||||
self.device = next((d for d in devices if d.id == self.device.id), self.device)
|
|
||||||
|
|
||||||
def has_capability(self, capability):
|
def has_capability(self, capability):
|
||||||
"""Test if device has a capability."""
|
"""Test if device has a capability."""
|
||||||
capabilities = self.device.capabilities
|
capabilities = self.device.capabilities
|
||||||
@ -175,13 +188,3 @@ class SomfyEntity(Entity):
|
|||||||
def assumed_state(self):
|
def assumed_state(self):
|
||||||
"""Return if the device has an assumed state."""
|
"""Return if the device has an assumed state."""
|
||||||
return not bool(self.device.states)
|
return not bool(self.device.states)
|
||||||
|
|
||||||
|
|
||||||
@Throttle(SCAN_INTERVAL)
|
|
||||||
async def update_all_devices(hass):
|
|
||||||
"""Update all the devices."""
|
|
||||||
try:
|
|
||||||
data = hass.data[DOMAIN]
|
|
||||||
data[DEVICES] = await hass.async_add_executor_job(data[API].get_devices)
|
|
||||||
except HTTPError as err:
|
|
||||||
_LOGGER.warning("Cannot update devices: %s", err.response.status_code)
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
"""Define constants for the Somfy component."""
|
"""Define constants for the Somfy component."""
|
||||||
|
|
||||||
DOMAIN = "somfy"
|
DOMAIN = "somfy"
|
||||||
|
COORDINATOR = "coordinator"
|
||||||
|
API = "api"
|
||||||
|
CONF_OPTIMISTIC = "optimistic"
|
||||||
|
@ -13,7 +13,8 @@ from homeassistant.components.cover import (
|
|||||||
from homeassistant.const import STATE_CLOSED, STATE_OPEN
|
from homeassistant.const import STATE_CLOSED, STATE_OPEN
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
|
|
||||||
from . import API, CONF_OPTIMISTIC, DEVICES, DOMAIN, SomfyEntity
|
from . import SomfyEntity
|
||||||
|
from .const import API, CONF_OPTIMISTIC, COORDINATOR, DOMAIN
|
||||||
|
|
||||||
BLIND_DEVICE_CATEGORIES = {Category.INTERIOR_BLIND.value, Category.EXTERIOR_BLIND.value}
|
BLIND_DEVICE_CATEGORIES = {Category.INTERIOR_BLIND.value, Category.EXTERIOR_BLIND.value}
|
||||||
SHUTTER_DEVICE_CATEGORIES = {Category.EXTERIOR_BLIND.value}
|
SHUTTER_DEVICE_CATEGORIES = {Category.EXTERIOR_BLIND.value}
|
||||||
@ -29,14 +30,14 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
|
|
||||||
def get_covers():
|
def get_covers():
|
||||||
"""Retrieve covers."""
|
"""Retrieve covers."""
|
||||||
devices = hass.data[DOMAIN][DEVICES]
|
domain_data = hass.data[DOMAIN]
|
||||||
|
coordinator = domain_data[COORDINATOR]
|
||||||
|
api = domain_data[API]
|
||||||
|
|
||||||
return [
|
return [
|
||||||
SomfyCover(
|
SomfyCover(coordinator, device_id, api, domain_data[CONF_OPTIMISTIC])
|
||||||
cover, hass.data[DOMAIN][API], hass.data[DOMAIN][CONF_OPTIMISTIC]
|
for device_id, device in coordinator.data.items()
|
||||||
)
|
if SUPPORTED_CATEGORIES & set(device.categories)
|
||||||
for cover in devices
|
|
||||||
if SUPPORTED_CATEGORIES & set(cover.categories)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
async_add_entities(await hass.async_add_executor_job(get_covers))
|
async_add_entities(await hass.async_add_executor_job(get_covers))
|
||||||
@ -45,11 +46,11 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
class SomfyCover(SomfyEntity, RestoreEntity, CoverEntity):
|
class SomfyCover(SomfyEntity, RestoreEntity, CoverEntity):
|
||||||
"""Representation of a Somfy cover device."""
|
"""Representation of a Somfy cover device."""
|
||||||
|
|
||||||
def __init__(self, device, api, optimistic):
|
def __init__(self, coordinator, device_id, api, optimistic):
|
||||||
"""Initialize the Somfy device."""
|
"""Initialize the Somfy device."""
|
||||||
super().__init__(device, api)
|
super().__init__(coordinator, device_id, api)
|
||||||
self.cover = Blind(self.device, self.api)
|
self.cover = Blind(self.device, self.api)
|
||||||
self.categories = set(device.categories)
|
self.categories = set(self.device.categories)
|
||||||
self.optimistic = optimistic
|
self.optimistic = optimistic
|
||||||
self._closed = None
|
self._closed = None
|
||||||
self._is_opening = None
|
self._is_opening = None
|
||||||
@ -163,7 +164,8 @@ class SomfyCover(SomfyEntity, RestoreEntity, CoverEntity):
|
|||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Complete the initialization."""
|
"""Complete the initialization."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if self.optimistic:
|
if not self.optimistic:
|
||||||
|
return
|
||||||
# Restore the last state if we use optimistic
|
# Restore the last state if we use optimistic
|
||||||
last_state = await self.async_get_last_state()
|
last_state = await self.async_get_last_state()
|
||||||
|
|
||||||
@ -172,5 +174,3 @@ class SomfyCover(SomfyEntity, RestoreEntity, CoverEntity):
|
|||||||
STATE_CLOSED,
|
STATE_CLOSED,
|
||||||
):
|
):
|
||||||
self._closed = last_state.state == STATE_CLOSED
|
self._closed = last_state.state == STATE_CLOSED
|
||||||
|
|
||||||
await self.async_update()
|
|
||||||
|
@ -4,7 +4,8 @@ from pymfy.api.devices.category import Category
|
|||||||
|
|
||||||
from homeassistant.components.switch import SwitchEntity
|
from homeassistant.components.switch import SwitchEntity
|
||||||
|
|
||||||
from . import API, DEVICES, DOMAIN, SomfyEntity
|
from . import SomfyEntity
|
||||||
|
from .const import API, COORDINATOR, DOMAIN
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
@ -12,11 +13,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
|
|
||||||
def get_shutters():
|
def get_shutters():
|
||||||
"""Retrieve switches."""
|
"""Retrieve switches."""
|
||||||
devices = hass.data[DOMAIN][DEVICES]
|
domain_data = hass.data[DOMAIN]
|
||||||
|
coordinator = domain_data[COORDINATOR]
|
||||||
|
api = domain_data[API]
|
||||||
|
|
||||||
return [
|
return [
|
||||||
SomfyCameraShutter(device, hass.data[DOMAIN][API])
|
SomfyCameraShutter(coordinator, device_id, api)
|
||||||
for device in devices
|
for device_id, device in coordinator.data.items()
|
||||||
if Category.CAMERA.value in device.categories
|
if Category.CAMERA.value in device.categories
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -26,9 +29,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
class SomfyCameraShutter(SomfyEntity, SwitchEntity):
|
class SomfyCameraShutter(SomfyEntity, SwitchEntity):
|
||||||
"""Representation of a Somfy Camera Shutter device."""
|
"""Representation of a Somfy Camera Shutter device."""
|
||||||
|
|
||||||
def __init__(self, device, api):
|
def __init__(self, coordinator, device_id, api):
|
||||||
"""Initialize the Somfy device."""
|
"""Initialize the Somfy device."""
|
||||||
super().__init__(device, api)
|
super().__init__(coordinator, device_id, api)
|
||||||
self.shutter = CameraProtect(self.device, self.api)
|
self.shutter = CameraProtect(self.device, self.api)
|
||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user