Use update coordinator for Xioami Miio subdevices (#46251)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
add0d9d3eb
commit
9d8ba6af96
6 changed files with 55 additions and 39 deletions
|
@ -1,7 +1,13 @@
|
|||
"""Support for Xiaomi Miio."""
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from miio.gateway import GatewayException
|
||||
|
||||
from homeassistant import config_entries, core
|
||||
from homeassistant.const import CONF_HOST, CONF_TOKEN
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import (
|
||||
CONF_DEVICE,
|
||||
|
@ -9,10 +15,13 @@ from .const import (
|
|||
CONF_GATEWAY,
|
||||
CONF_MODEL,
|
||||
DOMAIN,
|
||||
KEY_COORDINATOR,
|
||||
MODELS_SWITCH,
|
||||
)
|
||||
from .gateway import ConnectXiaomiGateway
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
GATEWAY_PLATFORMS = ["alarm_control_panel", "sensor", "light"]
|
||||
SWITCH_PLATFORMS = ["switch"]
|
||||
|
||||
|
@ -56,8 +65,6 @@ async def async_setup_gateway_entry(
|
|||
return False
|
||||
gateway_info = gateway.gateway_info
|
||||
|
||||
hass.data[DOMAIN][entry.entry_id] = gateway.gateway_device
|
||||
|
||||
gateway_model = f"{gateway_info.model}-{gateway_info.hardware_version}"
|
||||
|
||||
device_registry = await dr.async_get_registry(hass)
|
||||
|
@ -71,6 +78,30 @@ async def async_setup_gateway_entry(
|
|||
sw_version=gateway_info.firmware_version,
|
||||
)
|
||||
|
||||
async def async_update_data():
|
||||
"""Fetch data from the subdevice."""
|
||||
try:
|
||||
for sub_device in gateway.gateway_device.devices.values():
|
||||
await hass.async_add_executor_job(sub_device.update)
|
||||
except GatewayException as ex:
|
||||
raise UpdateFailed("Got exception while fetching the state") from ex
|
||||
|
||||
# Create update coordinator
|
||||
coordinator = DataUpdateCoordinator(
|
||||
hass,
|
||||
_LOGGER,
|
||||
# Name of the data. For logging purposes.
|
||||
name=name,
|
||||
update_method=async_update_data,
|
||||
# Polling interval. Will only be polled if there are subscribers.
|
||||
update_interval=timedelta(seconds=10),
|
||||
)
|
||||
|
||||
hass.data[DOMAIN][entry.entry_id] = {
|
||||
CONF_GATEWAY: gateway.gateway_device,
|
||||
KEY_COORDINATOR: coordinator,
|
||||
}
|
||||
|
||||
for component in GATEWAY_PLATFORMS:
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(entry, component)
|
||||
|
|
|
@ -15,7 +15,7 @@ from homeassistant.const import (
|
|||
STATE_ALARM_DISARMED,
|
||||
)
|
||||
|
||||
from .const import DOMAIN
|
||||
from .const import CONF_GATEWAY, DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -27,7 +27,7 @@ XIAOMI_STATE_ARMING_VALUE = "oning"
|
|||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Set up the Xiaomi Gateway Alarm from a config entry."""
|
||||
entities = []
|
||||
gateway = hass.data[DOMAIN][config_entry.entry_id]
|
||||
gateway = hass.data[DOMAIN][config_entry.entry_id][CONF_GATEWAY]
|
||||
entity = XiaomiGatewayAlarm(
|
||||
gateway,
|
||||
f"{config_entry.title} Alarm",
|
||||
|
|
|
@ -7,6 +7,8 @@ CONF_DEVICE = "device"
|
|||
CONF_MODEL = "model"
|
||||
CONF_MAC = "mac"
|
||||
|
||||
KEY_COORDINATOR = "coordinator"
|
||||
|
||||
MODELS_GATEWAY = ["lumi.gateway", "lumi.acpartner"]
|
||||
MODELS_SWITCH = [
|
||||
"chuangmi.plug.v1",
|
||||
|
|
|
@ -4,6 +4,7 @@ import logging
|
|||
from miio import DeviceException, gateway
|
||||
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
|
@ -56,16 +57,16 @@ class ConnectXiaomiGateway:
|
|||
return True
|
||||
|
||||
|
||||
class XiaomiGatewayDevice(Entity):
|
||||
class XiaomiGatewayDevice(CoordinatorEntity, Entity):
|
||||
"""Representation of a base Xiaomi Gateway Device."""
|
||||
|
||||
def __init__(self, sub_device, entry):
|
||||
def __init__(self, coordinator, sub_device, entry):
|
||||
"""Initialize the Xiaomi Gateway Device."""
|
||||
super().__init__(coordinator)
|
||||
self._sub_device = sub_device
|
||||
self._entry = entry
|
||||
self._unique_id = sub_device.sid
|
||||
self._name = f"{sub_device.name} ({sub_device.sid})"
|
||||
self._available = False
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
|
@ -88,18 +89,3 @@ class XiaomiGatewayDevice(Entity):
|
|||
"model": self._sub_device.model,
|
||||
"sw_version": self._sub_device.firmware_version,
|
||||
}
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
"""Return true when state is known."""
|
||||
return self._available
|
||||
|
||||
async def async_update(self):
|
||||
"""Fetch state from the sub device."""
|
||||
try:
|
||||
await self.hass.async_add_executor_job(self._sub_device.update)
|
||||
self._available = True
|
||||
except gateway.GatewayException as ex:
|
||||
if self._available:
|
||||
self._available = False
|
||||
_LOGGER.error("Got exception while fetching the state: %s", ex)
|
||||
|
|
|
@ -130,7 +130,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
entities = []
|
||||
|
||||
if config_entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY:
|
||||
gateway = hass.data[DOMAIN][config_entry.entry_id]
|
||||
gateway = hass.data[DOMAIN][config_entry.entry_id][CONF_GATEWAY]
|
||||
# Gateway light
|
||||
if gateway.model not in [
|
||||
GATEWAY_MODEL_AC_V1,
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
from dataclasses import dataclass
|
||||
import logging
|
||||
|
||||
from miio import AirQualityMonitor, DeviceException # pylint: disable=import-error
|
||||
from miio import AirQualityMonitor # pylint: disable=import-error
|
||||
from miio import DeviceException
|
||||
from miio.gateway import (
|
||||
GATEWAY_MODEL_AC_V1,
|
||||
GATEWAY_MODEL_AC_V2,
|
||||
GATEWAY_MODEL_AC_V3,
|
||||
GATEWAY_MODEL_EU,
|
||||
DeviceType,
|
||||
GatewayException,
|
||||
)
|
||||
import voluptuous as vol
|
||||
|
@ -31,7 +31,7 @@ from homeassistant.exceptions import PlatformNotReady
|
|||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from .const import CONF_FLOW_TYPE, CONF_GATEWAY, DOMAIN
|
||||
from .const import CONF_FLOW_TYPE, CONF_GATEWAY, DOMAIN, KEY_COORDINATOR
|
||||
from .gateway import XiaomiGatewayDevice
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -87,7 +87,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
entities = []
|
||||
|
||||
if config_entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY:
|
||||
gateway = hass.data[DOMAIN][config_entry.entry_id]
|
||||
gateway = hass.data[DOMAIN][config_entry.entry_id][CONF_GATEWAY]
|
||||
# Gateway illuminance sensor
|
||||
if gateway.model not in [
|
||||
GATEWAY_MODEL_AC_V1,
|
||||
|
@ -102,16 +102,15 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
)
|
||||
# Gateway sub devices
|
||||
sub_devices = gateway.devices
|
||||
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR]
|
||||
for sub_device in sub_devices.values():
|
||||
sensor_variables = None
|
||||
if sub_device.type == DeviceType.SensorHT:
|
||||
sensor_variables = ["temperature", "humidity"]
|
||||
if sub_device.type == DeviceType.AqaraHT:
|
||||
sensor_variables = ["temperature", "humidity", "pressure"]
|
||||
if sensor_variables is not None:
|
||||
sensor_variables = set(sub_device.status) & set(GATEWAY_SENSOR_TYPES)
|
||||
if sensor_variables:
|
||||
entities.extend(
|
||||
[
|
||||
XiaomiGatewaySensor(sub_device, config_entry, variable)
|
||||
XiaomiGatewaySensor(
|
||||
coordinator, sub_device, config_entry, variable
|
||||
)
|
||||
for variable in sensor_variables
|
||||
]
|
||||
)
|
||||
|
@ -240,9 +239,9 @@ class XiaomiAirQualityMonitor(Entity):
|
|||
class XiaomiGatewaySensor(XiaomiGatewayDevice):
|
||||
"""Representation of a XiaomiGatewaySensor."""
|
||||
|
||||
def __init__(self, sub_device, entry, data_key):
|
||||
def __init__(self, coordinator, sub_device, entry, data_key):
|
||||
"""Initialize the XiaomiSensor."""
|
||||
super().__init__(sub_device, entry)
|
||||
super().__init__(coordinator, sub_device, entry)
|
||||
self._data_key = data_key
|
||||
self._unique_id = f"{sub_device.sid}-{data_key}"
|
||||
self._name = f"{data_key} ({sub_device.sid})".capitalize()
|
||||
|
@ -288,9 +287,7 @@ class XiaomiGatewayIlluminanceSensor(Entity):
|
|||
@property
|
||||
def device_info(self):
|
||||
"""Return the device info of the gateway."""
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self._gateway_device_id)},
|
||||
}
|
||||
return {"identifiers": {(DOMAIN, self._gateway_device_id)}}
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue