Report the Weheat cooling start conditions (#181287)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Erwin Douna <e.douna@gmail.com>
This commit is contained in:
Barry vd. Heuvel
2026-09-07 17:31:34 +02:00
committed by GitHub
co-authored by Claude Opus 5 Erwin Douna
parent e02d091174
commit 1c063fcac6
5 changed files with 648 additions and 1 deletions
@@ -2,6 +2,7 @@
from collections.abc import Callable
from dataclasses import dataclass
from functools import partial
from typing import override
from weheat.abstractions.heat_pump import HeatPump
@@ -11,6 +12,7 @@ from homeassistant.components.binary_sensor import (
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
@@ -62,6 +64,25 @@ BINARY_SENSORS = [
]
COOLING_START_CONDITION_SENSORS = [
WeHeatBinarySensorEntityDescription(
translation_key=f"cooling_start_condition_{condition}",
key=f"cooling_start_condition_{condition}",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=partial(
lambda condition, status: (
status.cooling_start_conditions[condition]
if status.cooling_start_conditions is not None
else None
),
condition,
),
)
for condition in HeatPump.COOLING_START_CONDITION_BITS
]
async def async_setup_entry(
hass: HomeAssistant,
entry: WeheatConfigEntry,
@@ -78,6 +99,16 @@ async def async_setup_entry(
for entity_description in BINARY_SENSORS
if entity_description.value_fn(weheatdata.data_coordinator.data) is not None
]
entities.extend(
WeheatHeatPumpBinarySensor(
weheatdata.heat_pump_info,
weheatdata.data_coordinator,
entity_description,
)
for weheatdata in entry.runtime_data
if weheatdata.data_coordinator.data.cooling_start_conditions is not None
for entity_description in COOLING_START_CONDITION_SENSORS
)
async_add_entities(entities)
@@ -1,6 +1,39 @@
{
"entity": {
"binary_sensor": {
"cooling_start_condition_contact_not_blocked": {
"default": "mdi:snowflake-check"
},
"cooling_start_condition_control_method": {
"default": "mdi:snowflake-check"
},
"cooling_start_condition_demand": {
"default": "mdi:snowflake-check"
},
"cooling_start_condition_dtc": {
"default": "mdi:snowflake-check"
},
"cooling_start_condition_exponential_backoff": {
"default": "mdi:snowflake-check"
},
"cooling_start_condition_heat_cool_delay": {
"default": "mdi:snowflake-check"
},
"cooling_start_condition_indoor_unit_connected": {
"default": "mdi:snowflake-check"
},
"cooling_start_condition_inside_temperature": {
"default": "mdi:snowflake-check"
},
"cooling_start_condition_outside_air_temperature": {
"default": "mdi:snowflake-check"
},
"cooling_start_condition_water_temperature": {
"default": "mdi:snowflake-check"
},
"cooling_start_condition_water_to_air": {
"default": "mdi:snowflake-check"
},
"indoor_unit_auxiliary_pump_state": {
"default": "mdi:pump"
},
@@ -76,7 +76,7 @@ rules:
While unlikely to happen. Check if it is easily integrated.
entity-category: done
entity-device-class: done
entity-disabled-by-default: todo
entity-disabled-by-default: done
entity-translations: done
exception-translations: todo
icon-translations: done
@@ -30,6 +30,39 @@
},
"entity": {
"binary_sensor": {
"cooling_start_condition_contact_not_blocked": {
"name": "Cooling contact not blocking"
},
"cooling_start_condition_control_method": {
"name": "Cooling allowed by control method"
},
"cooling_start_condition_demand": {
"name": "Demand for cooling from cooling curve"
},
"cooling_start_condition_dtc": {
"name": "No cooling-related faults"
},
"cooling_start_condition_exponential_backoff": {
"name": "No cooling back-off waiting time"
},
"cooling_start_condition_heat_cool_delay": {
"name": "No heating in the last 24 hours"
},
"cooling_start_condition_indoor_unit_connected": {
"name": "Cooling indoor unit connected"
},
"cooling_start_condition_inside_temperature": {
"name": "Cooling room warmer than desired"
},
"cooling_start_condition_outside_air_temperature": {
"name": "Cooling outside temperature high enough"
},
"cooling_start_condition_water_temperature": {
"name": "Water warmer than cooling curve"
},
"cooling_start_condition_water_to_air": {
"name": "Cooling air warmer than system water"
},
"indoor_unit_auxiliary_pump_state": {
"name": "Indoor unit auxiliary water pump"
},
@@ -1,4 +1,354 @@
# serializer version: 1
# name: test_binary_entities[binary_sensor.test_model_cooling_air_warmer_than_system_water-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_model_cooling_air_warmer_than_system_water',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Cooling air warmer than system water',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Cooling air warmer than system water',
'platform': 'weheat',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cooling_start_condition_water_to_air',
'unique_id': '0000-1111-2222-3333_cooling_start_condition_water_to_air',
'unit_of_measurement': None,
})
# ---
# name: test_binary_entities[binary_sensor.test_model_cooling_air_warmer_than_system_water-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Model Cooling air warmer than system water',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_model_cooling_air_warmer_than_system_water',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_entities[binary_sensor.test_model_cooling_allowed_by_control_method-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_model_cooling_allowed_by_control_method',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Cooling allowed by control method',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Cooling allowed by control method',
'platform': 'weheat',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cooling_start_condition_control_method',
'unique_id': '0000-1111-2222-3333_cooling_start_condition_control_method',
'unit_of_measurement': None,
})
# ---
# name: test_binary_entities[binary_sensor.test_model_cooling_allowed_by_control_method-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Model Cooling allowed by control method',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_model_cooling_allowed_by_control_method',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_entities[binary_sensor.test_model_cooling_contact_not_blocking-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_model_cooling_contact_not_blocking',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Cooling contact not blocking',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Cooling contact not blocking',
'platform': 'weheat',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cooling_start_condition_contact_not_blocked',
'unique_id': '0000-1111-2222-3333_cooling_start_condition_contact_not_blocked',
'unit_of_measurement': None,
})
# ---
# name: test_binary_entities[binary_sensor.test_model_cooling_contact_not_blocking-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Model Cooling contact not blocking',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_model_cooling_contact_not_blocking',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_entities[binary_sensor.test_model_cooling_indoor_unit_connected-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_model_cooling_indoor_unit_connected',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Cooling indoor unit connected',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Cooling indoor unit connected',
'platform': 'weheat',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cooling_start_condition_indoor_unit_connected',
'unique_id': '0000-1111-2222-3333_cooling_start_condition_indoor_unit_connected',
'unit_of_measurement': None,
})
# ---
# name: test_binary_entities[binary_sensor.test_model_cooling_indoor_unit_connected-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Model Cooling indoor unit connected',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_model_cooling_indoor_unit_connected',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_entities[binary_sensor.test_model_cooling_outside_temperature_high_enough-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_model_cooling_outside_temperature_high_enough',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Cooling outside temperature high enough',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Cooling outside temperature high enough',
'platform': 'weheat',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cooling_start_condition_outside_air_temperature',
'unique_id': '0000-1111-2222-3333_cooling_start_condition_outside_air_temperature',
'unit_of_measurement': None,
})
# ---
# name: test_binary_entities[binary_sensor.test_model_cooling_outside_temperature_high_enough-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Model Cooling outside temperature high enough',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_model_cooling_outside_temperature_high_enough',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_entities[binary_sensor.test_model_cooling_room_warmer_than_desired-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_model_cooling_room_warmer_than_desired',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Cooling room warmer than desired',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Cooling room warmer than desired',
'platform': 'weheat',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cooling_start_condition_inside_temperature',
'unique_id': '0000-1111-2222-3333_cooling_start_condition_inside_temperature',
'unit_of_measurement': None,
})
# ---
# name: test_binary_entities[binary_sensor.test_model_cooling_room_warmer_than_desired-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Model Cooling room warmer than desired',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_model_cooling_room_warmer_than_desired',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_entities[binary_sensor.test_model_demand_for_cooling_from_cooling_curve-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_model_demand_for_cooling_from_cooling_curve',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Demand for cooling from cooling curve',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Demand for cooling from cooling curve',
'platform': 'weheat',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cooling_start_condition_demand',
'unique_id': '0000-1111-2222-3333_cooling_start_condition_demand',
'unit_of_measurement': None,
})
# ---
# name: test_binary_entities[binary_sensor.test_model_demand_for_cooling_from_cooling_curve-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Model Demand for cooling from cooling curve',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_model_demand_for_cooling_from_cooling_curve',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_binary_entities[binary_sensor.test_model_indoor_unit_auxiliary_water_pump-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
@@ -202,3 +552,203 @@
'state': 'off',
})
# ---
# name: test_binary_entities[binary_sensor.test_model_no_cooling_back_off_waiting_time-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_model_no_cooling_back_off_waiting_time',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'No cooling back-off waiting time',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'No cooling back-off waiting time',
'platform': 'weheat',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cooling_start_condition_exponential_backoff',
'unique_id': '0000-1111-2222-3333_cooling_start_condition_exponential_backoff',
'unit_of_measurement': None,
})
# ---
# name: test_binary_entities[binary_sensor.test_model_no_cooling_back_off_waiting_time-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Model No cooling back-off waiting time',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_model_no_cooling_back_off_waiting_time',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_entities[binary_sensor.test_model_no_cooling_related_faults-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_model_no_cooling_related_faults',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'No cooling-related faults',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'No cooling-related faults',
'platform': 'weheat',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cooling_start_condition_dtc',
'unique_id': '0000-1111-2222-3333_cooling_start_condition_dtc',
'unit_of_measurement': None,
})
# ---
# name: test_binary_entities[binary_sensor.test_model_no_cooling_related_faults-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Model No cooling-related faults',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_model_no_cooling_related_faults',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_entities[binary_sensor.test_model_no_heating_in_the_last_24_hours-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_model_no_heating_in_the_last_24_hours',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'No heating in the last 24 hours',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'No heating in the last 24 hours',
'platform': 'weheat',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cooling_start_condition_heat_cool_delay',
'unique_id': '0000-1111-2222-3333_cooling_start_condition_heat_cool_delay',
'unit_of_measurement': None,
})
# ---
# name: test_binary_entities[binary_sensor.test_model_no_heating_in_the_last_24_hours-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Model No heating in the last 24 hours',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_model_no_heating_in_the_last_24_hours',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_entities[binary_sensor.test_model_water_warmer_than_cooling_curve-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.test_model_water_warmer_than_cooling_curve',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Water warmer than cooling curve',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Water warmer than cooling curve',
'platform': 'weheat',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cooling_start_condition_water_temperature',
'unique_id': '0000-1111-2222-3333_cooling_start_condition_water_temperature',
'unit_of_measurement': None,
})
# ---
# name: test_binary_entities[binary_sensor.test_model_water_warmer_than_cooling_curve-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Test Model Water warmer than cooling curve',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_model_water_warmer_than_cooling_curve',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---