mirror of
https://github.com/home-assistant/core.git
synced 2025-04-26 02:07:54 +00:00
Add base entity for Sensibo (#67696)
This commit is contained in:
parent
ca32c38859
commit
af7670a5a5
@ -1015,6 +1015,7 @@ omit =
|
|||||||
homeassistant/components/sensibo/climate.py
|
homeassistant/components/sensibo/climate.py
|
||||||
homeassistant/components/sensibo/coordinator.py
|
homeassistant/components/sensibo/coordinator.py
|
||||||
homeassistant/components/sensibo/diagnostics.py
|
homeassistant/components/sensibo/diagnostics.py
|
||||||
|
homeassistant/components/sensibo/entity.py
|
||||||
homeassistant/components/sensibo/number.py
|
homeassistant/components/sensibo/number.py
|
||||||
homeassistant/components/serial/sensor.py
|
homeassistant/components/serial/sensor.py
|
||||||
homeassistant/components/serial_pm/sensor.py
|
homeassistant/components/serial_pm/sensor.py
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
"""Support for Sensibo wifi-enabled home thermostats."""
|
"""Support for Sensibo wifi-enabled home thermostats."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
|
||||||
|
|
||||||
from aiohttp.client_exceptions import ClientConnectionError
|
|
||||||
import async_timeout
|
|
||||||
from pysensibo.exceptions import AuthenticationError, SensiboError
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.climate import (
|
from homeassistant.components.climate import (
|
||||||
@ -36,15 +31,13 @@ from homeassistant.const import (
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import config_validation as cv, entity_platform
|
from homeassistant.helpers import config_validation as cv, entity_platform
|
||||||
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
|
|
||||||
from homeassistant.helpers.entity import DeviceInfo
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|
||||||
from homeassistant.util.temperature import convert as convert_temperature
|
from homeassistant.util.temperature import convert as convert_temperature
|
||||||
|
|
||||||
from .const import ALL, DOMAIN, LOGGER, TIMEOUT
|
from .const import ALL, DOMAIN, LOGGER
|
||||||
from .coordinator import SensiboDataUpdateCoordinator
|
from .coordinator import SensiboDataUpdateCoordinator
|
||||||
|
from .entity import SensiboBaseEntity
|
||||||
|
|
||||||
SERVICE_ASSUME_STATE = "assume_state"
|
SERVICE_ASSUME_STATE = "assume_state"
|
||||||
|
|
||||||
@ -126,17 +119,14 @@ async def async_setup_entry(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SensiboClimate(CoordinatorEntity, ClimateEntity):
|
class SensiboClimate(SensiboBaseEntity, ClimateEntity):
|
||||||
"""Representation of a Sensibo device."""
|
"""Representation of a Sensibo device."""
|
||||||
|
|
||||||
coordinator: SensiboDataUpdateCoordinator
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, coordinator: SensiboDataUpdateCoordinator, device_id: str
|
self, coordinator: SensiboDataUpdateCoordinator, device_id: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initiate SensiboClimate."""
|
"""Initiate SensiboClimate."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator, device_id)
|
||||||
self._client = coordinator.client
|
|
||||||
self._attr_unique_id = device_id
|
self._attr_unique_id = device_id
|
||||||
self._attr_name = coordinator.data[device_id]["name"]
|
self._attr_name = coordinator.data[device_id]["name"]
|
||||||
self._attr_temperature_unit = (
|
self._attr_temperature_unit = (
|
||||||
@ -146,17 +136,6 @@ class SensiboClimate(CoordinatorEntity, ClimateEntity):
|
|||||||
)
|
)
|
||||||
self._attr_supported_features = self.get_features()
|
self._attr_supported_features = self.get_features()
|
||||||
self._attr_precision = PRECISION_TENTHS
|
self._attr_precision = PRECISION_TENTHS
|
||||||
self._attr_device_info = DeviceInfo(
|
|
||||||
identifiers={(DOMAIN, coordinator.data[device_id]["id"])},
|
|
||||||
name=coordinator.data[device_id]["name"],
|
|
||||||
connections={(CONNECTION_NETWORK_MAC, coordinator.data[device_id]["mac"])},
|
|
||||||
manufacturer="Sensibo",
|
|
||||||
configuration_url="https://home.sensibo.com/",
|
|
||||||
model=coordinator.data[device_id]["model"],
|
|
||||||
sw_version=coordinator.data[device_id]["fw_ver"],
|
|
||||||
hw_version=coordinator.data[device_id]["fw_type"],
|
|
||||||
suggested_area=coordinator.data[device_id]["name"],
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_features(self) -> int:
|
def get_features(self) -> int:
|
||||||
"""Get supported features."""
|
"""Get supported features."""
|
||||||
@ -309,26 +288,14 @@ class SensiboClimate(CoordinatorEntity, ClimateEntity):
|
|||||||
self, name: str, value: str | int | bool, assumed_state: bool = False
|
self, name: str, value: str | int | bool, assumed_state: bool = False
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set AC state."""
|
"""Set AC state."""
|
||||||
result = {}
|
params = {
|
||||||
try:
|
"name": name,
|
||||||
async with async_timeout.timeout(TIMEOUT):
|
"value": value,
|
||||||
result = await self._client.async_set_ac_state_property(
|
"ac_states": self.coordinator.data[self.unique_id]["ac_states"],
|
||||||
self.unique_id,
|
"assumed_state": assumed_state,
|
||||||
name,
|
}
|
||||||
value,
|
result = await self.async_send_command("set_ac_state", params)
|
||||||
self.coordinator.data[self.unique_id]["ac_states"],
|
|
||||||
assumed_state,
|
|
||||||
)
|
|
||||||
except (
|
|
||||||
ClientConnectionError,
|
|
||||||
asyncio.TimeoutError,
|
|
||||||
AuthenticationError,
|
|
||||||
SensiboError,
|
|
||||||
) as err:
|
|
||||||
raise HomeAssistantError(
|
|
||||||
f"Failed to set AC state for device {self.name} to Sensibo servers: {err}"
|
|
||||||
) from err
|
|
||||||
LOGGER.debug("Result: %s", result)
|
|
||||||
if result["result"]["status"] == "Success":
|
if result["result"]["status"] == "Success":
|
||||||
self.coordinator.data[self.unique_id][AC_STATE_TO_DATA[name]] = value
|
self.coordinator.data[self.unique_id][AC_STATE_TO_DATA[name]] = value
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
77
homeassistant/components/sensibo/entity.py
Normal file
77
homeassistant/components/sensibo/entity.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
"""Base entity for Sensibo integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import async_timeout
|
||||||
|
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
|
||||||
|
from homeassistant.helpers.entity import DeviceInfo
|
||||||
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
|
from .const import DOMAIN, LOGGER, SENSIBO_ERRORS, TIMEOUT
|
||||||
|
from .coordinator import SensiboDataUpdateCoordinator
|
||||||
|
|
||||||
|
|
||||||
|
class SensiboBaseEntity(CoordinatorEntity):
|
||||||
|
"""Representation of a Sensibo numbers."""
|
||||||
|
|
||||||
|
coordinator: SensiboDataUpdateCoordinator
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
coordinator: SensiboDataUpdateCoordinator,
|
||||||
|
device_id: str,
|
||||||
|
) -> None:
|
||||||
|
"""Initiate Sensibo Number."""
|
||||||
|
super().__init__(coordinator)
|
||||||
|
self._device_id = device_id
|
||||||
|
self._client = coordinator.client
|
||||||
|
device = coordinator.data[device_id]
|
||||||
|
self._attr_device_info = DeviceInfo(
|
||||||
|
identifiers={(DOMAIN, device["id"])},
|
||||||
|
name=device["name"],
|
||||||
|
connections={(CONNECTION_NETWORK_MAC, device["mac"])},
|
||||||
|
manufacturer="Sensibo",
|
||||||
|
configuration_url="https://home.sensibo.com/",
|
||||||
|
model=device["model"],
|
||||||
|
sw_version=device["fw_ver"],
|
||||||
|
hw_version=device["fw_type"],
|
||||||
|
suggested_area=device["name"],
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_send_command(
|
||||||
|
self, command: str, params: dict[str, Any]
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
"""Send command to Sensibo api."""
|
||||||
|
try:
|
||||||
|
async with async_timeout.timeout(TIMEOUT):
|
||||||
|
result = await self.async_send_api_call(command, params)
|
||||||
|
except SENSIBO_ERRORS as err:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Failed to send command {command} for device {self.name} to Sensibo servers: {err}"
|
||||||
|
) from err
|
||||||
|
|
||||||
|
LOGGER.debug("Result: %s", result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
async def async_send_api_call(
|
||||||
|
self, command: str, params: dict[str, Any]
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
"""Send api call."""
|
||||||
|
result: dict[str, Any] = {"status": None}
|
||||||
|
if command == "set_calibration":
|
||||||
|
result = await self._client.async_set_calibration(
|
||||||
|
self._device_id,
|
||||||
|
params["data"],
|
||||||
|
)
|
||||||
|
if command == "set_ac_state":
|
||||||
|
result = await self._client.async_set_ac_state_property(
|
||||||
|
self._device_id,
|
||||||
|
params["name"],
|
||||||
|
params["value"],
|
||||||
|
params["ac_states"],
|
||||||
|
params["assumed_state"],
|
||||||
|
)
|
||||||
|
return result
|
@ -3,19 +3,16 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
import async_timeout
|
|
||||||
|
|
||||||
from homeassistant.components.number import NumberEntity, NumberEntityDescription
|
from homeassistant.components.number import NumberEntity, NumberEntityDescription
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
|
from homeassistant.helpers.entity import 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.update_coordinator import CoordinatorEntity
|
|
||||||
|
|
||||||
from .const import DOMAIN, LOGGER, SENSIBO_ERRORS, TIMEOUT
|
from .const import DOMAIN
|
||||||
from .coordinator import SensiboDataUpdateCoordinator
|
from .coordinator import SensiboDataUpdateCoordinator
|
||||||
|
from .entity import SensiboBaseEntity
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -73,10 +70,9 @@ async def async_setup_entry(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SensiboNumber(CoordinatorEntity, NumberEntity):
|
class SensiboNumber(SensiboBaseEntity, NumberEntity):
|
||||||
"""Representation of a Sensibo numbers."""
|
"""Representation of a Sensibo numbers."""
|
||||||
|
|
||||||
coordinator: SensiboDataUpdateCoordinator
|
|
||||||
entity_description: SensiboNumberEntityDescription
|
entity_description: SensiboNumberEntityDescription
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -86,25 +82,12 @@ class SensiboNumber(CoordinatorEntity, NumberEntity):
|
|||||||
entity_description: SensiboNumberEntityDescription,
|
entity_description: SensiboNumberEntityDescription,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initiate Sensibo Number."""
|
"""Initiate Sensibo Number."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator, device_id)
|
||||||
self.entity_description = entity_description
|
self.entity_description = entity_description
|
||||||
self._device_id = device_id
|
|
||||||
self._client = coordinator.client
|
|
||||||
self._attr_unique_id = f"{device_id}-{entity_description.key}"
|
self._attr_unique_id = f"{device_id}-{entity_description.key}"
|
||||||
self._attr_name = (
|
self._attr_name = (
|
||||||
f"{coordinator.data[device_id]['name']} {entity_description.name}"
|
f"{coordinator.data[device_id]['name']} {entity_description.name}"
|
||||||
)
|
)
|
||||||
self._attr_device_info = DeviceInfo(
|
|
||||||
identifiers={(DOMAIN, coordinator.data[device_id]["id"])},
|
|
||||||
name=coordinator.data[device_id]["name"],
|
|
||||||
connections={(CONNECTION_NETWORK_MAC, coordinator.data[device_id]["mac"])},
|
|
||||||
manufacturer="Sensibo",
|
|
||||||
configuration_url="https://home.sensibo.com/",
|
|
||||||
model=coordinator.data[device_id]["model"],
|
|
||||||
sw_version=coordinator.data[device_id]["fw_ver"],
|
|
||||||
hw_version=coordinator.data[device_id]["fw_type"],
|
|
||||||
suggested_area=coordinator.data[device_id]["name"],
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> float:
|
def value(self) -> float:
|
||||||
@ -114,17 +97,7 @@ class SensiboNumber(CoordinatorEntity, NumberEntity):
|
|||||||
async def async_set_value(self, value: float) -> None:
|
async def async_set_value(self, value: float) -> None:
|
||||||
"""Set value for calibration."""
|
"""Set value for calibration."""
|
||||||
data = {self.entity_description.remote_key: value}
|
data = {self.entity_description.remote_key: value}
|
||||||
try:
|
result = await self.async_send_command("set_calibration", {"data": data})
|
||||||
async with async_timeout.timeout(TIMEOUT):
|
|
||||||
result = await self._client.async_set_calibration(
|
|
||||||
self._device_id,
|
|
||||||
data,
|
|
||||||
)
|
|
||||||
except SENSIBO_ERRORS as err:
|
|
||||||
raise HomeAssistantError(
|
|
||||||
f"Failed to set calibration for device {self.name} to Sensibo servers: {err}"
|
|
||||||
) from err
|
|
||||||
LOGGER.debug("Result: %s", result)
|
|
||||||
if result["status"] == "success":
|
if result["status"] == "success":
|
||||||
self.coordinator.data[self._device_id][self.entity_description.key] = value
|
self.coordinator.data[self._device_id][self.entity_description.key] = value
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user