Address feedback to Overkiz integration (round 2) (#63036)
* Address feedback in multiple files * Add missing return statement * Improve sensor descriptions * Improve typing * Move to new device registry * Disable RSSI sensor by default * Improve typing
This commit is contained in:
parent
52ca06c750
commit
8599ddf51e
11 changed files with 30 additions and 33 deletions
|
@ -41,7 +41,7 @@ class HomeAssistantOverkizData:
|
||||||
"""Overkiz data stored in the Home Assistant data object."""
|
"""Overkiz data stored in the Home Assistant data object."""
|
||||||
|
|
||||||
coordinator: OverkizDataUpdateCoordinator
|
coordinator: OverkizDataUpdateCoordinator
|
||||||
platforms: dict[Platform, Device | Scenario]
|
platforms: defaultdict[Platform, list[Device | Scenario]]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
@ -74,9 +74,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
raise ConfigEntryNotReady("Failed to connect") from exception
|
raise ConfigEntryNotReady("Failed to connect") from exception
|
||||||
except MaintenanceException as exception:
|
except MaintenanceException as exception:
|
||||||
raise ConfigEntryNotReady("Server is down for maintenance") from exception
|
raise ConfigEntryNotReady("Server is down for maintenance") from exception
|
||||||
except Exception as exception: # pylint: disable=broad-except
|
|
||||||
_LOGGER.exception(exception)
|
|
||||||
return False
|
|
||||||
|
|
||||||
coordinator = OverkizDataUpdateCoordinator(
|
coordinator = OverkizDataUpdateCoordinator(
|
||||||
hass,
|
hass,
|
||||||
|
@ -98,7 +95,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
)
|
)
|
||||||
coordinator.update_interval = UPDATE_INTERVAL_ALL_ASSUMED_STATE
|
coordinator.update_interval = UPDATE_INTERVAL_ALL_ASSUMED_STATE
|
||||||
|
|
||||||
platforms: dict[Platform, Device | Scenario] = defaultdict(list)
|
platforms: defaultdict[Platform, list[Device | Scenario]] = defaultdict(list)
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = HomeAssistantOverkizData(
|
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = HomeAssistantOverkizData(
|
||||||
coordinator=coordinator,
|
coordinator=coordinator,
|
||||||
|
@ -121,7 +118,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
|
||||||
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
|
hass.config_entries.async_setup_platforms(entry, PLATFORMS)
|
||||||
|
|
||||||
device_registry = await dr.async_get_registry(hass)
|
device_registry = dr.async_get(hass)
|
||||||
|
|
||||||
for gateway in setup.gateways:
|
for gateway in setup.gateways:
|
||||||
_LOGGER.debug("Added gateway (%s)", gateway)
|
_LOGGER.debug("Added gateway (%s)", gateway)
|
||||||
|
|
|
@ -46,7 +46,7 @@ async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: ConfigEntry,
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
):
|
) -> None:
|
||||||
"""Set up the Overkiz button from a config entry."""
|
"""Set up the Overkiz button from a config entry."""
|
||||||
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
||||||
entities: list[ButtonEntity] = []
|
entities: list[ButtonEntity] = []
|
||||||
|
|
|
@ -19,6 +19,7 @@ from homeassistant import config_entries
|
||||||
from homeassistant.components import dhcp
|
from homeassistant.components import dhcp
|
||||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||||
from homeassistant.data_entry_flow import FlowResult
|
from homeassistant.data_entry_flow import FlowResult
|
||||||
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
|
||||||
from .const import CONF_HUB, DEFAULT_HUB, DOMAIN
|
from .const import CONF_HUB, DEFAULT_HUB, DOMAIN
|
||||||
|
|
||||||
|
@ -35,9 +36,13 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
username = user_input[CONF_USERNAME]
|
username = user_input[CONF_USERNAME]
|
||||||
password = user_input[CONF_PASSWORD]
|
password = user_input[CONF_PASSWORD]
|
||||||
server = SUPPORTED_SERVERS[user_input[CONF_HUB]]
|
server = SUPPORTED_SERVERS[user_input[CONF_HUB]]
|
||||||
|
session = async_get_clientsession(self.hass)
|
||||||
|
|
||||||
async with OverkizClient(
|
async with OverkizClient(
|
||||||
username=username, password=password, server=server
|
username=username,
|
||||||
|
password=password,
|
||||||
|
server=server,
|
||||||
|
session=session,
|
||||||
) as client:
|
) as client:
|
||||||
await client.login()
|
await client.login()
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ from pyoverkiz.exceptions import (
|
||||||
from pyoverkiz.models import DataType, Device, Place, State
|
from pyoverkiz.models import DataType, Device, Place, State
|
||||||
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import device_registry
|
from homeassistant.helpers import device_registry as dr
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
from .const import DOMAIN, UPDATE_INTERVAL
|
from .const import DOMAIN, UPDATE_INTERVAL
|
||||||
|
@ -97,9 +97,6 @@ class OverkizDataUpdateCoordinator(DataUpdateCoordinator):
|
||||||
raise UpdateFailed("Too many requests, try again later.") from exception
|
raise UpdateFailed("Too many requests, try again later.") from exception
|
||||||
|
|
||||||
return self.devices
|
return self.devices
|
||||||
except Exception as exception:
|
|
||||||
_LOGGER.debug(exception)
|
|
||||||
raise UpdateFailed(exception) from exception
|
|
||||||
|
|
||||||
for event in events:
|
for event in events:
|
||||||
_LOGGER.debug(event)
|
_LOGGER.debug(event)
|
||||||
|
@ -123,7 +120,7 @@ class OverkizDataUpdateCoordinator(DataUpdateCoordinator):
|
||||||
|
|
||||||
elif event.name == EventName.DEVICE_REMOVED:
|
elif event.name == EventName.DEVICE_REMOVED:
|
||||||
base_device_url, *_ = event.device_url.split("#")
|
base_device_url, *_ = event.device_url.split("#")
|
||||||
registry = await device_registry.async_get_registry(self.hass)
|
registry = dr.async_get(self.hass)
|
||||||
|
|
||||||
if registered_device := registry.async_get_device(
|
if registered_device := registry.async_get_device(
|
||||||
{(DOMAIN, base_device_url)}
|
{(DOMAIN, base_device_url)}
|
||||||
|
@ -176,7 +173,7 @@ class OverkizDataUpdateCoordinator(DataUpdateCoordinator):
|
||||||
cast_to_python = DATA_TYPE_TO_PYTHON[data_type]
|
cast_to_python = DATA_TYPE_TO_PYTHON[data_type]
|
||||||
return cast_to_python(state.value)
|
return cast_to_python(state.value)
|
||||||
|
|
||||||
def places_to_area(self, place):
|
def places_to_area(self, place: Place) -> dict[str, str]:
|
||||||
"""Convert places with sub_places to a flat dictionary."""
|
"""Convert places with sub_places to a flat dictionary."""
|
||||||
areas = {}
|
areas = {}
|
||||||
if isinstance(place, Place):
|
if isinstance(place, Place):
|
||||||
|
|
|
@ -74,7 +74,7 @@ class OverkizEntity(CoordinatorEntity):
|
||||||
),
|
),
|
||||||
hw_version=self.device.controllable_name,
|
hw_version=self.device.controllable_name,
|
||||||
suggested_area=self.coordinator.areas[self.device.place_oid],
|
suggested_area=self.coordinator.areas[self.device.place_oid],
|
||||||
via_device=self.executor.get_gateway_id(),
|
via_device=(DOMAIN, self.executor.get_gateway_id()),
|
||||||
configuration_url=self.coordinator.client.server.configuration_url,
|
configuration_url=self.coordinator.client.server.configuration_url,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ class OverkizExecutor:
|
||||||
"""Return True if a command exists in a list of commands."""
|
"""Return True if a command exists in a list of commands."""
|
||||||
return self.select_command(*commands) is not None
|
return self.select_command(*commands) is not None
|
||||||
|
|
||||||
def select_state(self, *states) -> str | None:
|
def select_state(self, *states: str) -> str | None:
|
||||||
"""Select first existing active state in a list of states."""
|
"""Select first existing active state in a list of states."""
|
||||||
for state in states:
|
for state in states:
|
||||||
if current_state := self.device.states[state]:
|
if current_state := self.device.states[state]:
|
||||||
|
@ -49,7 +49,7 @@ class OverkizExecutor:
|
||||||
"""Return True if a state exists in self."""
|
"""Return True if a state exists in self."""
|
||||||
return self.select_state(*states) is not None
|
return self.select_state(*states) is not None
|
||||||
|
|
||||||
def select_attribute(self, *attributes) -> str | None:
|
def select_attribute(self, *attributes: str) -> str | None:
|
||||||
"""Select first existing active state in a list of states."""
|
"""Select first existing active state in a list of states."""
|
||||||
for attribute in attributes:
|
for attribute in attributes:
|
||||||
if current_attribute := self.device.attributes[attribute]:
|
if current_attribute := self.device.attributes[attribute]:
|
||||||
|
@ -57,7 +57,7 @@ class OverkizExecutor:
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def async_execute_command(self, command_name: str, *args: Any):
|
async def async_execute_command(self, command_name: str, *args: Any) -> None:
|
||||||
"""Execute device command in async context."""
|
"""Execute device command in async context."""
|
||||||
try:
|
try:
|
||||||
exec_id = await self.coordinator.client.execute_command(
|
exec_id = await self.coordinator.client.execute_command(
|
||||||
|
@ -118,11 +118,11 @@ class OverkizExecutor:
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def async_cancel_execution(self, exec_id: str):
|
async def async_cancel_execution(self, exec_id: str) -> None:
|
||||||
"""Cancel running execution via execution id."""
|
"""Cancel running execution via execution id."""
|
||||||
await self.coordinator.client.cancel_command(exec_id)
|
await self.coordinator.client.cancel_command(exec_id)
|
||||||
|
|
||||||
def get_gateway_id(self):
|
def get_gateway_id(self) -> str:
|
||||||
"""
|
"""
|
||||||
Retrieve gateway id from device url.
|
Retrieve gateway id from device url.
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: ConfigEntry,
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
):
|
) -> None:
|
||||||
"""Set up the Overkiz lights from a config entry."""
|
"""Set up the Overkiz lights from a config entry."""
|
||||||
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: ConfigEntry,
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
):
|
) -> None:
|
||||||
"""Set up the Overkiz locks from a config entry."""
|
"""Set up the Overkiz locks from a config entry."""
|
||||||
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: ConfigEntry,
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
):
|
) -> None:
|
||||||
"""Set up the Overkiz number from a config entry."""
|
"""Set up the Overkiz number from a config entry."""
|
||||||
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
||||||
entities: list[OverkizNumber] = []
|
entities: list[OverkizNumber] = []
|
||||||
|
@ -89,12 +89,12 @@ class OverkizNumber(OverkizDescriptiveEntity, NumberEntity):
|
||||||
entity_description: OverkizNumberDescription
|
entity_description: OverkizNumberDescription
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> float:
|
def value(self) -> float | None:
|
||||||
"""Return the entity value to represent the entity state."""
|
"""Return the entity value to represent the entity state."""
|
||||||
if state := self.device.states.get(self.entity_description.key):
|
if state := self.device.states.get(self.entity_description.key):
|
||||||
return state.value
|
return state.value
|
||||||
|
|
||||||
return 0
|
return None
|
||||||
|
|
||||||
async def async_set_value(self, value: float) -> None:
|
async def async_set_value(self, value: float) -> None:
|
||||||
"""Set new value."""
|
"""Set new value."""
|
||||||
|
|
|
@ -20,7 +20,7 @@ async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: ConfigEntry,
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
):
|
) -> None:
|
||||||
"""Set up the Overkiz scenes from a config entry."""
|
"""Set up the Overkiz scenes from a config entry."""
|
||||||
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ from homeassistant.const import (
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
|
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.typing import StateType
|
||||||
|
|
||||||
from . import HomeAssistantOverkizData
|
from . import HomeAssistantOverkizData
|
||||||
from .const import DOMAIN, IGNORED_OVERKIZ_DEVICES
|
from .const import DOMAIN, IGNORED_OVERKIZ_DEVICES
|
||||||
|
@ -54,7 +55,6 @@ SENSOR_DESCRIPTIONS: list[OverkizSensorDescription] = [
|
||||||
OverkizSensorDescription(
|
OverkizSensorDescription(
|
||||||
key=OverkizState.CORE_BATTERY,
|
key=OverkizState.CORE_BATTERY,
|
||||||
name="Battery",
|
name="Battery",
|
||||||
device_class=SensorDeviceClass.BATTERY,
|
|
||||||
native_value=lambda value: str(value).capitalize(),
|
native_value=lambda value: str(value).capitalize(),
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
|
@ -66,6 +66,7 @@ SENSOR_DESCRIPTIONS: list[OverkizSensorDescription] = [
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
native_value=lambda value: round(float(value)),
|
native_value=lambda value: round(float(value)),
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
),
|
),
|
||||||
OverkizSensorDescription(
|
OverkizSensorDescription(
|
||||||
key=OverkizState.CORE_EXPECTED_NUMBER_OF_SHOWER,
|
key=OverkizState.CORE_EXPECTED_NUMBER_OF_SHOWER,
|
||||||
|
@ -126,7 +127,6 @@ SENSOR_DESCRIPTIONS: list[OverkizSensorDescription] = [
|
||||||
OverkizSensorDescription(
|
OverkizSensorDescription(
|
||||||
key=OverkizState.CORE_FOSSIL_ENERGY_CONSUMPTION,
|
key=OverkizState.CORE_FOSSIL_ENERGY_CONSUMPTION,
|
||||||
name="Fossil Energy Consumption",
|
name="Fossil Energy Consumption",
|
||||||
device_class=SensorDeviceClass.ENERGY,
|
|
||||||
),
|
),
|
||||||
OverkizSensorDescription(
|
OverkizSensorDescription(
|
||||||
key=OverkizState.CORE_GAS_CONSUMPTION,
|
key=OverkizState.CORE_GAS_CONSUMPTION,
|
||||||
|
@ -292,7 +292,6 @@ SENSOR_DESCRIPTIONS: list[OverkizSensorDescription] = [
|
||||||
key=OverkizState.CORE_SUN_ENERGY,
|
key=OverkizState.CORE_SUN_ENERGY,
|
||||||
name="Sun Energy",
|
name="Sun Energy",
|
||||||
native_value=lambda value: round(float(value), 2),
|
native_value=lambda value: round(float(value), 2),
|
||||||
device_class=SensorDeviceClass.ENERGY,
|
|
||||||
icon="mdi:solar-power",
|
icon="mdi:solar-power",
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
|
@ -330,7 +329,6 @@ SENSOR_DESCRIPTIONS: list[OverkizSensorDescription] = [
|
||||||
name="Discrete RSSI Level",
|
name="Discrete RSSI Level",
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
native_value=lambda value: str(value).capitalize(),
|
native_value=lambda value: str(value).capitalize(),
|
||||||
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
# DomesticHotWaterProduction/WaterHeatingSystem
|
# DomesticHotWaterProduction/WaterHeatingSystem
|
||||||
|
@ -349,7 +347,7 @@ async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entry: ConfigEntry,
|
entry: ConfigEntry,
|
||||||
async_add_entities: AddEntitiesCallback,
|
async_add_entities: AddEntitiesCallback,
|
||||||
):
|
) -> None:
|
||||||
"""Set up the Overkiz sensors from a config entry."""
|
"""Set up the Overkiz sensors from a config entry."""
|
||||||
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id]
|
||||||
entities: list[SensorEntity] = []
|
entities: list[SensorEntity] = []
|
||||||
|
@ -392,7 +390,7 @@ class OverkizStateSensor(OverkizDescriptiveEntity, SensorEntity):
|
||||||
entity_description: OverkizSensorDescription
|
entity_description: OverkizSensorDescription
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_value(self):
|
def native_value(self) -> StateType:
|
||||||
"""Return the value of the sensor."""
|
"""Return the value of the sensor."""
|
||||||
state = self.device.states.get(self.entity_description.key)
|
state = self.device.states.get(self.entity_description.key)
|
||||||
|
|
||||||
|
@ -420,7 +418,7 @@ class OverkizHomeKitSetupCodeSensor(OverkizEntity, SensorEntity):
|
||||||
self._attr_name = "HomeKit Setup Code"
|
self._attr_name = "HomeKit Setup Code"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_value(self):
|
def native_value(self) -> str:
|
||||||
"""Return the value of the sensor."""
|
"""Return the value of the sensor."""
|
||||||
return self.device.attributes.get(OverkizAttribute.HOMEKIT_SETUP_CODE).value
|
return self.device.attributes.get(OverkizAttribute.HOMEKIT_SETUP_CODE).value
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue