diff --git a/.coveragerc b/.coveragerc index 04b61d9f93e..afdf2b3acb9 100644 --- a/.coveragerc +++ b/.coveragerc @@ -845,6 +845,7 @@ omit = homeassistant/components/nibe_heatpump/__init__.py homeassistant/components/nibe_heatpump/climate.py homeassistant/components/nibe_heatpump/binary_sensor.py + homeassistant/components/nibe_heatpump/button.py homeassistant/components/nibe_heatpump/number.py homeassistant/components/nibe_heatpump/select.py homeassistant/components/nibe_heatpump/sensor.py diff --git a/homeassistant/components/nibe_heatpump/__init__.py b/homeassistant/components/nibe_heatpump/__init__.py index 103d50a8aba..ed907a7ce6a 100644 --- a/homeassistant/components/nibe_heatpump/__init__.py +++ b/homeassistant/components/nibe_heatpump/__init__.py @@ -48,6 +48,7 @@ from .const import ( PLATFORMS: list[Platform] = [ Platform.BINARY_SENSOR, + Platform.BUTTON, Platform.CLIMATE, Platform.NUMBER, Platform.SELECT, @@ -252,6 +253,10 @@ class Coordinator(ContextCoordinator[dict[int, Coil], int]): self.async_update_context_listeners([coil.address]) + async def async_read_coil(self, coil: Coil) -> Coil: + """Read coil and update state using callbacks.""" + return await self.connection.read_coil(coil) + async def _async_update_data(self) -> dict[int, Coil]: self.task = asyncio.current_task() try: diff --git a/homeassistant/components/nibe_heatpump/button.py b/homeassistant/components/nibe_heatpump/button.py new file mode 100644 index 00000000000..da94ba9fc11 --- /dev/null +++ b/homeassistant/components/nibe_heatpump/button.py @@ -0,0 +1,63 @@ +"""The Nibe Heat Pump sensors.""" +from __future__ import annotations + +from nibe.coil_groups import UNIT_COILGROUPS, UnitCoilGroup +from nibe.exceptions import CoilNotFoundException + +from homeassistant.components.button import ButtonEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import EntityCategory +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.update_coordinator import CoordinatorEntity + +from . import DOMAIN, LOGGER, Coordinator + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up platform.""" + + coordinator: Coordinator = hass.data[DOMAIN][config_entry.entry_id] + + def reset_buttons(): + for entity_description in UNIT_COILGROUPS.get(coordinator.series, {}).get( + "main" + ): + try: + yield NibeAlarmResetButton(coordinator, entity_description) + except CoilNotFoundException as exception: + LOGGER.debug("Skipping button %r", exception) + + async_add_entities(reset_buttons()) + + +class NibeAlarmResetButton(CoordinatorEntity[Coordinator], ButtonEntity): + """Sensor entity.""" + + _attr_has_entity_name = True + _attr_entity_category = EntityCategory.DIAGNOSTIC + + def __init__(self, coordinator: Coordinator, unit: UnitCoilGroup) -> None: + """Initialize entity.""" + self._reset_coil = coordinator.heatpump.get_coil_by_address(unit.alarm_reset) + self._alarm_coil = coordinator.heatpump.get_coil_by_address(unit.alarm) + super().__init__(coordinator, {self._alarm_coil.address}) + self._attr_unique_id = f"{coordinator.unique_id}-alarm_reset" + self._attr_device_info = coordinator.device_info + + async def async_press(self) -> None: + """Execute the command.""" + await self.coordinator.async_write_coil(self._reset_coil, 1) + await self.coordinator.async_read_coil(self._alarm_coil) + + @property + def available(self) -> bool: + """Return if entity is available.""" + if coil := self.coordinator.data.get(self._alarm_coil.address): + return coil.value != 0 + + return False