Convert somfy to use DataUpdateCoordinator (#42434)

This commit is contained in:
J. Nick Koston 2020-10-26 23:42:12 -05:00 committed by GitHub
parent f3a15eab6e
commit df25feab37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 60 deletions

View File

@ -4,7 +4,6 @@ from datetime import timedelta
import logging
from pymfy.api.devices.category import Category
from requests import HTTPError
import voluptuous as vol
from homeassistant.components.somfy import config_flow
@ -17,22 +16,19 @@ from homeassistant.helpers import (
)
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.typing import HomeAssistantType
from homeassistant.util import Throttle
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
)
from . import api
from .const import DOMAIN
API = "api"
DEVICES = "devices"
from .const import API, CONF_OPTIMISTIC, COORDINATOR, DOMAIN
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(minutes=1)
CONF_OPTIMISTIC = "optimistic"
SOMFY_AUTH_CALLBACK_PATH = "/auth/somfy/callback"
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)
hass.data[DOMAIN][DEVICES] = []
data = hass.data[DOMAIN]
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)
devices = hass.data[DOMAIN][DEVICES]
hubs = [device for device in devices if Category.HUB.value in device.categories]
hubs = [
device
for device in coordinator.data.values()
if Category.HUB.value in device.categories
]
for hub in hubs:
device_registry.async_get_or_create(
@ -127,18 +140,24 @@ async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry):
return True
class SomfyEntity(Entity):
class SomfyEntity(CoordinatorEntity, Entity):
"""Representation of a generic Somfy device."""
def __init__(self, device, somfy_api):
def __init__(self, coordinator, device_id, somfy_api):
"""Initialize the Somfy device."""
self.device = device
super().__init__(coordinator)
self._id = device_id
self.api = somfy_api
@property
def device(self):
"""Return data for the device id."""
return self.coordinator.data[self._id]
@property
def unique_id(self):
"""Return the unique id base on the id returned by Somfy."""
return self.device.id
return self._id
@property
def name(self):
@ -160,12 +179,6 @@ class SomfyEntity(Entity):
"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):
"""Test if device has a capability."""
capabilities = self.device.capabilities
@ -175,13 +188,3 @@ class SomfyEntity(Entity):
def assumed_state(self):
"""Return if the device has an assumed state."""
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)

View File

@ -1,3 +1,6 @@
"""Define constants for the Somfy component."""
DOMAIN = "somfy"
COORDINATOR = "coordinator"
API = "api"
CONF_OPTIMISTIC = "optimistic"

View File

@ -13,7 +13,8 @@ from homeassistant.components.cover import (
from homeassistant.const import STATE_CLOSED, STATE_OPEN
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}
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():
"""Retrieve covers."""
devices = hass.data[DOMAIN][DEVICES]
domain_data = hass.data[DOMAIN]
coordinator = domain_data[COORDINATOR]
api = domain_data[API]
return [
SomfyCover(
cover, hass.data[DOMAIN][API], hass.data[DOMAIN][CONF_OPTIMISTIC]
)
for cover in devices
if SUPPORTED_CATEGORIES & set(cover.categories)
SomfyCover(coordinator, device_id, api, domain_data[CONF_OPTIMISTIC])
for device_id, device in coordinator.data.items()
if SUPPORTED_CATEGORIES & set(device.categories)
]
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):
"""Representation of a Somfy cover device."""
def __init__(self, device, api, optimistic):
def __init__(self, coordinator, device_id, api, optimistic):
"""Initialize the Somfy device."""
super().__init__(device, api)
super().__init__(coordinator, device_id, api)
self.cover = Blind(self.device, self.api)
self.categories = set(device.categories)
self.categories = set(self.device.categories)
self.optimistic = optimistic
self._closed = None
self._is_opening = None
@ -163,14 +164,13 @@ class SomfyCover(SomfyEntity, RestoreEntity, CoverEntity):
async def async_added_to_hass(self):
"""Complete the initialization."""
await super().async_added_to_hass()
if self.optimistic:
# Restore the last state if we use optimistic
last_state = await self.async_get_last_state()
if not self.optimistic:
return
# Restore the last state if we use optimistic
last_state = await self.async_get_last_state()
if last_state is not None and last_state.state in (
STATE_OPEN,
STATE_CLOSED,
):
self._closed = last_state.state == STATE_CLOSED
await self.async_update()
if last_state is not None and last_state.state in (
STATE_OPEN,
STATE_CLOSED,
):
self._closed = last_state.state == STATE_CLOSED

View File

@ -4,7 +4,8 @@ from pymfy.api.devices.category import Category
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):
@ -12,11 +13,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
def get_shutters():
"""Retrieve switches."""
devices = hass.data[DOMAIN][DEVICES]
domain_data = hass.data[DOMAIN]
coordinator = domain_data[COORDINATOR]
api = domain_data[API]
return [
SomfyCameraShutter(device, hass.data[DOMAIN][API])
for device in devices
SomfyCameraShutter(coordinator, device_id, api)
for device_id, device in coordinator.data.items()
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):
"""Representation of a Somfy Camera Shutter device."""
def __init__(self, device, api):
def __init__(self, coordinator, device_id, api):
"""Initialize the Somfy device."""
super().__init__(device, api)
super().__init__(coordinator, device_id, api)
self.shutter = CameraProtect(self.device, self.api)
async def async_update(self):