Skip to content

Commit

Permalink
Convert somfy to use DataUpdateCoordinator
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco committed Oct 26, 2020
1 parent bcc2458 commit 5badfc5
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 49 deletions.
69 changes: 36 additions & 33 deletions homeassistant/components/somfy/__init__.py
Expand Up @@ -4,7 +4,6 @@
import logging

from pymfy.api.devices.category import Category
from requests import HTTPError
import voluptuous as vol

from homeassistant.components.somfy import config_flow
Expand All @@ -17,22 +16,19 @@
)
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"

Expand Down Expand Up @@ -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)

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 update_all_devices(hass)
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(
Expand Down Expand Up @@ -127,14 +140,20 @@ 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, id, somfy_api):
"""Initialize the Somfy device."""
self.device = device
super().__init__(coordinator)
self.id = 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."""
Expand All @@ -160,12 +179,6 @@ def device_info(self):
"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
Expand All @@ -175,13 +188,3 @@ def has_capability(self, capability):
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)
3 changes: 3 additions & 0 deletions homeassistant/components/somfy/const.py
@@ -1,3 +1,6 @@
"""Define constants for the Somfy component."""

DOMAIN = "somfy"
COORDINATOR = "coordinator"
API = "api"
CONF_OPTIMISTIC = "optimistic"
21 changes: 11 additions & 10 deletions homeassistant/components/somfy/cover.py
Expand Up @@ -14,7 +14,8 @@
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}
Expand All @@ -30,14 +31,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))
Expand All @@ -46,11 +47,11 @@ def get_covers():
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
Expand Down
15 changes: 9 additions & 6 deletions homeassistant/components/somfy/switch.py
Expand Up @@ -4,19 +4,22 @@

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):
"""Set up the Somfy switch platform."""

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
]

Expand All @@ -26,9 +29,9 @@ def get_shutters():
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):
Expand Down

0 comments on commit 5badfc5

Please sign in to comment.