diff --git a/homeassistant/components/peblar/__init__.py b/homeassistant/components/peblar/__init__.py index c185a0e255059..bf1b3ef7e6624 100644 --- a/homeassistant/components/peblar/__init__.py +++ b/homeassistant/components/peblar/__init__.py @@ -16,10 +16,8 @@ from homeassistant.const import CONF_HOST, CONF_PASSWORD, Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady -from homeassistant.helpers import device_registry as dr from homeassistant.helpers.aiohttp_client import async_create_clientsession -from .const import DOMAIN from .coordinator import ( PeblarConfigEntry, PeblarDataUpdateCoordinator, @@ -76,29 +74,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: PeblarConfigEntry) -> bo entry.runtime_data = PeblarRuntimeData( data_coordinator=meter_coordinator, system_information=system_information, - user_configuraton_coordinator=user_configuration_coordinator, + user_configuration_coordinator=user_configuration_coordinator, version_coordinator=version_coordinator, ) - # Peblar is a single device integration. Setting up the device directly - # during setup. This way we only have to reference it in all entities. - device_registry = dr.async_get(hass) - device_registry.async_get_or_create( - config_entry_id=entry.entry_id, - configuration_url=f"http://{entry.data[CONF_HOST]}", - connections={ - (dr.CONNECTION_NETWORK_MAC, system_information.ethernet_mac_address), - (dr.CONNECTION_NETWORK_MAC, system_information.wlan_mac_address), - }, - identifiers={(DOMAIN, system_information.product_serial_number)}, - manufacturer=system_information.product_vendor_name, - model_id=system_information.product_number, - model=system_information.product_model_name, - name="Peblar EV Charger", - serial_number=system_information.product_serial_number, - sw_version=version_coordinator.data.current.firmware, - ) - # Forward the setup to the platforms await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) diff --git a/homeassistant/components/peblar/binary_sensor.py b/homeassistant/components/peblar/binary_sensor.py index 5b65a8e976d30..e8e5095f050b2 100644 --- a/homeassistant/components/peblar/binary_sensor.py +++ b/homeassistant/components/peblar/binary_sensor.py @@ -12,12 +12,10 @@ ) from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant -from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DOMAIN from .coordinator import PeblarConfigEntry, PeblarData, PeblarDataUpdateCoordinator +from .entity import PeblarEntity PARALLEL_UPDATES = 0 @@ -56,35 +54,23 @@ async def async_setup_entry( ) -> None: """Set up Peblar binary sensor based on a config entry.""" async_add_entities( - PeblarBinarySensorEntity(entry=entry, description=description) + PeblarBinarySensorEntity( + entry=entry, + coordinator=entry.runtime_data.data_coordinator, + description=description, + ) for description in DESCRIPTIONS ) class PeblarBinarySensorEntity( - CoordinatorEntity[PeblarDataUpdateCoordinator], BinarySensorEntity + PeblarEntity[PeblarDataUpdateCoordinator], + BinarySensorEntity, ): """Defines a Peblar binary sensor entity.""" entity_description: PeblarBinarySensorEntityDescription - _attr_has_entity_name = True - - def __init__( - self, - entry: PeblarConfigEntry, - description: PeblarBinarySensorEntityDescription, - ) -> None: - """Initialize the binary sensor entity.""" - super().__init__(entry.runtime_data.data_coordinator) - self.entity_description = description - self._attr_unique_id = f"{entry.unique_id}-{description.key}" - self._attr_device_info = DeviceInfo( - identifiers={ - (DOMAIN, entry.runtime_data.system_information.product_serial_number) - }, - ) - @property def is_on(self) -> bool: """Return state of the binary sensor.""" diff --git a/homeassistant/components/peblar/button.py b/homeassistant/components/peblar/button.py index 68d871c829831..66411daa2284e 100644 --- a/homeassistant/components/peblar/button.py +++ b/homeassistant/components/peblar/button.py @@ -15,12 +15,10 @@ ) from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant -from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DOMAIN from .coordinator import PeblarConfigEntry, PeblarUserConfigurationDataUpdateCoordinator +from .entity import PeblarEntity PARALLEL_UPDATES = 1 @@ -59,6 +57,7 @@ async def async_setup_entry( async_add_entities( PeblarButtonEntity( entry=entry, + coordinator=entry.runtime_data.user_configuration_coordinator, description=description, ) for description in DESCRIPTIONS @@ -66,29 +65,13 @@ async def async_setup_entry( class PeblarButtonEntity( - CoordinatorEntity[PeblarUserConfigurationDataUpdateCoordinator], ButtonEntity + PeblarEntity[PeblarUserConfigurationDataUpdateCoordinator], + ButtonEntity, ): """Defines an Peblar button.""" entity_description: PeblarButtonEntityDescription - _attr_has_entity_name = True - - def __init__( - self, - entry: PeblarConfigEntry, - description: PeblarButtonEntityDescription, - ) -> None: - """Initialize the button entity.""" - super().__init__(coordinator=entry.runtime_data.user_configuraton_coordinator) - self.entity_description = description - self._attr_unique_id = f"{entry.unique_id}_{description.key}" - self._attr_device_info = DeviceInfo( - identifiers={ - (DOMAIN, entry.runtime_data.system_information.product_serial_number) - }, - ) - async def async_press(self) -> None: """Trigger button press on the Peblar device.""" await self.entity_description.press_fn(self.coordinator.peblar) diff --git a/homeassistant/components/peblar/coordinator.py b/homeassistant/components/peblar/coordinator.py index e2b16e1e62a2f..4afc544cc1d3a 100644 --- a/homeassistant/components/peblar/coordinator.py +++ b/homeassistant/components/peblar/coordinator.py @@ -30,7 +30,7 @@ class PeblarRuntimeData: data_coordinator: PeblarDataUpdateCoordinator system_information: PeblarSystemInformation - user_configuraton_coordinator: PeblarUserConfigurationDataUpdateCoordinator + user_configuration_coordinator: PeblarUserConfigurationDataUpdateCoordinator version_coordinator: PeblarVersionDataUpdateCoordinator diff --git a/homeassistant/components/peblar/diagnostics.py b/homeassistant/components/peblar/diagnostics.py index 32716148c3f0e..a8c7423f79a64 100644 --- a/homeassistant/components/peblar/diagnostics.py +++ b/homeassistant/components/peblar/diagnostics.py @@ -15,7 +15,7 @@ async def async_get_config_entry_diagnostics( """Return diagnostics for a config entry.""" return { "system_information": entry.runtime_data.system_information.to_dict(), - "user_configuration": entry.runtime_data.user_configuraton_coordinator.data.to_dict(), + "user_configuration": entry.runtime_data.user_configuration_coordinator.data.to_dict(), "ev": entry.runtime_data.data_coordinator.data.ev.to_dict(), "meter": entry.runtime_data.data_coordinator.data.meter.to_dict(), "system": entry.runtime_data.data_coordinator.data.system.to_dict(), diff --git a/homeassistant/components/peblar/entity.py b/homeassistant/components/peblar/entity.py new file mode 100644 index 0000000000000..ecfd3e8232b49 --- /dev/null +++ b/homeassistant/components/peblar/entity.py @@ -0,0 +1,55 @@ +"""Base entity for the Peblar integration.""" + +from __future__ import annotations + +from typing import Any + +from homeassistant.const import CONF_HOST +from homeassistant.helpers import device_registry as dr +from homeassistant.helpers.device_registry import DeviceInfo +from homeassistant.helpers.entity import EntityDescription +from homeassistant.helpers.update_coordinator import ( + CoordinatorEntity, + DataUpdateCoordinator, +) + +from .const import DOMAIN +from .coordinator import PeblarConfigEntry + + +class PeblarEntity[_DataUpdateCoordinatorT: DataUpdateCoordinator[Any]]( + CoordinatorEntity[_DataUpdateCoordinatorT] +): + """Defines a Peblar entity.""" + + _attr_has_entity_name = True + + def __init__( + self, + *, + entry: PeblarConfigEntry, + coordinator: _DataUpdateCoordinatorT, + description: EntityDescription, + ) -> None: + """Initialize the Peblar entity.""" + super().__init__(coordinator=coordinator) + self.entity_description = description + self._attr_unique_id = f"{entry.unique_id}_{description.key}" + + system_information = entry.runtime_data.system_information + self._attr_device_info = DeviceInfo( + configuration_url=f"http://{entry.data[CONF_HOST]}", + connections={ + (dr.CONNECTION_NETWORK_MAC, system_information.ethernet_mac_address), + (dr.CONNECTION_NETWORK_MAC, system_information.wlan_mac_address), + }, + identifiers={ + (DOMAIN, entry.runtime_data.system_information.product_serial_number) + }, + manufacturer=system_information.product_vendor_name, + model=system_information.product_model_name, + model_id=system_information.product_number, + name="Peblar EV Charger", + serial_number=system_information.product_serial_number, + sw_version=entry.runtime_data.version_coordinator.data.current.firmware, + ) diff --git a/homeassistant/components/peblar/number.py b/homeassistant/components/peblar/number.py index 32647199b8b62..d17ff09eb94ff 100644 --- a/homeassistant/components/peblar/number.py +++ b/homeassistant/components/peblar/number.py @@ -15,17 +15,15 @@ ) from homeassistant.const import EntityCategory, UnitOfElectricCurrent from homeassistant.core import HomeAssistant -from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DOMAIN from .coordinator import ( PeblarConfigEntry, PeblarData, PeblarDataUpdateCoordinator, PeblarRuntimeData, ) +from .entity import PeblarEntity PARALLEL_UPDATES = 1 @@ -64,33 +62,29 @@ async def async_setup_entry( async_add_entities( PeblarNumberEntity( entry=entry, + coordinator=entry.runtime_data.data_coordinator, description=description, ) for description in DESCRIPTIONS ) -class PeblarNumberEntity(CoordinatorEntity[PeblarDataUpdateCoordinator], NumberEntity): +class PeblarNumberEntity( + PeblarEntity[PeblarDataUpdateCoordinator], + NumberEntity, +): """Defines a Peblar number.""" entity_description: PeblarNumberEntityDescription - _attr_has_entity_name = True - def __init__( self, entry: PeblarConfigEntry, + coordinator: PeblarDataUpdateCoordinator, description: PeblarNumberEntityDescription, ) -> None: """Initialize the Peblar entity.""" - super().__init__(entry.runtime_data.data_coordinator) - self.entity_description = description - self._attr_unique_id = f"{entry.unique_id}_{description.key}" - self._attr_device_info = DeviceInfo( - identifiers={ - (DOMAIN, entry.runtime_data.system_information.product_serial_number) - }, - ) + super().__init__(entry=entry, coordinator=coordinator, description=description) self._attr_native_max_value = description.native_max_value_fn( entry.runtime_data ) diff --git a/homeassistant/components/peblar/select.py b/homeassistant/components/peblar/select.py index d2c74f482c6c2..e9c7da77beca5 100644 --- a/homeassistant/components/peblar/select.py +++ b/homeassistant/components/peblar/select.py @@ -11,12 +11,10 @@ from homeassistant.components.select import SelectEntity, SelectEntityDescription from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant -from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DOMAIN from .coordinator import PeblarConfigEntry, PeblarUserConfigurationDataUpdateCoordinator +from .entity import PeblarEntity PARALLEL_UPDATES = 1 @@ -56,6 +54,7 @@ async def async_setup_entry( async_add_entities( PeblarSelectEntity( entry=entry, + coordinator=entry.runtime_data.user_configuration_coordinator, description=description, ) for description in DESCRIPTIONS @@ -63,29 +62,13 @@ async def async_setup_entry( class PeblarSelectEntity( - CoordinatorEntity[PeblarUserConfigurationDataUpdateCoordinator], SelectEntity + PeblarEntity[PeblarUserConfigurationDataUpdateCoordinator], + SelectEntity, ): - """Defines a peblar select entity.""" + """Defines a Peblar select entity.""" entity_description: PeblarSelectEntityDescription - _attr_has_entity_name = True - - def __init__( - self, - entry: PeblarConfigEntry, - description: PeblarSelectEntityDescription, - ) -> None: - """Initialize the select entity.""" - super().__init__(entry.runtime_data.user_configuraton_coordinator) - self.entity_description = description - self._attr_unique_id = f"{entry.unique_id}-{description.key}" - self._attr_device_info = DeviceInfo( - identifiers={ - (DOMAIN, entry.runtime_data.system_information.product_serial_number) - }, - ) - @property def current_option(self) -> str | None: """Return the selected entity option to represent the entity state.""" diff --git a/homeassistant/components/peblar/sensor.py b/homeassistant/components/peblar/sensor.py index df8cac13bcc43..e655253d75c4f 100644 --- a/homeassistant/components/peblar/sensor.py +++ b/homeassistant/components/peblar/sensor.py @@ -22,17 +22,15 @@ UnitOfPower, ) from homeassistant.core import HomeAssistant -from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.util.dt import utcnow from .const import ( - DOMAIN, PEBLAR_CHARGE_LIMITER_TO_HOME_ASSISTANT, PEBLAR_CP_STATE_TO_HOME_ASSISTANT, ) from .coordinator import PeblarConfigEntry, PeblarData, PeblarDataUpdateCoordinator +from .entity import PeblarEntity PARALLEL_UPDATES = 0 @@ -237,34 +235,21 @@ async def async_setup_entry( ) -> None: """Set up Peblar sensors based on a config entry.""" async_add_entities( - PeblarSensorEntity(entry, description) + PeblarSensorEntity( + entry=entry, + coordinator=entry.runtime_data.data_coordinator, + description=description, + ) for description in DESCRIPTIONS - if description.has_fn(entry.runtime_data.user_configuraton_coordinator.data) + if description.has_fn(entry.runtime_data.user_configuration_coordinator.data) ) -class PeblarSensorEntity(CoordinatorEntity[PeblarDataUpdateCoordinator], SensorEntity): +class PeblarSensorEntity(PeblarEntity[PeblarDataUpdateCoordinator], SensorEntity): """Defines a Peblar sensor.""" entity_description: PeblarSensorDescription - _attr_has_entity_name = True - - def __init__( - self, - entry: PeblarConfigEntry, - description: PeblarSensorDescription, - ) -> None: - """Initialize the Peblar entity.""" - super().__init__(entry.runtime_data.data_coordinator) - self.entity_description = description - self._attr_unique_id = f"{entry.unique_id}_{description.key}" - self._attr_device_info = DeviceInfo( - identifiers={ - (DOMAIN, entry.runtime_data.system_information.product_serial_number) - }, - ) - @property def native_value(self) -> datetime | int | str | None: """Return the state of the sensor.""" diff --git a/homeassistant/components/peblar/switch.py b/homeassistant/components/peblar/switch.py index 3b7ab5915082e..88f52d01e3aa1 100644 --- a/homeassistant/components/peblar/switch.py +++ b/homeassistant/components/peblar/switch.py @@ -11,17 +11,15 @@ from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant -from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DOMAIN from .coordinator import ( PeblarConfigEntry, PeblarData, PeblarDataUpdateCoordinator, PeblarRuntimeData, ) +from .entity import PeblarEntity PARALLEL_UPDATES = 1 @@ -42,7 +40,7 @@ class PeblarSwitchEntityDescription(SwitchEntityDescription): entity_category=EntityCategory.CONFIG, has_fn=lambda x: ( x.data_coordinator.data.system.force_single_phase_allowed - and x.user_configuraton_coordinator.data.connected_phases > 1 + and x.user_configuration_coordinator.data.connected_phases > 1 ), is_on_fn=lambda x: x.ev.force_single_phase, set_fn=lambda x, on: x.ev_interface(force_single_phase=on), @@ -59,6 +57,7 @@ async def async_setup_entry( async_add_entities( PeblarSwitchEntity( entry=entry, + coordinator=entry.runtime_data.data_coordinator, description=description, ) for description in DESCRIPTIONS @@ -66,28 +65,14 @@ async def async_setup_entry( ) -class PeblarSwitchEntity(CoordinatorEntity[PeblarDataUpdateCoordinator], SwitchEntity): +class PeblarSwitchEntity( + PeblarEntity[PeblarDataUpdateCoordinator], + SwitchEntity, +): """Defines a Peblar switch entity.""" entity_description: PeblarSwitchEntityDescription - _attr_has_entity_name = True - - def __init__( - self, - entry: PeblarConfigEntry, - description: PeblarSwitchEntityDescription, - ) -> None: - """Initialize the select entity.""" - super().__init__(entry.runtime_data.data_coordinator) - self.entity_description = description - self._attr_unique_id = f"{entry.unique_id}-{description.key}" - self._attr_device_info = DeviceInfo( - identifiers={ - (DOMAIN, entry.runtime_data.system_information.product_serial_number) - }, - ) - @property def is_on(self) -> bool: """Return state of the switch.""" diff --git a/homeassistant/components/peblar/update.py b/homeassistant/components/peblar/update.py index 37f20722b980c..67ce30a89a648 100644 --- a/homeassistant/components/peblar/update.py +++ b/homeassistant/components/peblar/update.py @@ -11,16 +11,14 @@ UpdateEntityDescription, ) from homeassistant.core import HomeAssistant -from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DOMAIN from .coordinator import ( PeblarConfigEntry, PeblarVersionDataUpdateCoordinator, PeblarVersionInformation, ) +from .entity import PeblarEntity PARALLEL_UPDATES = 1 @@ -56,34 +54,23 @@ async def async_setup_entry( ) -> None: """Set up Peblar update based on a config entry.""" async_add_entities( - PeblarUpdateEntity(entry, description) for description in DESCRIPTIONS + PeblarUpdateEntity( + entry=entry, + coordinator=entry.runtime_data.version_coordinator, + description=description, + ) + for description in DESCRIPTIONS ) class PeblarUpdateEntity( - CoordinatorEntity[PeblarVersionDataUpdateCoordinator], UpdateEntity + PeblarEntity[PeblarVersionDataUpdateCoordinator], + UpdateEntity, ): """Defines a Peblar update entity.""" entity_description: PeblarUpdateEntityDescription - _attr_has_entity_name = True - - def __init__( - self, - entry: PeblarConfigEntry, - description: PeblarUpdateEntityDescription, - ) -> None: - """Initialize the update entity.""" - super().__init__(entry.runtime_data.version_coordinator) - self.entity_description = description - self._attr_unique_id = f"{entry.unique_id}_{description.key}" - self._attr_device_info = DeviceInfo( - identifiers={ - (DOMAIN, entry.runtime_data.system_information.product_serial_number) - }, - ) - @property def installed_version(self) -> str | None: """Version currently installed and in use.""" diff --git a/tests/components/peblar/snapshots/test_binary_sensor.ambr b/tests/components/peblar/snapshots/test_binary_sensor.ambr index 5dd008dd320e1..72c3ac78a1242 100644 --- a/tests/components/peblar/snapshots/test_binary_sensor.ambr +++ b/tests/components/peblar/snapshots/test_binary_sensor.ambr @@ -28,7 +28,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'active_error_codes', - 'unique_id': '23-45-A4O-MOF-active_error_codes', + 'unique_id': '23-45-A4O-MOF_active_error_codes', 'unit_of_measurement': None, }) # --- @@ -75,7 +75,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'active_warning_codes', - 'unique_id': '23-45-A4O-MOF-active_warning_codes', + 'unique_id': '23-45-A4O-MOF_active_warning_codes', 'unit_of_measurement': None, }) # --- diff --git a/tests/components/peblar/snapshots/test_select.ambr b/tests/components/peblar/snapshots/test_select.ambr index 9f0852d7cf424..62e09325601ff 100644 --- a/tests/components/peblar/snapshots/test_select.ambr +++ b/tests/components/peblar/snapshots/test_select.ambr @@ -36,7 +36,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'smart_charging', - 'unique_id': '23-45-A4O-MOF-smart_charging', + 'unique_id': '23-45-A4O-MOF_smart_charging', 'unit_of_measurement': None, }) # --- diff --git a/tests/components/peblar/snapshots/test_switch.ambr b/tests/components/peblar/snapshots/test_switch.ambr index f4fc768030f88..538292785938f 100644 --- a/tests/components/peblar/snapshots/test_switch.ambr +++ b/tests/components/peblar/snapshots/test_switch.ambr @@ -28,7 +28,7 @@ 'previous_unique_id': None, 'supported_features': 0, 'translation_key': 'force_single_phase', - 'unique_id': '23-45-A4O-MOF-force_single_phase', + 'unique_id': '23-45-A4O-MOF_force_single_phase', 'unit_of_measurement': None, }) # ---