diff --git a/homeassistant/components/p1_monitor/__init__.py b/homeassistant/components/p1_monitor/__init__.py index 03055013345..b157f3e8116 100644 --- a/homeassistant/components/p1_monitor/__init__.py +++ b/homeassistant/components/p1_monitor/__init__.py @@ -3,7 +3,14 @@ from __future__ import annotations from typing import TypedDict -from p1monitor import P1Monitor, Phases, Settings, SmartMeter +from p1monitor import ( + P1Monitor, + P1MonitorNoDataError, + Phases, + Settings, + SmartMeter, + WaterMeter, +) from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, Platform @@ -19,6 +26,7 @@ from .const import ( SERVICE_PHASES, SERVICE_SETTINGS, SERVICE_SMARTMETER, + SERVICE_WATERMETER, ) PLATFORMS = [Platform.SENSOR] @@ -55,12 +63,14 @@ class P1MonitorData(TypedDict): smartmeter: SmartMeter phases: Phases settings: Settings + watermeter: WaterMeter | None class P1MonitorDataUpdateCoordinator(DataUpdateCoordinator[P1MonitorData]): """Class to manage fetching P1 Monitor data from single endpoint.""" config_entry: ConfigEntry + has_water_meter: bool | None = None def __init__( self, @@ -84,6 +94,16 @@ class P1MonitorDataUpdateCoordinator(DataUpdateCoordinator[P1MonitorData]): SERVICE_SMARTMETER: await self.p1monitor.smartmeter(), SERVICE_PHASES: await self.p1monitor.phases(), SERVICE_SETTINGS: await self.p1monitor.settings(), + SERVICE_WATERMETER: None, } + if self.has_water_meter or self.has_water_meter is None: + try: + data[SERVICE_WATERMETER] = await self.p1monitor.watermeter() + self.has_water_meter = True + except P1MonitorNoDataError: + LOGGER.debug("No watermeter data received from P1 Monitor") + if self.has_water_meter is None: + self.has_water_meter = False + return data diff --git a/homeassistant/components/p1_monitor/const.py b/homeassistant/components/p1_monitor/const.py index d72927a80f6..045301d38c4 100644 --- a/homeassistant/components/p1_monitor/const.py +++ b/homeassistant/components/p1_monitor/const.py @@ -10,11 +10,6 @@ LOGGER = logging.getLogger(__package__) SCAN_INTERVAL = timedelta(seconds=5) SERVICE_SMARTMETER: Final = "smartmeter" +SERVICE_WATERMETER: Final = "watermeter" SERVICE_PHASES: Final = "phases" SERVICE_SETTINGS: Final = "settings" - -SERVICES: dict[str, str] = { - SERVICE_SMARTMETER: "SmartMeter", - SERVICE_PHASES: "Phases", - SERVICE_SETTINGS: "Settings", -} diff --git a/homeassistant/components/p1_monitor/diagnostics.py b/homeassistant/components/p1_monitor/diagnostics.py index b99cc7b86e1..29f48d47cd9 100644 --- a/homeassistant/components/p1_monitor/diagnostics.py +++ b/homeassistant/components/p1_monitor/diagnostics.py @@ -10,7 +10,13 @@ from homeassistant.const import CONF_HOST from homeassistant.core import HomeAssistant from . import P1MonitorDataUpdateCoordinator -from .const import DOMAIN, SERVICE_PHASES, SERVICE_SETTINGS, SERVICE_SMARTMETER +from .const import ( + DOMAIN, + SERVICE_PHASES, + SERVICE_SETTINGS, + SERVICE_SMARTMETER, + SERVICE_WATERMETER, +) TO_REDACT = { CONF_HOST, @@ -23,7 +29,7 @@ async def async_get_config_entry_diagnostics( """Return diagnostics for a config entry.""" coordinator: P1MonitorDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] - return { + data = { "entry": { "title": entry.title, "data": async_redact_data(entry.data, TO_REDACT), @@ -34,3 +40,8 @@ async def async_get_config_entry_diagnostics( "settings": asdict(coordinator.data[SERVICE_SETTINGS]), }, } + + if coordinator.has_water_meter: + data["data"]["watermeter"] = asdict(coordinator.data[SERVICE_WATERMETER]) + + return data diff --git a/homeassistant/components/p1_monitor/manifest.json b/homeassistant/components/p1_monitor/manifest.json index c94893f61fd..626cff15dfa 100644 --- a/homeassistant/components/p1_monitor/manifest.json +++ b/homeassistant/components/p1_monitor/manifest.json @@ -3,7 +3,7 @@ "name": "P1 Monitor", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/p1_monitor", - "requirements": ["p1monitor==1.0.1"], + "requirements": ["p1monitor==2.1.0"], "codeowners": ["@klaasnicolaas"], "quality_scale": "platinum", "iot_class": "local_polling", diff --git a/homeassistant/components/p1_monitor/sensor.py b/homeassistant/components/p1_monitor/sensor.py index 57f6b0ad99c..757bf249ca1 100644 --- a/homeassistant/components/p1_monitor/sensor.py +++ b/homeassistant/components/p1_monitor/sensor.py @@ -19,6 +19,7 @@ from homeassistant.const import ( ENERGY_KILO_WATT_HOUR, POWER_WATT, VOLUME_CUBIC_METERS, + VOLUME_LITERS, ) from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import DeviceEntryType @@ -33,206 +34,256 @@ from .const import ( SERVICE_PHASES, SERVICE_SETTINGS, SERVICE_SMARTMETER, - SERVICES, + SERVICE_WATERMETER, ) -SENSORS: dict[ - Literal["smartmeter", "phases", "settings"], tuple[SensorEntityDescription, ...] -] = { - SERVICE_SMARTMETER: ( - SensorEntityDescription( - key="gas_consumption", - name="Gas Consumption", - entity_registry_enabled_default=False, - native_unit_of_measurement=VOLUME_CUBIC_METERS, - device_class=SensorDeviceClass.GAS, - state_class=SensorStateClass.TOTAL_INCREASING, - ), - SensorEntityDescription( - key="power_consumption", - name="Power Consumption", - native_unit_of_measurement=POWER_WATT, - device_class=SensorDeviceClass.POWER, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="energy_consumption_high", - name="Energy Consumption - High Tariff", - native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, - device_class=SensorDeviceClass.ENERGY, - state_class=SensorStateClass.TOTAL_INCREASING, - ), - SensorEntityDescription( - key="energy_consumption_low", - name="Energy Consumption - Low Tariff", - native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, - device_class=SensorDeviceClass.ENERGY, - state_class=SensorStateClass.TOTAL_INCREASING, - ), - SensorEntityDescription( - key="power_production", - name="Power Production", - native_unit_of_measurement=POWER_WATT, - device_class=SensorDeviceClass.POWER, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="energy_production_high", - name="Energy Production - High Tariff", - native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, - device_class=SensorDeviceClass.ENERGY, - state_class=SensorStateClass.TOTAL_INCREASING, - ), - SensorEntityDescription( - key="energy_production_low", - name="Energy Production - Low Tariff", - native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, - device_class=SensorDeviceClass.ENERGY, - state_class=SensorStateClass.TOTAL_INCREASING, - ), - SensorEntityDescription( - key="energy_tariff_period", - name="Energy Tariff Period", - icon="mdi:calendar-clock", - ), +SENSORS_SMARTMETER: tuple[SensorEntityDescription, ...] = ( + SensorEntityDescription( + key="gas_consumption", + name="Gas Consumption", + entity_registry_enabled_default=False, + native_unit_of_measurement=VOLUME_CUBIC_METERS, + device_class=SensorDeviceClass.GAS, + state_class=SensorStateClass.TOTAL_INCREASING, ), - SERVICE_PHASES: ( - SensorEntityDescription( - key="voltage_phase_l1", - name="Voltage Phase L1", - native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, - device_class=SensorDeviceClass.VOLTAGE, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="voltage_phase_l2", - name="Voltage Phase L2", - native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, - device_class=SensorDeviceClass.VOLTAGE, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="voltage_phase_l3", - name="Voltage Phase L3", - native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, - device_class=SensorDeviceClass.VOLTAGE, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="current_phase_l1", - name="Current Phase L1", - native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, - device_class=SensorDeviceClass.CURRENT, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="current_phase_l2", - name="Current Phase L2", - native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, - device_class=SensorDeviceClass.CURRENT, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="current_phase_l3", - name="Current Phase L3", - native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, - device_class=SensorDeviceClass.CURRENT, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="power_consumed_phase_l1", - name="Power Consumed Phase L1", - native_unit_of_measurement=POWER_WATT, - device_class=SensorDeviceClass.POWER, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="power_consumed_phase_l2", - name="Power Consumed Phase L2", - native_unit_of_measurement=POWER_WATT, - device_class=SensorDeviceClass.POWER, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="power_consumed_phase_l3", - name="Power Consumed Phase L3", - native_unit_of_measurement=POWER_WATT, - device_class=SensorDeviceClass.POWER, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="power_produced_phase_l1", - name="Power Produced Phase L1", - native_unit_of_measurement=POWER_WATT, - device_class=SensorDeviceClass.POWER, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="power_produced_phase_l2", - name="Power Produced Phase L2", - native_unit_of_measurement=POWER_WATT, - device_class=SensorDeviceClass.POWER, - state_class=SensorStateClass.MEASUREMENT, - ), - SensorEntityDescription( - key="power_produced_phase_l3", - name="Power Produced Phase L3", - native_unit_of_measurement=POWER_WATT, - device_class=SensorDeviceClass.POWER, - state_class=SensorStateClass.MEASUREMENT, - ), + SensorEntityDescription( + key="power_consumption", + name="Power Consumption", + native_unit_of_measurement=POWER_WATT, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, ), - SERVICE_SETTINGS: ( - SensorEntityDescription( - key="gas_consumption_price", - name="Gas Consumption Price", - entity_registry_enabled_default=False, - state_class=SensorStateClass.MEASUREMENT, - native_unit_of_measurement=f"{CURRENCY_EURO}/{VOLUME_CUBIC_METERS}", - ), - SensorEntityDescription( - key="energy_consumption_price_low", - name="Energy Consumption Price - Low", - state_class=SensorStateClass.MEASUREMENT, - native_unit_of_measurement=f"{CURRENCY_EURO}/{ENERGY_KILO_WATT_HOUR}", - ), - SensorEntityDescription( - key="energy_consumption_price_high", - name="Energy Consumption Price - High", - state_class=SensorStateClass.MEASUREMENT, - native_unit_of_measurement=f"{CURRENCY_EURO}/{ENERGY_KILO_WATT_HOUR}", - ), - SensorEntityDescription( - key="energy_production_price_low", - name="Energy Production Price - Low", - state_class=SensorStateClass.MEASUREMENT, - native_unit_of_measurement=f"{CURRENCY_EURO}/{ENERGY_KILO_WATT_HOUR}", - ), - SensorEntityDescription( - key="energy_production_price_high", - name="Energy Production Price - High", - state_class=SensorStateClass.MEASUREMENT, - native_unit_of_measurement=f"{CURRENCY_EURO}/{ENERGY_KILO_WATT_HOUR}", - ), + SensorEntityDescription( + key="energy_consumption_high", + name="Energy Consumption - High Tariff", + native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, ), -} + SensorEntityDescription( + key="energy_consumption_low", + name="Energy Consumption - Low Tariff", + native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + ), + SensorEntityDescription( + key="power_production", + name="Power Production", + native_unit_of_measurement=POWER_WATT, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="energy_production_high", + name="Energy Production - High Tariff", + native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + ), + SensorEntityDescription( + key="energy_production_low", + name="Energy Production - Low Tariff", + native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + ), + SensorEntityDescription( + key="energy_tariff_period", + name="Energy Tariff Period", + icon="mdi:calendar-clock", + ), +) + +SENSORS_PHASES: tuple[SensorEntityDescription, ...] = ( + SensorEntityDescription( + key="voltage_phase_l1", + name="Voltage Phase L1", + native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, + device_class=SensorDeviceClass.VOLTAGE, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="voltage_phase_l2", + name="Voltage Phase L2", + native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, + device_class=SensorDeviceClass.VOLTAGE, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="voltage_phase_l3", + name="Voltage Phase L3", + native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, + device_class=SensorDeviceClass.VOLTAGE, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="current_phase_l1", + name="Current Phase L1", + native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + device_class=SensorDeviceClass.CURRENT, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="current_phase_l2", + name="Current Phase L2", + native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + device_class=SensorDeviceClass.CURRENT, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="current_phase_l3", + name="Current Phase L3", + native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + device_class=SensorDeviceClass.CURRENT, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="power_consumed_phase_l1", + name="Power Consumed Phase L1", + native_unit_of_measurement=POWER_WATT, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="power_consumed_phase_l2", + name="Power Consumed Phase L2", + native_unit_of_measurement=POWER_WATT, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="power_consumed_phase_l3", + name="Power Consumed Phase L3", + native_unit_of_measurement=POWER_WATT, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="power_produced_phase_l1", + name="Power Produced Phase L1", + native_unit_of_measurement=POWER_WATT, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="power_produced_phase_l2", + name="Power Produced Phase L2", + native_unit_of_measurement=POWER_WATT, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + ), + SensorEntityDescription( + key="power_produced_phase_l3", + name="Power Produced Phase L3", + native_unit_of_measurement=POWER_WATT, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + ), +) + +SENSORS_SETTINGS: tuple[SensorEntityDescription, ...] = ( + SensorEntityDescription( + key="gas_consumption_price", + name="Gas Consumption Price", + entity_registry_enabled_default=False, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=f"{CURRENCY_EURO}/{VOLUME_CUBIC_METERS}", + ), + SensorEntityDescription( + key="energy_consumption_price_low", + name="Energy Consumption Price - Low", + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=f"{CURRENCY_EURO}/{ENERGY_KILO_WATT_HOUR}", + ), + SensorEntityDescription( + key="energy_consumption_price_high", + name="Energy Consumption Price - High", + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=f"{CURRENCY_EURO}/{ENERGY_KILO_WATT_HOUR}", + ), + SensorEntityDescription( + key="energy_production_price_low", + name="Energy Production Price - Low", + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=f"{CURRENCY_EURO}/{ENERGY_KILO_WATT_HOUR}", + ), + SensorEntityDescription( + key="energy_production_price_high", + name="Energy Production Price - High", + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=f"{CURRENCY_EURO}/{ENERGY_KILO_WATT_HOUR}", + ), +) + +SENSORS_WATERMETER: tuple[SensorEntityDescription, ...] = ( + SensorEntityDescription( + key="consumption_day", + name="Consumption Day", + state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=VOLUME_LITERS, + ), + SensorEntityDescription( + key="consumption_total", + name="Consumption Total", + state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=VOLUME_CUBIC_METERS, + ), + SensorEntityDescription( + key="pulse_count", + name="Pulse Count", + ), +) async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up P1 Monitor Sensors based on a config entry.""" - async_add_entities( + coordinator: P1MonitorDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] + entities: list[P1MonitorSensorEntity] = [] + entities.extend( P1MonitorSensorEntity( - coordinator=hass.data[DOMAIN][entry.entry_id], + coordinator=coordinator, description=description, - service_key=service_key, - name=entry.title, - service=SERVICES[service_key], + name="SmartMeter", + service_key="smartmeter", + service=SERVICE_SMARTMETER, ) - for service_key, service_sensors in SENSORS.items() - for description in service_sensors + for description in SENSORS_SMARTMETER ) + entities.extend( + P1MonitorSensorEntity( + coordinator=coordinator, + description=description, + name="Phases", + service_key="phases", + service=SERVICE_PHASES, + ) + for description in SENSORS_PHASES + ) + entities.extend( + P1MonitorSensorEntity( + coordinator=coordinator, + description=description, + name="Settings", + service_key="settings", + service=SERVICE_SETTINGS, + ) + for description in SENSORS_SETTINGS + ) + if coordinator.has_water_meter: + entities.extend( + P1MonitorSensorEntity( + coordinator=coordinator, + description=description, + name="WaterMeter", + service_key="watermeter", + service=SERVICE_WATERMETER, + ) + for description in SENSORS_WATERMETER + ) + async_add_entities(entities) class P1MonitorSensorEntity( @@ -245,7 +296,7 @@ class P1MonitorSensorEntity( *, coordinator: P1MonitorDataUpdateCoordinator, description: SensorEntityDescription, - service_key: Literal["smartmeter", "phases", "settings"], + service_key: Literal["smartmeter", "watermeter", "phases", "settings"], name: str, service: str, ) -> None: @@ -253,7 +304,7 @@ class P1MonitorSensorEntity( super().__init__(coordinator=coordinator) self._service_key = service_key - self.entity_id = f"{SENSOR_DOMAIN}.{name}_{description.key}" + self.entity_id = f"{SENSOR_DOMAIN}.{service}_{description.key}" self.entity_description = description self._attr_unique_id = ( f"{coordinator.config_entry.entry_id}_{service_key}_{description.key}" @@ -266,7 +317,7 @@ class P1MonitorSensorEntity( }, configuration_url=f"http://{coordinator.config_entry.data[CONF_HOST]}", manufacturer="P1 Monitor", - name=service, + name=name, ) @property diff --git a/requirements_all.txt b/requirements_all.txt index 2a25c6da9df..322d67a94df 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1206,7 +1206,7 @@ orvibo==1.1.1 ovoenergy==1.2.0 # homeassistant.components.p1_monitor -p1monitor==1.0.1 +p1monitor==2.1.0 # homeassistant.components.mqtt # homeassistant.components.shiftr diff --git a/requirements_test_all.txt b/requirements_test_all.txt index d9cfea5b10b..8c67a756157 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -842,7 +842,7 @@ openerz-api==0.1.0 ovoenergy==1.2.0 # homeassistant.components.p1_monitor -p1monitor==1.0.1 +p1monitor==2.1.0 # homeassistant.components.mqtt # homeassistant.components.shiftr diff --git a/tests/components/p1_monitor/conftest.py b/tests/components/p1_monitor/conftest.py index dbdf572c6de..5f6713f5228 100644 --- a/tests/components/p1_monitor/conftest.py +++ b/tests/components/p1_monitor/conftest.py @@ -2,7 +2,7 @@ import json from unittest.mock import AsyncMock, MagicMock, patch -from p1monitor import Phases, Settings, SmartMeter +from p1monitor import Phases, Settings, SmartMeter, WaterMeter import pytest from homeassistant.components.p1_monitor.const import DOMAIN @@ -43,7 +43,12 @@ def mock_p1monitor(): json.loads(load_fixture("p1_monitor/settings.json")) ) ) - yield p1monitor_mock + client.watermeter = AsyncMock( + return_value=WaterMeter.from_dict( + json.loads(load_fixture("p1_monitor/watermeter.json")) + ) + ) + yield client @pytest.fixture diff --git a/tests/components/p1_monitor/fixtures/watermeter.json b/tests/components/p1_monitor/fixtures/watermeter.json new file mode 100644 index 00000000000..f69a4edcf88 --- /dev/null +++ b/tests/components/p1_monitor/fixtures/watermeter.json @@ -0,0 +1,10 @@ +[ + { + "TIMEPERIOD_ID": 13, + "TIMESTAMP_UTC": 1656194400, + "TIMESTAMP_lOCAL": "2022-06-26 00:00:00", + "WATERMETER_CONSUMPTION_LITER": 112.0, + "WATERMETER_CONSUMPTION_TOTAL_M3": 1696.14, + "WATERMETER_PULS_COUNT": 112.0 + } +] diff --git a/tests/components/p1_monitor/test_config_flow.py b/tests/components/p1_monitor/test_config_flow.py index 42a41789a92..13541e782b4 100644 --- a/tests/components/p1_monitor/test_config_flow.py +++ b/tests/components/p1_monitor/test_config_flow.py @@ -27,17 +27,12 @@ async def test_full_user_flow(hass: HomeAssistant) -> None: ) as mock_setup_entry: result2 = await hass.config_entries.flow.async_configure( result["flow_id"], - user_input={ - CONF_NAME: "Name", - CONF_HOST: "example.com", - }, + user_input={CONF_NAME: "Name", CONF_HOST: "example.com"}, ) assert result2.get("type") == FlowResultType.CREATE_ENTRY assert result2.get("title") == "Name" - assert result2.get("data") == { - CONF_HOST: "example.com", - } + assert result2.get("data") == {CONF_HOST: "example.com"} assert len(mock_setup_entry.mock_calls) == 1 assert len(mock_p1monitor.mock_calls) == 1 @@ -52,10 +47,7 @@ async def test_api_error(hass: HomeAssistant) -> None: result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER}, - data={ - CONF_NAME: "Name", - CONF_HOST: "example.com", - }, + data={CONF_NAME: "Name", CONF_HOST: "example.com"}, ) assert result.get("type") == FlowResultType.FORM diff --git a/tests/components/p1_monitor/test_diagnostics.py b/tests/components/p1_monitor/test_diagnostics.py index 6b97107c353..1ab9da7adc8 100644 --- a/tests/components/p1_monitor/test_diagnostics.py +++ b/tests/components/p1_monitor/test_diagnostics.py @@ -55,5 +55,10 @@ async def test_diagnostics( "energy_production_price_high": "0.20522", "energy_production_price_low": "0.20522", }, + "watermeter": { + "consumption_day": 112.0, + "consumption_total": 1696.14, + "pulse_count": 112.0, + }, }, } diff --git a/tests/components/p1_monitor/test_init.py b/tests/components/p1_monitor/test_init.py index 1cf9cf21966..d7817faecdf 100644 --- a/tests/components/p1_monitor/test_init.py +++ b/tests/components/p1_monitor/test_init.py @@ -28,7 +28,7 @@ async def test_load_unload_config_entry( @patch( - "homeassistant.components.p1_monitor.P1Monitor.request", + "homeassistant.components.p1_monitor.P1Monitor._request", side_effect=P1MonitorConnectionError, ) async def test_config_entry_not_ready( diff --git a/tests/components/p1_monitor/test_sensor.py b/tests/components/p1_monitor/test_sensor.py index faaafca5ab8..fe9560c9cb6 100644 --- a/tests/components/p1_monitor/test_sensor.py +++ b/tests/components/p1_monitor/test_sensor.py @@ -1,4 +1,7 @@ """Tests for the sensors provided by the P1 Monitor integration.""" +from unittest.mock import MagicMock + +from p1monitor import P1MonitorNoDataError import pytest from homeassistant.components.p1_monitor.const import DOMAIN @@ -17,6 +20,7 @@ from homeassistant.const import ( ELECTRIC_POTENTIAL_VOLT, ENERGY_KILO_WATT_HOUR, POWER_WATT, + VOLUME_LITERS, ) from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr, entity_registry as er @@ -33,8 +37,8 @@ async def test_smartmeter( entity_registry = er.async_get(hass) device_registry = dr.async_get(hass) - state = hass.states.get("sensor.monitor_power_consumption") - entry = entity_registry.async_get("sensor.monitor_power_consumption") + state = hass.states.get("sensor.smartmeter_power_consumption") + entry = entity_registry.async_get("sensor.smartmeter_power_consumption") assert entry assert state assert entry.unique_id == f"{entry_id}_smartmeter_power_consumption" @@ -45,8 +49,8 @@ async def test_smartmeter( assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.POWER assert ATTR_ICON not in state.attributes - state = hass.states.get("sensor.monitor_energy_consumption_high") - entry = entity_registry.async_get("sensor.monitor_energy_consumption_high") + state = hass.states.get("sensor.smartmeter_energy_consumption_high") + entry = entity_registry.async_get("sensor.smartmeter_energy_consumption_high") assert entry assert state assert entry.unique_id == f"{entry_id}_smartmeter_energy_consumption_high" @@ -59,8 +63,8 @@ async def test_smartmeter( assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.ENERGY assert ATTR_ICON not in state.attributes - state = hass.states.get("sensor.monitor_energy_tariff_period") - entry = entity_registry.async_get("sensor.monitor_energy_tariff_period") + state = hass.states.get("sensor.smartmeter_energy_tariff_period") + entry = entity_registry.async_get("sensor.smartmeter_energy_tariff_period") assert entry assert state assert entry.unique_id == f"{entry_id}_smartmeter_energy_tariff_period" @@ -90,8 +94,8 @@ async def test_phases( entity_registry = er.async_get(hass) device_registry = dr.async_get(hass) - state = hass.states.get("sensor.monitor_voltage_phase_l1") - entry = entity_registry.async_get("sensor.monitor_voltage_phase_l1") + state = hass.states.get("sensor.phases_voltage_phase_l1") + entry = entity_registry.async_get("sensor.phases_voltage_phase_l1") assert entry assert state assert entry.unique_id == f"{entry_id}_phases_voltage_phase_l1" @@ -102,8 +106,8 @@ async def test_phases( assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.VOLTAGE assert ATTR_ICON not in state.attributes - state = hass.states.get("sensor.monitor_current_phase_l1") - entry = entity_registry.async_get("sensor.monitor_current_phase_l1") + state = hass.states.get("sensor.phases_current_phase_l1") + entry = entity_registry.async_get("sensor.phases_current_phase_l1") assert entry assert state assert entry.unique_id == f"{entry_id}_phases_current_phase_l1" @@ -114,8 +118,8 @@ async def test_phases( assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.CURRENT assert ATTR_ICON not in state.attributes - state = hass.states.get("sensor.monitor_power_consumed_phase_l1") - entry = entity_registry.async_get("sensor.monitor_power_consumed_phase_l1") + state = hass.states.get("sensor.phases_power_consumed_phase_l1") + entry = entity_registry.async_get("sensor.phases_power_consumed_phase_l1") assert entry assert state assert entry.unique_id == f"{entry_id}_phases_power_consumed_phase_l1" @@ -146,8 +150,8 @@ async def test_settings( entity_registry = er.async_get(hass) device_registry = dr.async_get(hass) - state = hass.states.get("sensor.monitor_energy_consumption_price_low") - entry = entity_registry.async_get("sensor.monitor_energy_consumption_price_low") + state = hass.states.get("sensor.settings_energy_consumption_price_low") + entry = entity_registry.async_get("sensor.settings_energy_consumption_price_low") assert entry assert state assert entry.unique_id == f"{entry_id}_settings_energy_consumption_price_low" @@ -159,8 +163,8 @@ async def test_settings( == f"{CURRENCY_EURO}/{ENERGY_KILO_WATT_HOUR}" ) - state = hass.states.get("sensor.monitor_energy_production_price_low") - entry = entity_registry.async_get("sensor.monitor_energy_production_price_low") + state = hass.states.get("sensor.settings_energy_production_price_low") + entry = entity_registry.async_get("sensor.settings_energy_production_price_low") assert entry assert state assert entry.unique_id == f"{entry_id}_settings_energy_production_price_low" @@ -183,9 +187,52 @@ async def test_settings( assert not device_entry.sw_version +async def test_watermeter( + hass: HomeAssistant, + init_integration: MockConfigEntry, +) -> None: + """Test the P1 Monitor - WaterMeter sensors.""" + entry_id = init_integration.entry_id + entity_registry = er.async_get(hass) + device_registry = dr.async_get(hass) + state = hass.states.get("sensor.watermeter_consumption_day") + entry = entity_registry.async_get("sensor.watermeter_consumption_day") + assert entry + assert state + assert entry.unique_id == f"{entry_id}_watermeter_consumption_day" + assert state.state == "112.0" + assert state.attributes.get(ATTR_FRIENDLY_NAME) == "Consumption Day" + assert state.attributes.get(ATTR_STATE_CLASS) is SensorStateClass.TOTAL_INCREASING + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == VOLUME_LITERS + + assert entry.device_id + device_entry = device_registry.async_get(entry.device_id) + assert device_entry + assert device_entry.identifiers == {(DOMAIN, f"{entry_id}_watermeter")} + assert device_entry.manufacturer == "P1 Monitor" + assert device_entry.name == "WaterMeter" + assert device_entry.entry_type is dr.DeviceEntryType.SERVICE + assert not device_entry.model + assert not device_entry.sw_version + + +async def test_no_watermeter( + hass: HomeAssistant, mock_p1monitor: MagicMock, mock_config_entry: MockConfigEntry +) -> None: + """Test the P1 Monitor - Without WaterMeter sensors.""" + mock_p1monitor.watermeter.side_effect = P1MonitorNoDataError + mock_config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(mock_config_entry.entry_id) + await hass.async_block_till_done() + + assert not hass.states.get("sensor.watermeter_consumption_day") + assert not hass.states.get("sensor.consumption_total") + assert not hass.states.get("sensor.pulse_count") + + @pytest.mark.parametrize( "entity_id", - ("sensor.monitor_gas_consumption",), + ("sensor.smartmeter_gas_consumption",), ) async def test_smartmeter_disabled_by_default( hass: HomeAssistant, init_integration: MockConfigEntry, entity_id: str