Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd6f079a92 | ||
|
|
cb57dc1e92 |
@@ -24,6 +24,10 @@ from .const import (
|
||||
DATA_INTEGRATION_REQUEST,
|
||||
DATA_PUMP_ACTIVE,
|
||||
DATA_RENEWAL_REQUEST,
|
||||
DATA_VENTILATION_MODE_DEHUMIDIFICATION,
|
||||
DATA_VENTILATION_MODE_INTEGRATION,
|
||||
DATA_VENTILATION_MODE_RENEWAL,
|
||||
DATA_VENTILATION_MODE_VENTILATION,
|
||||
DATA_VENTILATION_REQUEST,
|
||||
DATA_ZONE_ACTIVITY,
|
||||
DOMAIN,
|
||||
@@ -42,6 +46,14 @@ ZONE_REQUEST_TYPES: dict[str, tuple[str, str]] = {
|
||||
"dehumidification_pump": (DATA_DEHUMIDIFICATION_PUMP, "Dehumidification pump"),
|
||||
}
|
||||
|
||||
# Ventilation mode types with their data keys and display names
|
||||
VENTILATION_MODE_TYPES: dict[str, tuple[str, str]] = {
|
||||
"dehumidification": (DATA_VENTILATION_MODE_DEHUMIDIFICATION, "Dehumidification"),
|
||||
"ventilation": (DATA_VENTILATION_MODE_VENTILATION, "Ventilation"),
|
||||
"renewal": (DATA_VENTILATION_MODE_RENEWAL, "Renewal"),
|
||||
"integration": (DATA_VENTILATION_MODE_INTEGRATION, "Integration"),
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
@@ -58,6 +70,10 @@ async def async_setup_entry(
|
||||
for pump_id in range(1, 9):
|
||||
entities.append(RDZPumpActiveBinarySensor(coordinator, pump_id))
|
||||
|
||||
# Add ventilation mode binary sensors
|
||||
for mode_type in VENTILATION_MODE_TYPES:
|
||||
entities.append(RDZVentilationModeBinarySensor(coordinator, mode_type))
|
||||
|
||||
# Add zone pump binary sensors for each configured zone
|
||||
for zone_id_str, zone_data in zones_config.items():
|
||||
zone_id = int(zone_id_str) if isinstance(zone_id_str, str) else zone_id_str
|
||||
@@ -119,6 +135,55 @@ class RDZPumpActiveBinarySensor(CoordinatorEntity[RDZDataUpdateCoordinator], Bin
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
||||
class RDZVentilationModeBinarySensor(CoordinatorEntity[RDZDataUpdateCoordinator], BinarySensorEntity):
|
||||
"""Representation of an RDZ HMI ventilation mode binary sensor.
|
||||
|
||||
Indicates whether a ventilation unit work mode is active.
|
||||
"""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
_attr_device_class = BinarySensorDeviceClass.RUNNING
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: RDZDataUpdateCoordinator,
|
||||
mode_type: str,
|
||||
) -> None:
|
||||
"""Initialize the ventilation mode binary sensor entity.
|
||||
|
||||
Args:
|
||||
coordinator: The data coordinator.
|
||||
mode_type: The type of ventilation mode (key in VENTILATION_MODE_TYPES).
|
||||
"""
|
||||
super().__init__(coordinator)
|
||||
self._mode_type = mode_type
|
||||
self._data_key, self._display_name = VENTILATION_MODE_TYPES[mode_type]
|
||||
|
||||
self._attr_unique_id = f"{DOMAIN}_{coordinator.client.host}_ventilation_mode_{mode_type}"
|
||||
self._attr_name = self._display_name
|
||||
|
||||
# Place on the System device
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, f"{coordinator.client.host}_system")},
|
||||
name="RDZ HMI System",
|
||||
manufacturer="RDZ",
|
||||
model="HMI Control System",
|
||||
sw_version="1.0",
|
||||
)
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return True if the ventilation mode is active."""
|
||||
if self.coordinator.data is None:
|
||||
return None
|
||||
return self.coordinator.data.get(self._data_key)
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Handle updated data from the coordinator."""
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
||||
class RDZZonePumpBinarySensor(CoordinatorEntity[RDZDataUpdateCoordinator], BinarySensorEntity):
|
||||
"""Representation of an RDZ HMI zone pump binary sensor.
|
||||
|
||||
|
||||
@@ -140,6 +140,12 @@ REGISTER_CALCULATED_WATER_TEMP_COUNT = 8
|
||||
# Pump active bitmask register
|
||||
REGISTER_PUMP_ACTIVE = 7615
|
||||
|
||||
# Ventilation mode registers (LSB = on/off)
|
||||
REGISTER_VENTILATION_MODE_DEHUMIDIFICATION = 8201
|
||||
REGISTER_VENTILATION_MODE_VENTILATION = 8202
|
||||
REGISTER_VENTILATION_MODE_RENEWAL = 8203
|
||||
REGISTER_VENTILATION_MODE_INTEGRATION = 8204
|
||||
|
||||
# Data keys for new features
|
||||
DATA_OUTSIDE_TEMP = "outside_temperature"
|
||||
DATA_TIME_SETTINGS = "time_settings"
|
||||
@@ -148,3 +154,7 @@ DATA_DELIVERY_WATER_TEMPS = "delivery_water_temps"
|
||||
DATA_CALCULATED_WATER_TEMPS = "calculated_water_temps"
|
||||
DATA_PUMP_ACTIVE = "pump_active"
|
||||
DATA_CALCULATED_SETPOINTS = "calculated_setpoints"
|
||||
DATA_VENTILATION_MODE_DEHUMIDIFICATION = "ventilation_mode_dehumidification"
|
||||
DATA_VENTILATION_MODE_VENTILATION = "ventilation_mode_ventilation"
|
||||
DATA_VENTILATION_MODE_RENEWAL = "ventilation_mode_renewal"
|
||||
DATA_VENTILATION_MODE_INTEGRATION = "ventilation_mode_integration"
|
||||
|
||||
@@ -34,6 +34,10 @@ from .const import (
|
||||
DATA_SYSTEM_ACTIVATION,
|
||||
DATA_TEMPERATURES,
|
||||
DATA_TIME_SETTINGS,
|
||||
DATA_VENTILATION_MODE_DEHUMIDIFICATION,
|
||||
DATA_VENTILATION_MODE_INTEGRATION,
|
||||
DATA_VENTILATION_MODE_RENEWAL,
|
||||
DATA_VENTILATION_MODE_VENTILATION,
|
||||
DATA_VENTILATION_REQUEST,
|
||||
DATA_WINTER_SETPOINTS,
|
||||
DATA_ZONE_ACTIVITY,
|
||||
@@ -107,6 +111,9 @@ class RDZDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
||||
integration_request = await self.client.read_integration_request()
|
||||
dehumidification_pump = await self.client.read_dehumidification_pump()
|
||||
|
||||
# Read ventilation mode registers
|
||||
ventilation_modes = await self.client.read_ventilation_modes()
|
||||
|
||||
if temperatures is None or winter_setpoints is None or summer_setpoints is None:
|
||||
raise UpdateFailed("Failed to read data from Modbus device")
|
||||
|
||||
@@ -140,6 +147,11 @@ class RDZDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
||||
DATA_RENEWAL_REQUEST: renewal_request,
|
||||
DATA_INTEGRATION_REQUEST: integration_request,
|
||||
DATA_DEHUMIDIFICATION_PUMP: dehumidification_pump,
|
||||
# Ventilation mode states
|
||||
DATA_VENTILATION_MODE_DEHUMIDIFICATION: ventilation_modes.get("dehumidification") if ventilation_modes else None,
|
||||
DATA_VENTILATION_MODE_VENTILATION: ventilation_modes.get("ventilation") if ventilation_modes else None,
|
||||
DATA_VENTILATION_MODE_RENEWAL: ventilation_modes.get("renewal") if ventilation_modes else None,
|
||||
DATA_VENTILATION_MODE_INTEGRATION: ventilation_modes.get("integration") if ventilation_modes else None,
|
||||
}
|
||||
|
||||
except Exception as ex:
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"requirements": ["pymodbus>=3.6.0"],
|
||||
"version": "1.1.4"
|
||||
"version": "1.1.5"
|
||||
}
|
||||
|
||||
@@ -558,3 +558,19 @@ class RDZModbusClient:
|
||||
return await self._read_zone_bitmask(
|
||||
REGISTER_DEHUMIDIFICATION_PUMP_START, REGISTER_DEHUMIDIFICATION_PUMP_COUNT
|
||||
)
|
||||
|
||||
async def read_ventilation_modes(self) -> dict[str, bool] | None:
|
||||
"""Read ventilation mode registers 8201-8204.
|
||||
|
||||
Returns dict with keys: dehumidification, ventilation, renewal, integration.
|
||||
LSB (bit 0) of each register indicates on/off state.
|
||||
"""
|
||||
registers = await self.read_registers(8201, 4)
|
||||
if registers is None:
|
||||
return None
|
||||
return {
|
||||
"dehumidification": bool(registers[0] & 1),
|
||||
"ventilation": bool(registers[1] & 1),
|
||||
"renewal": bool(registers[2] & 1),
|
||||
"integration": bool(registers[3] & 1),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user