Moehlenhoff alpha2 sensors (#72161)

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
j-a-n 2022-05-24 11:03:49 +02:00 committed by GitHub
parent cc162bf691
commit 54f5238ef6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 152 additions and 19 deletions

View File

@ -724,8 +724,10 @@ omit =
homeassistant/components/modem_callerid/button.py
homeassistant/components/modem_callerid/sensor.py
homeassistant/components/moehlenhoff_alpha2/__init__.py
homeassistant/components/moehlenhoff_alpha2/binary_sensor.py
homeassistant/components/moehlenhoff_alpha2/climate.py
homeassistant/components/moehlenhoff_alpha2/const.py
homeassistant/components/moehlenhoff_alpha2/sensor.py
homeassistant/components/motion_blinds/__init__.py
homeassistant/components/motion_blinds/const.py
homeassistant/components/motion_blinds/cover.py

View File

@ -17,7 +17,7 @@ from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
PLATFORMS = [Platform.CLIMATE]
PLATFORMS = [Platform.CLIMATE, Platform.SENSOR, Platform.BINARY_SENSOR]
UPDATE_INTERVAL = timedelta(seconds=60)
@ -65,10 +65,16 @@ class Alpha2BaseCoordinator(DataUpdateCoordinator[dict[str, dict]]):
update_interval=UPDATE_INTERVAL,
)
async def _async_update_data(self) -> dict[str, dict]:
async def _async_update_data(self) -> dict[str, dict[str, dict]]:
"""Fetch the latest data from the source."""
await self.base.update_data()
return {ha["ID"]: ha for ha in self.base.heat_areas if ha.get("ID")}
return {
"heat_areas": {ha["ID"]: ha for ha in self.base.heat_areas if ha.get("ID")},
"heat_controls": {
hc["ID"]: hc for hc in self.base.heat_controls if hc.get("ID")
},
"io_devices": {io["ID"]: io for io in self.base.io_devices if io.get("ID")},
}
def get_cooling(self) -> bool:
"""Return if cooling mode is enabled."""

View File

@ -0,0 +1,56 @@
"""Support for Alpha2 IO device battery sensors."""
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import Alpha2BaseCoordinator
from .const import DOMAIN
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Add Alpha2 sensor entities from a config_entry."""
coordinator: Alpha2BaseCoordinator = hass.data[DOMAIN][config_entry.entry_id]
async_add_entities(
Alpha2IODeviceBatterySensor(coordinator, io_device_id)
for io_device_id, io_device in coordinator.data["io_devices"].items()
if io_device["_HEATAREA_ID"]
)
class Alpha2IODeviceBatterySensor(
CoordinatorEntity[Alpha2BaseCoordinator], BinarySensorEntity
):
"""Alpha2 IO device battery binary sensor."""
_attr_device_class = BinarySensorDeviceClass.BATTERY
_attr_entity_category = EntityCategory.DIAGNOSTIC
def __init__(self, coordinator: Alpha2BaseCoordinator, io_device_id: str) -> None:
"""Initialize Alpha2IODeviceBatterySensor."""
super().__init__(coordinator)
self.io_device_id = io_device_id
self._attr_unique_id = f"{io_device_id}:battery"
io_device = self.coordinator.data["io_devices"][io_device_id]
heat_area = self.coordinator.data["heat_areas"][io_device["_HEATAREA_ID"]]
self._attr_name = (
f"{heat_area['HEATAREA_NAME']} IO device {io_device['NR']} battery"
)
@property
def is_on(self):
"""Return the state of the sensor."""
# 0=empty, 1=weak, 2=good
return self.coordinator.data["io_devices"][self.io_device_id]["BATTERY"] < 2

View File

@ -29,7 +29,8 @@ async def async_setup_entry(
coordinator: Alpha2BaseCoordinator = hass.data[DOMAIN][config_entry.entry_id]
async_add_entities(
Alpha2Climate(coordinator, heat_area_id) for heat_area_id in coordinator.data
Alpha2Climate(coordinator, heat_area_id)
for heat_area_id in coordinator.data["heat_areas"]
)
@ -51,26 +52,34 @@ class Alpha2Climate(CoordinatorEntity[Alpha2BaseCoordinator], ClimateEntity):
super().__init__(coordinator)
self.heat_area_id = heat_area_id
self._attr_unique_id = heat_area_id
@property
def name(self) -> str:
"""Return the name of the climate device."""
return self.coordinator.data[self.heat_area_id]["HEATAREA_NAME"]
self._attr_name = self.coordinator.data["heat_areas"][heat_area_id][
"HEATAREA_NAME"
]
@property
def min_temp(self) -> float:
"""Return the minimum temperature."""
return float(self.coordinator.data[self.heat_area_id].get("T_TARGET_MIN", 0.0))
return float(
self.coordinator.data["heat_areas"][self.heat_area_id].get(
"T_TARGET_MIN", 0.0
)
)
@property
def max_temp(self) -> float:
"""Return the maximum temperature."""
return float(self.coordinator.data[self.heat_area_id].get("T_TARGET_MAX", 30.0))
return float(
self.coordinator.data["heat_areas"][self.heat_area_id].get(
"T_TARGET_MAX", 30.0
)
)
@property
def current_temperature(self) -> float:
"""Return the current temperature."""
return float(self.coordinator.data[self.heat_area_id].get("T_ACTUAL", 0.0))
return float(
self.coordinator.data["heat_areas"][self.heat_area_id].get("T_ACTUAL", 0.0)
)
@property
def hvac_mode(self) -> HVACMode:
@ -86,7 +95,9 @@ class Alpha2Climate(CoordinatorEntity[Alpha2BaseCoordinator], ClimateEntity):
@property
def hvac_action(self) -> HVACAction:
"""Return the current running hvac operation."""
if not self.coordinator.data[self.heat_area_id]["_HEATCTRL_STATE"]:
if not self.coordinator.data["heat_areas"][self.heat_area_id][
"_HEATCTRL_STATE"
]:
return HVACAction.IDLE
if self.coordinator.get_cooling():
return HVACAction.COOLING
@ -95,7 +106,9 @@ class Alpha2Climate(CoordinatorEntity[Alpha2BaseCoordinator], ClimateEntity):
@property
def target_temperature(self) -> float:
"""Return the temperature we try to reach."""
return float(self.coordinator.data[self.heat_area_id].get("T_TARGET", 0.0))
return float(
self.coordinator.data["heat_areas"][self.heat_area_id].get("T_TARGET", 0.0)
)
async def async_set_temperature(self, **kwargs) -> None:
"""Set new target temperatures."""
@ -109,9 +122,9 @@ class Alpha2Climate(CoordinatorEntity[Alpha2BaseCoordinator], ClimateEntity):
@property
def preset_mode(self) -> str:
"""Return the current preset mode."""
if self.coordinator.data[self.heat_area_id]["HEATAREA_MODE"] == 1:
if self.coordinator.data["heat_areas"][self.heat_area_id]["HEATAREA_MODE"] == 1:
return PRESET_DAY
if self.coordinator.data[self.heat_area_id]["HEATAREA_MODE"] == 2:
if self.coordinator.data["heat_areas"][self.heat_area_id]["HEATAREA_MODE"] == 2:
return PRESET_NIGHT
return PRESET_AUTO

View File

@ -3,7 +3,7 @@
"name": "Möhlenhoff Alpha 2",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/moehlenhoff_alpha2",
"requirements": ["moehlenhoff-alpha2==1.1.2"],
"requirements": ["moehlenhoff-alpha2==1.2.1"],
"iot_class": "local_push",
"codeowners": ["@j-a-n"]
}

View File

@ -0,0 +1,56 @@
"""Support for Alpha2 heat control valve opening sensors."""
from homeassistant.components.sensor import SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PERCENTAGE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import Alpha2BaseCoordinator
from .const import DOMAIN
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Add Alpha2 sensor entities from a config_entry."""
coordinator: Alpha2BaseCoordinator = hass.data[DOMAIN][config_entry.entry_id]
# HEATCTRL attribute ACTOR_PERCENT is not available in older firmware versions
async_add_entities(
Alpha2HeatControlValveOpeningSensor(coordinator, heat_control_id)
for heat_control_id, heat_control in coordinator.data["heat_controls"].items()
if heat_control["INUSE"]
and heat_control["_HEATAREA_ID"]
and heat_control.get("ACTOR_PERCENT") is not None
)
class Alpha2HeatControlValveOpeningSensor(
CoordinatorEntity[Alpha2BaseCoordinator], SensorEntity
):
"""Alpha2 heat control valve opening sensor."""
_attr_native_unit_of_measurement = PERCENTAGE
def __init__(
self, coordinator: Alpha2BaseCoordinator, heat_control_id: str
) -> None:
"""Initialize Alpha2HeatControlValveOpeningSensor."""
super().__init__(coordinator)
self.heat_control_id = heat_control_id
self._attr_unique_id = f"{heat_control_id}:valve_opening"
heat_control = self.coordinator.data["heat_controls"][heat_control_id]
heat_area = self.coordinator.data["heat_areas"][heat_control["_HEATAREA_ID"]]
self._attr_name = f"{heat_area['HEATAREA_NAME']} heat control {heat_control['NR']} valve opening"
@property
def native_value(self) -> int:
"""Return the current valve opening percentage."""
return self.coordinator.data["heat_controls"][self.heat_control_id][
"ACTOR_PERCENT"
]

View File

@ -1035,7 +1035,7 @@ minio==5.0.10
mitemp_bt==0.0.5
# homeassistant.components.moehlenhoff_alpha2
moehlenhoff-alpha2==1.1.2
moehlenhoff-alpha2==1.2.1
# homeassistant.components.motion_blinds
motionblinds==0.6.7

View File

@ -712,7 +712,7 @@ millheater==0.9.0
minio==5.0.10
# homeassistant.components.moehlenhoff_alpha2
moehlenhoff-alpha2==1.1.2
moehlenhoff-alpha2==1.2.1
# homeassistant.components.motion_blinds
motionblinds==0.6.7