From 4bbdf475b4645e97257b5d0925d003a697794564 Mon Sep 17 00:00:00 2001 From: Diogo Gomes Date: Thu, 9 Nov 2023 10:12:05 +0000 Subject: [PATCH] Add switch platform to V2C (#103678) Co-authored-by: Joost Lekkerkerker --- .coveragerc | 1 + homeassistant/components/v2c/__init__.py | 2 +- homeassistant/components/v2c/coordinator.py | 2 +- homeassistant/components/v2c/strings.json | 5 ++ homeassistant/components/v2c/switch.py | 93 +++++++++++++++++++++ 5 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 homeassistant/components/v2c/switch.py diff --git a/.coveragerc b/.coveragerc index d58eafa442c..0a7e8cd7489 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1433,6 +1433,7 @@ omit = homeassistant/components/v2c/coordinator.py homeassistant/components/v2c/entity.py homeassistant/components/v2c/sensor.py + homeassistant/components/v2c/switch.py homeassistant/components/velbus/__init__.py homeassistant/components/velbus/binary_sensor.py homeassistant/components/velbus/button.py diff --git a/homeassistant/components/v2c/__init__.py b/homeassistant/components/v2c/__init__.py index 030ae56bb79..c1b22b5735d 100644 --- a/homeassistant/components/v2c/__init__.py +++ b/homeassistant/components/v2c/__init__.py @@ -11,7 +11,7 @@ from homeassistant.helpers.httpx_client import get_async_client from .const import DOMAIN from .coordinator import V2CUpdateCoordinator -PLATFORMS: list[Platform] = [Platform.SENSOR] +PLATFORMS: list[Platform] = [Platform.SENSOR, Platform.SWITCH] async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: diff --git a/homeassistant/components/v2c/coordinator.py b/homeassistant/components/v2c/coordinator.py index b2db66f1b80..2ab6b967fc6 100644 --- a/homeassistant/components/v2c/coordinator.py +++ b/homeassistant/components/v2c/coordinator.py @@ -11,7 +11,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed -SCAN_INTERVAL = timedelta(seconds=60) +SCAN_INTERVAL = timedelta(seconds=5) _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/v2c/strings.json b/homeassistant/components/v2c/strings.json index 7ef658b5daa..fb30ea826d7 100644 --- a/homeassistant/components/v2c/strings.json +++ b/homeassistant/components/v2c/strings.json @@ -32,6 +32,11 @@ "fv_power": { "name": "Photovoltaic power" } + }, + "switch": { + "paused": { + "name": "Pause session" + } } } } diff --git a/homeassistant/components/v2c/switch.py b/homeassistant/components/v2c/switch.py new file mode 100644 index 00000000000..d54c14f88d6 --- /dev/null +++ b/homeassistant/components/v2c/switch.py @@ -0,0 +1,93 @@ +"""Switch platform for V2C EVSE.""" +from __future__ import annotations + +from collections.abc import Callable, Coroutine +from dataclasses import dataclass +import logging +from typing import Any + +from pytrydan import Trydan, TrydanData +from pytrydan.models.trydan import PauseState + +from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import DOMAIN +from .coordinator import V2CUpdateCoordinator +from .entity import V2CBaseEntity + +_LOGGER = logging.getLogger(__name__) + + +@dataclass +class V2CRequiredKeysMixin: + """Mixin for required keys.""" + + value_fn: Callable[[TrydanData], bool] + turn_on_fn: Callable[[Trydan], Coroutine[Any, Any, Any]] + turn_off_fn: Callable[[Trydan], Coroutine[Any, Any, Any]] + + +@dataclass +class V2CSwitchEntityDescription(SwitchEntityDescription, V2CRequiredKeysMixin): + """Describes a V2C EVSE switch entity.""" + + +TRYDAN_SWITCHES = ( + V2CSwitchEntityDescription( + key="paused", + translation_key="paused", + icon="mdi:pause", + value_fn=lambda evse_data: evse_data.paused == PauseState.PAUSED, + turn_on_fn=lambda evse: evse.pause(), + turn_off_fn=lambda evse: evse.resume(), + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up V2C switch platform.""" + coordinator: V2CUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id] + + entities: list[SwitchEntity] = [ + V2CSwitchEntity(coordinator, description, config_entry.entry_id) + for description in TRYDAN_SWITCHES + ] + async_add_entities(entities) + + +class V2CSwitchEntity(V2CBaseEntity, SwitchEntity): + """Representation of a V2C switch entity.""" + + entity_description: V2CSwitchEntityDescription + + def __init__( + self, + coordinator: V2CUpdateCoordinator, + description: SwitchEntityDescription, + entry_id: str, + ) -> None: + """Initialize the V2C switch entity.""" + super().__init__(coordinator, description) + self._attr_unique_id = f"{entry_id}_{description.key}" + + @property + def is_on(self) -> bool: + """Return the state of the EVSE switch.""" + return self.entity_description.value_fn(self.data) + + async def async_turn_on(self): + """Turn on the EVSE switch.""" + await self.entity_description.turn_on_fn(self.coordinator.evse) + await self.coordinator.async_request_refresh() + + async def async_turn_off(self): + """Turn off the EVSE switch.""" + await self.entity_description.turn_off_fn(self.coordinator.evse) + await self.coordinator.async_request_refresh()