diff --git a/homeassistant/components/weheat/const.py b/homeassistant/components/weheat/const.py index fa1b17f8c07281..e33fd98357272d 100644 --- a/homeassistant/components/weheat/const.py +++ b/homeassistant/components/weheat/const.py @@ -23,3 +23,4 @@ DISPLAY_PRECISION_WATTS = 0 DISPLAY_PRECISION_COP = 1 +DISPLAY_PRECISION_WATER_TEMP = 1 diff --git a/homeassistant/components/weheat/coordinator.py b/homeassistant/components/weheat/coordinator.py index 92c1299037119d..69d1319ed52199 100644 --- a/homeassistant/components/weheat/coordinator.py +++ b/homeassistant/components/weheat/coordinator.py @@ -46,27 +46,27 @@ def __init__( name=DOMAIN, update_interval=timedelta(seconds=UPDATE_INTERVAL), ) - self._heat_pump_info = heat_pump - self._heat_pump_data = HeatPump(API_URL, self._heat_pump_info.uuid) + self.heat_pump_info = heat_pump + self._heat_pump_data = HeatPump(API_URL, heat_pump.uuid) self.session = session @property def heatpump_id(self) -> str: """Return the heat pump id.""" - return self._heat_pump_info.uuid + return self.heat_pump_info.uuid @property def readable_name(self) -> str | None: """Return the readable name of the heat pump.""" - if self._heat_pump_info.name: - return self._heat_pump_info.name - return self._heat_pump_info.model + if self.heat_pump_info.name: + return self.heat_pump_info.name + return self.heat_pump_info.model @property def model(self) -> str: """Return the model of the heat pump.""" - return self._heat_pump_info.model + return self.heat_pump_info.model def fetch_data(self) -> HeatPump: """Get the data from the API.""" diff --git a/homeassistant/components/weheat/icons.json b/homeassistant/components/weheat/icons.json index b1eaf481bfa6c9..a7579c12ecd842 100644 --- a/homeassistant/components/weheat/icons.json +++ b/homeassistant/components/weheat/icons.json @@ -9,6 +9,30 @@ }, "cop": { "default": "mdi:speedometer" + }, + "water_inlet_temperature": { + "default": "mdi:thermometer" + }, + "water_outlet_temperature": { + "default": "mdi:thermometer" + }, + "ch_inlet_temperature": { + "default": "mdi:radiator" + }, + "outside_temperature": { + "default": "mdi:home-thermometer-outline" + }, + "dhw_top_temperature": { + "default": "mdi:thermometer" + }, + "dhw_bottom_temperature": { + "default": "mdi:thermometer" + }, + "heat_pump_state": { + "default": "mdi:state-machine" + }, + "electricity_used": { + "default": "mdi:flash" } } } diff --git a/homeassistant/components/weheat/sensor.py b/homeassistant/components/weheat/sensor.py index a5bbc66001c09c..fc7d3628a33647 100644 --- a/homeassistant/components/weheat/sensor.py +++ b/homeassistant/components/weheat/sensor.py @@ -11,13 +11,17 @@ SensorEntityDescription, SensorStateClass, ) -from homeassistant.const import UnitOfPower +from homeassistant.const import UnitOfEnergy, UnitOfPower, UnitOfTemperature from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType from . import WeheatConfigEntry -from .const import DISPLAY_PRECISION_COP, DISPLAY_PRECISION_WATTS +from .const import ( + DISPLAY_PRECISION_COP, + DISPLAY_PRECISION_WATER_TEMP, + DISPLAY_PRECISION_WATTS, +) from .coordinator import WeheatDataUpdateCoordinator from .entity import WeheatEntity @@ -55,6 +59,84 @@ class WeHeatSensorEntityDescription(SensorEntityDescription): suggested_display_precision=DISPLAY_PRECISION_COP, value_fn=lambda status: status.cop, ), + WeHeatSensorEntityDescription( + translation_key="water_inlet_temperature", + key="water_inlet_temperature", + native_unit_of_measurement=UnitOfTemperature.CELSIUS, + device_class=SensorDeviceClass.TEMPERATURE, + state_class=SensorStateClass.MEASUREMENT, + suggested_display_precision=DISPLAY_PRECISION_WATER_TEMP, + value_fn=lambda status: status.water_inlet_temperature, + ), + WeHeatSensorEntityDescription( + translation_key="water_outlet_temperature", + key="water_outlet_temperature", + native_unit_of_measurement=UnitOfTemperature.CELSIUS, + device_class=SensorDeviceClass.TEMPERATURE, + state_class=SensorStateClass.MEASUREMENT, + suggested_display_precision=DISPLAY_PRECISION_WATER_TEMP, + value_fn=lambda status: status.water_outlet_temperature, + ), + WeHeatSensorEntityDescription( + translation_key="ch_inlet_temperature", + key="ch_inlet_temperature", + native_unit_of_measurement=UnitOfTemperature.CELSIUS, + device_class=SensorDeviceClass.TEMPERATURE, + state_class=SensorStateClass.MEASUREMENT, + suggested_display_precision=DISPLAY_PRECISION_WATER_TEMP, + value_fn=lambda status: status.water_house_in_temperature, + ), + WeHeatSensorEntityDescription( + translation_key="outside_temperature", + key="outside_temperature", + native_unit_of_measurement=UnitOfTemperature.CELSIUS, + device_class=SensorDeviceClass.TEMPERATURE, + state_class=SensorStateClass.MEASUREMENT, + suggested_display_precision=DISPLAY_PRECISION_WATER_TEMP, + value_fn=lambda status: status.air_inlet_temperature, + ), + WeHeatSensorEntityDescription( + translation_key="heat_pump_state", + key="heat_pump_state", + name=None, + device_class=SensorDeviceClass.ENUM, + options=[s.name.lower() for s in HeatPump.State], + value_fn=( + lambda status: status.heat_pump_state.name.lower() + if status.heat_pump_state + else None + ), + ), + WeHeatSensorEntityDescription( + translation_key="electricity_used", + key="electricity_used", + native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda status: status.energy_total, + ), +] + + +DHW_SENSORS = [ + WeHeatSensorEntityDescription( + translation_key="dhw_top_temperature", + key="dhw_top_temperature", + native_unit_of_measurement=UnitOfTemperature.CELSIUS, + device_class=SensorDeviceClass.TEMPERATURE, + state_class=SensorStateClass.MEASUREMENT, + suggested_display_precision=DISPLAY_PRECISION_WATER_TEMP, + value_fn=lambda status: status.dhw_top_temperature, + ), + WeHeatSensorEntityDescription( + translation_key="dhw_bottom_temperature", + key="dhw_bottom_temperature", + native_unit_of_measurement=UnitOfTemperature.CELSIUS, + device_class=SensorDeviceClass.TEMPERATURE, + state_class=SensorStateClass.MEASUREMENT, + suggested_display_precision=DISPLAY_PRECISION_WATER_TEMP, + value_fn=lambda status: status.dhw_bottom_temperature, + ), ] @@ -64,12 +146,20 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up the sensors for weheat heat pump.""" - async_add_entities( + entities = [ WeheatHeatPumpSensor(coordinator, entity_description) for entity_description in SENSORS for coordinator in entry.runtime_data + ] + entities.extend( + WeheatHeatPumpSensor(coordinator, entity_description) + for entity_description in DHW_SENSORS + for coordinator in entry.runtime_data + if coordinator.heat_pump_info.has_dhw ) + async_add_entities(entities) + class WeheatHeatPumpSensor(WeheatEntity, SensorEntity): """Defines a Weheat heat pump sensor.""" diff --git a/homeassistant/components/weheat/strings.json b/homeassistant/components/weheat/strings.json index 63871b065b6943..b77af4ed306f4e 100644 --- a/homeassistant/components/weheat/strings.json +++ b/homeassistant/components/weheat/strings.json @@ -40,6 +40,40 @@ }, "cop": { "name": "COP" + }, + "water_inlet_temperature": { + "name": "Water inlet temperature" + }, + "water_outlet_temperature": { + "name": "Water outlet temperature" + }, + "ch_inlet_temperature": { + "name": "Central heating inlet temperature" + }, + "outside_temperature": { + "name": "Outside temperature" + }, + "dhw_top_temperature": { + "name": "DHW top temperature" + }, + "dhw_bottom_temperature": { + "name": "DHW bottom temperature" + }, + "heat_pump_state": { + "state": { + "standby": "[%key:common::state::standby%]", + "water_check": "Checking water temperature", + "heating": "Heating", + "cooling": "Cooling", + "dhw": "Heating DHW", + "legionella_prevention": "Legionella prevention", + "defrosting": "Defrosting", + "self_test": "Self test", + "manual_control": "Manual control" + } + }, + "electricity_used": { + "name": "Electricity used" } } } diff --git a/tests/components/weheat/__init__.py b/tests/components/weheat/__init__.py index c077280ccb5698..65c4f84ba77a9c 100644 --- a/tests/components/weheat/__init__.py +++ b/tests/components/weheat/__init__.py @@ -1 +1,13 @@ """Tests for the Weheat integration.""" + +from homeassistant.core import HomeAssistant + +from tests.common import MockConfigEntry + + +async def setup_integration(hass: HomeAssistant, config_entry: MockConfigEntry) -> None: + """Fixture for setting up the component.""" + config_entry.add_to_hass(hass) + + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() diff --git a/tests/components/weheat/conftest.py b/tests/components/weheat/conftest.py index 831d4d460aca4a..1b4bf26c35f899 100644 --- a/tests/components/weheat/conftest.py +++ b/tests/components/weheat/conftest.py @@ -1,8 +1,12 @@ """Fixtures for Weheat tests.""" -from unittest.mock import patch +from collections.abc import Generator +from time import time +from unittest.mock import AsyncMock, MagicMock, patch import pytest +from weheat.abstractions.discovery import HeatPumpDiscovery +from weheat.abstractions.heat_pump import HeatPump from homeassistant.components.application_credentials import ( DOMAIN as APPLICATION_CREDENTIALS, @@ -13,7 +17,9 @@ from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component -from .const import CLIENT_ID, CLIENT_SECRET +from .const import CLIENT_ID, CLIENT_SECRET, TEST_HP_UUID, TEST_MODEL, TEST_SN + +from tests.common import MockConfigEntry @pytest.fixture(autouse=True) @@ -34,3 +40,77 @@ def mock_setup_entry(): "homeassistant.components.weheat.async_setup_entry", return_value=True ) as mock_setup: yield mock_setup + + +@pytest.fixture +def mock_heat_pump_info() -> HeatPumpDiscovery.HeatPumpInfo: + """Create a HeatPumpInfo with default settings.""" + return HeatPumpDiscovery.HeatPumpInfo(TEST_HP_UUID, None, TEST_MODEL, TEST_SN, True) + + +@pytest.fixture +def mock_config_entry() -> MockConfigEntry: + """Mock a config entry.""" + return MockConfigEntry( + domain=DOMAIN, + title="Weheat", + data={ + "id": "12345", + "auth_implementation": DOMAIN, + "token": { + "refresh_token": "mock-refresh-token", + "access_token": "mock-access-token", + "type": "Bearer", + "expires_in": 60, + "expires_at": time() + 60, + }, + }, + unique_id="123456789", + ) + + +@pytest.fixture +def mock_weheat_discover(mock_heat_pump_info) -> Generator[AsyncMock]: + """Mock an Weheat discovery.""" + with ( + patch( + "homeassistant.components.weheat.HeatPumpDiscovery.discover_active", + autospec=True, + ) as mock_discover, + ): + mock_discover.return_value = [mock_heat_pump_info] + + yield mock_discover + + +@pytest.fixture +def mock_weheat_heat_pump_instance() -> MagicMock: + """Mock an Weheat heat pump instance with a set of default values.""" + mock_heat_pump_instance = MagicMock(spec_set=HeatPump) + + mock_heat_pump_instance.water_inlet_temperature = 11 + mock_heat_pump_instance.water_outlet_temperature = 22 + mock_heat_pump_instance.water_house_in_temperature = 33 + mock_heat_pump_instance.air_inlet_temperature = 44 + mock_heat_pump_instance.power_input = 55 + mock_heat_pump_instance.power_output = 66 + mock_heat_pump_instance.dhw_top_temperature = 77 + mock_heat_pump_instance.dhw_bottom_temperature = 88 + mock_heat_pump_instance.cop = 4.5 + mock_heat_pump_instance.heat_pump_state = HeatPump.State.HEATING + mock_heat_pump_instance.energy_total = 12345 + + return mock_heat_pump_instance + + +@pytest.fixture +def mock_weheat_heat_pump(mock_weheat_heat_pump_instance) -> Generator[AsyncMock]: + """Mock the coordinator HeatPump data.""" + with ( + patch( + "homeassistant.components.weheat.coordinator.HeatPump", + ) as mock_heat_pump, + ): + mock_heat_pump.return_value = mock_weheat_heat_pump_instance + + yield mock_weheat_heat_pump_instance diff --git a/tests/components/weheat/const.py b/tests/components/weheat/const.py index 01733de1c916d2..bae74dc70a10af 100644 --- a/tests/components/weheat/const.py +++ b/tests/components/weheat/const.py @@ -9,3 +9,8 @@ CONF_AUTH_IMPLEMENTATION = "auth_implementation" MOCK_REFRESH_TOKEN = "mock_refresh_token" MOCK_ACCESS_TOKEN = "mock_access_token" + +TEST_HP_UUID = "0000-1111-2222-3333" +TEST_NAME = "Test Heat Pump" +TEST_MODEL = "Test Model" +TEST_SN = "SN-Test-This" diff --git a/tests/components/weheat/snapshots/test_sensor.ambr b/tests/components/weheat/snapshots/test_sensor.ambr new file mode 100644 index 00000000000000..fc2b6a845a88ad --- /dev/null +++ b/tests/components/weheat/snapshots/test_sensor.ambr @@ -0,0 +1,660 @@ +# serializer version: 1 +# name: test_all_entities[sensor.test_model-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'standby', + 'water_check', + 'heating', + 'cooling', + 'dhw', + 'legionella_prevention', + 'defrosting', + 'self_test', + 'manual_control', + ]), + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': None, + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'heat_pump_state', + 'unique_id': '0000-1111-2222-3333_heat_pump_state', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.test_model-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Test Model', + 'options': list([ + 'standby', + 'water_check', + 'heating', + 'cooling', + 'dhw', + 'legionella_prevention', + 'defrosting', + 'self_test', + 'manual_control', + ]), + }), + 'context': , + 'entity_id': 'sensor.test_model', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'heating', + }) +# --- +# name: test_all_entities[sensor.test_model_central_heating_inlet_temperature-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model_central_heating_inlet_temperature', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 1, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Central heating inlet temperature', + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'ch_inlet_temperature', + 'unique_id': '0000-1111-2222-3333_ch_inlet_temperature', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[sensor.test_model_central_heating_inlet_temperature-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'temperature', + 'friendly_name': 'Test Model Central heating inlet temperature', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.test_model_central_heating_inlet_temperature', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '33', + }) +# --- +# name: test_all_entities[sensor.test_model_cop-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model_cop', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 1, + }), + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'COP', + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'cop', + 'unique_id': '0000-1111-2222-3333_cop', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[sensor.test_model_cop-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test Model COP', + 'state_class': , + }), + 'context': , + 'entity_id': 'sensor.test_model_cop', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '4.5', + }) +# --- +# name: test_all_entities[sensor.test_model_dhw_bottom_temperature-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model_dhw_bottom_temperature', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 1, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'DHW bottom temperature', + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'dhw_bottom_temperature', + 'unique_id': '0000-1111-2222-3333_dhw_bottom_temperature', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[sensor.test_model_dhw_bottom_temperature-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'temperature', + 'friendly_name': 'Test Model DHW bottom temperature', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.test_model_dhw_bottom_temperature', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '88', + }) +# --- +# name: test_all_entities[sensor.test_model_dhw_top_temperature-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model_dhw_top_temperature', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 1, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'DHW top temperature', + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'dhw_top_temperature', + 'unique_id': '0000-1111-2222-3333_dhw_top_temperature', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[sensor.test_model_dhw_top_temperature-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'temperature', + 'friendly_name': 'Test Model DHW top temperature', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.test_model_dhw_top_temperature', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '77', + }) +# --- +# name: test_all_entities[sensor.test_model_electricity_used-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model_electricity_used', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Electricity used', + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'electricity_used', + 'unique_id': '0000-1111-2222-3333_electricity_used', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[sensor.test_model_electricity_used-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'energy', + 'friendly_name': 'Test Model Electricity used', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.test_model_electricity_used', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '12345', + }) +# --- +# name: test_all_entities[sensor.test_model_input_power-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model_input_power', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 0, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Input power', + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'power_input', + 'unique_id': '0000-1111-2222-3333_power_input', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[sensor.test_model_input_power-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'power', + 'friendly_name': 'Test Model Input power', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.test_model_input_power', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '55', + }) +# --- +# name: test_all_entities[sensor.test_model_output_power-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model_output_power', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 0, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Output power', + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'power_output', + 'unique_id': '0000-1111-2222-3333_power_output', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[sensor.test_model_output_power-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'power', + 'friendly_name': 'Test Model Output power', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.test_model_output_power', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '66', + }) +# --- +# name: test_all_entities[sensor.test_model_outside_temperature-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model_outside_temperature', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 1, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Outside temperature', + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'outside_temperature', + 'unique_id': '0000-1111-2222-3333_outside_temperature', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[sensor.test_model_outside_temperature-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'temperature', + 'friendly_name': 'Test Model Outside temperature', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.test_model_outside_temperature', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '44', + }) +# --- +# name: test_all_entities[sensor.test_model_power_output-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model_power_output', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 0, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'power output', + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'power_output', + 'unique_id': '0000-1111-2222-3333_power_output', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[sensor.test_model_power_output-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'power', + 'friendly_name': 'Test Model power output', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.test_model_power_output', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '77', + }) +# --- +# name: test_all_entities[sensor.test_model_water_inlet_temperature-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model_water_inlet_temperature', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 1, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Water inlet temperature', + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'water_inlet_temperature', + 'unique_id': '0000-1111-2222-3333_water_inlet_temperature', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[sensor.test_model_water_inlet_temperature-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'temperature', + 'friendly_name': 'Test Model Water inlet temperature', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.test_model_water_inlet_temperature', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '11', + }) +# --- +# name: test_all_entities[sensor.test_model_water_outlet_temperature-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_model_water_outlet_temperature', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 1, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Water outlet temperature', + 'platform': 'weheat', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'water_outlet_temperature', + 'unique_id': '0000-1111-2222-3333_water_outlet_temperature', + 'unit_of_measurement': , + }) +# --- +# name: test_all_entities[sensor.test_model_water_outlet_temperature-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'temperature', + 'friendly_name': 'Test Model Water outlet temperature', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.test_model_water_outlet_temperature', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '22', + }) +# --- diff --git a/tests/components/weheat/test_sensor.py b/tests/components/weheat/test_sensor.py new file mode 100644 index 00000000000000..5bd05b5cb2b1d2 --- /dev/null +++ b/tests/components/weheat/test_sensor.py @@ -0,0 +1,56 @@ +"""Tests for the weheat sensor platform.""" + +from unittest.mock import AsyncMock, patch + +from freezegun.api import FrozenDateTimeFactory +import pytest +from syrupy import SnapshotAssertion +from weheat.abstractions.discovery import HeatPumpDiscovery + +from homeassistant.const import Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from . import setup_integration + +from tests.common import MockConfigEntry, snapshot_platform + + +@pytest.mark.usefixtures("entity_registry_enabled_by_default") +async def test_all_entities( + hass: HomeAssistant, + snapshot: SnapshotAssertion, + mock_weheat_discover: AsyncMock, + mock_weheat_heat_pump: AsyncMock, + mock_config_entry: MockConfigEntry, + entity_registry: er.EntityRegistry, +) -> None: + """Test all entities.""" + with patch("homeassistant.components.weheat.PLATFORMS", [Platform.SENSOR]): + await setup_integration(hass, mock_config_entry) + + await hass.async_block_till_done() + + await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id) + + +@pytest.mark.parametrize(("has_dhw", "nr_of_entities"), [(False, 9), (True, 11)]) +async def test_create_entities( + hass: HomeAssistant, + mock_weheat_discover: AsyncMock, + mock_weheat_heat_pump: AsyncMock, + mock_heat_pump_info: HeatPumpDiscovery.HeatPumpInfo, + mock_config_entry: MockConfigEntry, + freezer: FrozenDateTimeFactory, + has_dhw: bool, + nr_of_entities: int, +) -> None: + """Test creating entities.""" + mock_heat_pump_info.has_dhw = has_dhw + mock_weheat_discover.return_value = [mock_heat_pump_info] + + with patch("homeassistant.components.weheat.PLATFORMS", [Platform.SENSOR]): + await setup_integration(hass, mock_config_entry) + + await hass.async_block_till_done() + assert len(hass.states.async_all()) == nr_of_entities