diff --git a/custom_components/alfen_wallbox/__init__.py b/custom_components/alfen_wallbox/__init__.py index 6307501..2e4df14 100644 --- a/custom_components/alfen_wallbox/__init__.py +++ b/custom_components/alfen_wallbox/__init__.py @@ -1,29 +1,24 @@ """Alfen Wallbox integration.""" import asyncio -from datetime import timedelta +from asyncio import timeout import logging from aiohttp import ClientConnectionError -from async_timeout import timeout from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( CONF_HOST, CONF_NAME, - CONF_USERNAME, CONF_PASSWORD, + CONF_USERNAME, Platform, ) from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady from .alfen import AlfenDevice - -from .const import ( - DOMAIN, - TIMEOUT, -) +from .const import DOMAIN, TIMEOUT PLATFORMS = [ Platform.SENSOR, @@ -45,6 +40,7 @@ async def async_setup(hass: HomeAssistant, config: dict) -> bool: async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: + """Set up Alfen Wallbox from a config entry.""" conf = config_entry.data device = await alfen_setup( hass, conf[CONF_HOST], conf[CONF_NAME], conf[CONF_USERNAME], conf[CONF_PASSWORD] diff --git a/custom_components/alfen_wallbox/alfen.py b/custom_components/alfen_wallbox/alfen.py index 3492a82..8153d2a 100644 --- a/custom_components/alfen_wallbox/alfen.py +++ b/custom_components/alfen_wallbox/alfen.py @@ -1,41 +1,39 @@ +"""Alfen Wallbox API.""" import json import logging import ssl from aiohttp import ClientResponse -from homeassistant.helpers.aiohttp_client import async_get_clientsession - from urllib3 import disable_warnings from homeassistant.core import HomeAssistant -from homeassistant.util import Throttle - +from homeassistant.helpers.aiohttp_client import async_get_clientsession from .const import ( + ALFEN_PRODUCT_MAP, CAT, + CAT_COMM, + CAT_DISPLAY, CAT_GENERIC, CAT_GENERIC2, + CAT_MBUS_TCP, CAT_METER1, CAT_METER2, CAT_METER4, CAT_OCPP, CAT_STATES, CAT_TEMP, - CAT_MBUS_TCP, - CAT_COMM, - CAT_DISPLAY, CMD, DISPLAY_NAME_VALUE, DOMAIN, - ALFEN_PRODUCT_MAP, ID, + INFO, LICENSES, + LOGIN, + LOGOUT, METHOD_GET, METHOD_POST, OFFSET, - INFO, - LOGIN, - LOGOUT, PARAM_COMMAND, PARAM_DISPLAY_NAME, PARAM_PASSWORD, @@ -44,7 +42,7 @@ PROPERTIES, TIMEOUT, TOTAL, - VALUE + VALUE, ) POST_HEADER_JSON = {"Content-Type": "application/json"} @@ -88,18 +86,21 @@ def __init__(self, self.ssl = context async def init(self): + """Initialize the Alfen API.""" await self.get_info() - self.id = "alfen_{}".format(self.name) + self.id = f"alfen_{self.name}" if self.name is None: self.name = f"{self.info.identity} ({self.host})" def get_number_of_socket(self): + """Get number of socket from the properties.""" for prop in self.properties: if prop[ID] == '205E_0': self.number_socket = int(prop[VALUE]) break def get_licenses(self): + """Get licenses from the properties.""" for prop in self.properties: if prop[ID] == '21A2_0': for key, value in LICENSES.items(): @@ -108,6 +109,7 @@ def get_licenses(self): break async def get_info(self): + """Get info from the API.""" response = await self._session.get( url=self.__get_url(INFO), ssl=self.ssl ) @@ -129,6 +131,7 @@ async def get_info(self): @property def status(self) -> str: + """Return the status of the device.""" return self._status @property @@ -143,12 +146,14 @@ def device_info(self) -> dict: } async def async_update(self): + """Update the device properties.""" if not self.keepLogout and not self.wait and not self.updating: self.updating = True await self._get_all_properties_value() self.updating = False async def _post(self, cmd, payload=None, allowed_login=True) -> ClientResponse | None: + """Send a POST request to the API.""" try: self.wait = True _LOGGER.debug("Send Post Request") @@ -180,6 +185,7 @@ async def _post(self, cmd, payload=None, allowed_login=True) -> ClientResponse | return None async def _get(self, url, allowed_login=True) -> ClientResponse | None: + """Send a GET request to the API.""" try: async with self._session.get(url, timeout=TIMEOUT, ssl=self.ssl) as response: if response.status == 401 and allowed_login: @@ -196,6 +202,7 @@ async def _get(self, url, allowed_login=True) -> ClientResponse | None: return None async def login(self): + """Login to the API.""" try: response = await self._post(cmd=LOGIN, payload={ PARAM_USERNAME: self.username, PARAM_PASSWORD: self.password, PARAM_DISPLAY_NAME: DISPLAY_NAME_VALUE}) @@ -205,6 +212,7 @@ async def login(self): return None async def logout(self): + """Logout from the API.""" try: response = await self._post(cmd=LOGOUT) _LOGGER.debug(f"Logout response {response}") @@ -213,6 +221,7 @@ async def logout(self): return None async def _update_value(self, api_param, value, allowed_login=True) -> ClientResponse | None: + """Update a value on the API.""" try: self.wait = True async with self._session.post( @@ -233,8 +242,9 @@ async def _update_value(self, api_param, value, allowed_login=True) -> ClientRes return None async def _get_value(self, api_param): + """Get a value from the API.""" response = await self._get(url=self.__get_url( - "{}?{}={}".format(PROP, ID, api_param))) + f"{PROP}?{ID}={api_param}")) _LOGGER.debug(f"Status Response {response}") @@ -248,6 +258,7 @@ async def _get_value(self, api_param): break async def _get_all_properties_value(self): + """Get all properties from the API.""" _LOGGER.debug(f"Get properties") properties = [] for cat in (CAT_GENERIC, CAT_GENERIC2, CAT_METER1, CAT_STATES, CAT_TEMP, CAT_OCPP, CAT_METER4, CAT_MBUS_TCP, CAT_COMM, CAT_DISPLAY, CAT_METER2): @@ -255,7 +266,7 @@ async def _get_all_properties_value(self): offset = 0 while (nextRequest): response = await self._get(url=self.__get_url( - "{}?{}={}&{}={}".format(PROP, CAT, cat, OFFSET, offset))) + f"{PROP}?{CAT}={cat}&{OFFSET}={offset}")) _LOGGER.debug(f"Status Response {response}") if response is not None: properties += response[PROPERTIES] @@ -266,10 +277,12 @@ async def _get_all_properties_value(self): self.properties = properties async def reboot_wallbox(self): + """Reboot the wallbox.""" response = await self._post(cmd=CMD, payload={PARAM_COMMAND: "reboot"}) _LOGGER.debug(f"Reboot response {response}") async def async_request(self, method: str, cmd: str, json_data=None) -> ClientResponse | None: + """Send a request to the API.""" try: return await self.request(method, cmd, json_data) except Exception as e: # pylint: disable=broad-except @@ -277,6 +290,7 @@ async def async_request(self, method: str, cmd: str, json_data=None) -> ClientRe return None async def request(self, method: str, cmd: str, json_data=None) -> ClientResponse: + """Send a request to the API.""" if method == METHOD_POST: response = await self._post(cmd=cmd, payload=json_data) elif method == METHOD_GET: @@ -286,6 +300,7 @@ async def request(self, method: str, cmd: str, json_data=None) -> ClientResponse return response async def set_value(self, api_param, value): + """Set a value on the API.""" response = await self._update_value(api_param, value) if response: # we expect that the value is updated so we are just update the value in the properties @@ -297,15 +312,18 @@ async def set_value(self, api_param, value): break async def get_value(self, api_param): + """Get a value from the API.""" await self._get_value(api_param) async def set_current_limit(self, limit) -> None: + """Set the current limit.""" _LOGGER.debug(f"Set current limit {limit}A") if limit > 32 | limit < 1: return None await self.set_value("2129_0", limit) async def set_rfid_auth_mode(self, enabled): + """Set the RFID Auth Mode.""" _LOGGER.debug(f"Set RFID Auth Mode {enabled}") value = 0 @@ -315,12 +333,14 @@ async def set_rfid_auth_mode(self, enabled): await self.set_value("2126_0", value) async def set_current_phase(self, phase) -> None: + """Set the current phase.""" _LOGGER.debug(f"Set current phase {phase}") if phase not in ('L1', 'L2', 'L3'): return None await self.set_value("2069_0", phase) async def set_phase_switching(self, enabled): + """Set the phase switching.""" _LOGGER.debug(f"Set Phase Switching {enabled}") value = 0 @@ -329,23 +349,28 @@ async def set_phase_switching(self, enabled): await self.set_value("2185_0", value) async def set_green_share(self, value) -> None: + """Set the green share.""" _LOGGER.debug(f"Set green share value {value}%") if value < 0 | value > 100: return None await self.set_value("3280_2", value) async def set_comfort_power(self, value) -> None: + """Set the comfort power.""" _LOGGER.debug(f"Set Comfort Level {value}W") if value < 1400 | value > 5000: return None await self.set_value("3280_3", value) def __get_url(self, action) -> str: - return "https://{}/api/{}".format(self.host, action) + """Get the URL for the API.""" + return f"https://{self.host}/api/{action}" class AlfenDeviceInfo: + """Representation of a Alfen device info.""" def __init__(self, response) -> None: + """Initialize the Alfen device info.""" self.identity = response["Identity"] self.firmware_version = response["FWVersion"] self.model_id = response["Model"] diff --git a/custom_components/alfen_wallbox/binary_sensor.py b/custom_components/alfen_wallbox/binary_sensor.py index c89e677..1916527 100644 --- a/custom_components/alfen_wallbox/binary_sensor.py +++ b/custom_components/alfen_wallbox/binary_sensor.py @@ -1,37 +1,40 @@ -import logging - +"""Support for Alfen Eve Proline binary sensors.""" from dataclasses import dataclass +import logging from typing import Final +from homeassistant.components.binary_sensor import ( + BinarySensorEntity, + BinarySensorEntityDescription, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import DOMAIN as ALFEN_DOMAIN +from .alfen import AlfenDevice from .const import ( ID, - LICENSE_NONE, - LICENSE_SCN, - LICENSE_LOAD_BALANCING_STATIC, - LICENSE_LOAD_BALANCING_ACTIVE, LICENSE_HIGH_POWER, - LICENSE_RFID, - LICENSE_PERSONALIZED_DISPLAY, + LICENSE_LOAD_BALANCING_ACTIVE, + LICENSE_LOAD_BALANCING_STATIC, LICENSE_MOBILE, + LICENSE_NONE, LICENSE_PAYMENT_GIROE, - VALUE + LICENSE_PERSONALIZED_DISPLAY, + LICENSE_RFID, + LICENSE_SCN, + VALUE, ) -from .alfen import AlfenDevice from .entity import AlfenEntity -from homeassistant.components.binary_sensor import BinarySensorEntity, BinarySensorEntityDescription -from homeassistant.config_entries import ConfigEntry -from homeassistant.core import HomeAssistant -from homeassistant.helpers.entity_platform import AddEntitiesCallback - -from . import DOMAIN as ALFEN_DOMAIN - _LOGGER = logging.getLogger(__name__) @dataclass class AlfenBinaryDescriptionMixin: """Define an entity description mixin for binary sensor entities.""" + api_param: str @@ -133,7 +136,7 @@ def __init__(self, # check if license is available if '21A2_0' in self._device.properties: if self._device.properties['21A2_0'][VALUE] == LICENSE_NONE: - return False + return if self.entity_description.key == "license_scn": self._attr_is_on = LICENSE_SCN in self._device.licenses if self.entity_description.key == "license_active_loadbalancing": @@ -157,6 +160,8 @@ def __init__(self, @property def available(self) -> bool: + """Return True if entity is available.""" + if self.entity_description.api_param is not None: for prop in self._device.properties: if prop[ID] == self.entity_description.api_param: @@ -167,6 +172,8 @@ def available(self) -> bool: @property def is_on(self) -> bool: + """Return True if entity is on.""" + if self.entity_description.api_param is not None: for prop in self._device.properties: if prop[ID] == self.entity_description.api_param: diff --git a/custom_components/alfen_wallbox/button.py b/custom_components/alfen_wallbox/button.py index 50944a4..3180922 100644 --- a/custom_components/alfen_wallbox/button.py +++ b/custom_components/alfen_wallbox/button.py @@ -1,20 +1,28 @@ - +"""Button entity for Alfen EV chargers.""""" from dataclasses import dataclass import logging from typing import Final -from homeassistant import core -from .alfen import POST_HEADER_JSON, AlfenDevice -from .entity import AlfenEntity - from homeassistant.components.button import ButtonEntity, ButtonEntityDescription from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import CMD, DISPLAY_NAME_VALUE, LOGIN, LOGOUT, METHOD_POST, PARAM_COMMAND, COMMAND_REBOOT, PARAM_DISPLAY_NAME, PARAM_PASSWORD, PARAM_USERNAME from . import DOMAIN as ALFEN_DOMAIN - +from .alfen import AlfenDevice +from .const import ( + CMD, + COMMAND_REBOOT, + DISPLAY_NAME_VALUE, + LOGIN, + LOGOUT, + METHOD_POST, + PARAM_COMMAND, + PARAM_DISPLAY_NAME, + PARAM_PASSWORD, + PARAM_USERNAME, +) +from .entity import AlfenEntity _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/alfen_wallbox/config_flow.py b/custom_components/alfen_wallbox/config_flow.py index 1fd7998..a702a15 100644 --- a/custom_components/alfen_wallbox/config_flow.py +++ b/custom_components/alfen_wallbox/config_flow.py @@ -1,16 +1,15 @@ """Config flow for the Alfen Wallbox platform.""" import asyncio +from asyncio import timeout import logging from aiohttp import ClientError -from async_timeout import timeout import voluptuous as vol from homeassistant import config_entries -from homeassistant.const import CONF_HOST, CONF_NAME, CONF_USERNAME, CONF_PASSWORD +from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME from .alfen import AlfenDevice - from .const import DOMAIN, TIMEOUT _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/alfen_wallbox/const.py b/custom_components/alfen_wallbox/const.py index 04b81da..0630059 100644 --- a/custom_components/alfen_wallbox/const.py +++ b/custom_components/alfen_wallbox/const.py @@ -1,4 +1,4 @@ - +"""Constants for the Alfen Wallbox integration.""" DOMAIN = "alfen_wallbox" ID = "id" diff --git a/custom_components/alfen_wallbox/entity.py b/custom_components/alfen_wallbox/entity.py index 821f2c1..5f79cc0 100644 --- a/custom_components/alfen_wallbox/entity.py +++ b/custom_components/alfen_wallbox/entity.py @@ -1,14 +1,16 @@ -from datetime import timedelta +"""Base entity for Alfen Wallbox integration.""" import logging +from homeassistant.helpers.entity import DeviceInfo, Entity + from .alfen import AlfenDevice from .const import DOMAIN as ALFEN_DOMAIN -from homeassistant.helpers.entity import DeviceInfo, Entity _LOGGER = logging.getLogger(__name__) class AlfenEntity(Entity): + """Define a base Alfen entity.""" def __init__(self, device: AlfenDevice) -> None: """Initialize the Alfen entity.""" diff --git a/custom_components/alfen_wallbox/number.py b/custom_components/alfen_wallbox/number.py index 5226736..17be3b8 100644 --- a/custom_components/alfen_wallbox/number.py +++ b/custom_components/alfen_wallbox/number.py @@ -1,15 +1,17 @@ -from homeassistant.helpers import entity_platform -from .const import ID, LICENSE_HIGH_POWER, SERVICE_SET_COMFORT_POWER, SERVICE_SET_CURRENT_LIMIT, SERVICE_SET_GREEN_SHARE, VALUE -from homeassistant.components.number import NumberDeviceClass, NumberEntity, NumberEntityDescription, NumberMode -from homeassistant.config_entries import ConfigEntry -from homeassistant.helpers.entity_platform import AddEntitiesCallback -from . import DOMAIN as ALFEN_DOMAIN -from homeassistant.core import HomeAssistant +"""Support for Alfen Eve Proline Wallbox.""" +from dataclasses import dataclass import logging from typing import Final -from dataclasses import dataclass -from .entity import AlfenEntity -from .alfen import AlfenDevice + +import voluptuous as vol + +from homeassistant.components.number import ( + NumberDeviceClass, + NumberEntity, + NumberEntityDescription, + NumberMode, +) +from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( CURRENCY_EURO, PERCENTAGE, @@ -17,11 +19,21 @@ UnitOfPower, UnitOfTime, ) +from homeassistant.core import HomeAssistant +from homeassistant.helpers import config_validation as cv, entity_platform +from homeassistant.helpers.entity_platform import AddEntitiesCallback -import voluptuous as vol - -from homeassistant.helpers import config_validation as cv - +from . import DOMAIN as ALFEN_DOMAIN +from .alfen import AlfenDevice +from .const import ( + ID, + LICENSE_HIGH_POWER, + SERVICE_SET_COMFORT_POWER, + SERVICE_SET_CURRENT_LIMIT, + SERVICE_SET_GREEN_SHARE, + VALUE, +) +from .entity import AlfenEntity _LOGGER = logging.getLogger(__name__) @@ -29,6 +41,7 @@ @dataclass class AlfenNumberDescriptionMixin: """Define an entity description mixin for select entities.""" + assumed_state: bool state: float api_param: str diff --git a/custom_components/alfen_wallbox/select.py b/custom_components/alfen_wallbox/select.py index fa6a839..0233150 100644 --- a/custom_components/alfen_wallbox/select.py +++ b/custom_components/alfen_wallbox/select.py @@ -1,28 +1,26 @@ -import logging -from typing import Final, Any - +"""Alfen Wallbox Select Entities.""" from dataclasses import dataclass +import logging +from typing import Final -from homeassistant.helpers import entity_platform - -from .const import ID, SERVICE_DISABLE_RFID_AUTHORIZATION_MODE, SERVICE_ENABLE_RFID_AUTHORIZATION_MODE, SERVICE_SET_CURRENT_PHASE, VALUE -from .entity import AlfenEntity +import voluptuous as vol +from homeassistant.components.select import SelectEntity, SelectEntityDescription from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers import entity_platform from homeassistant.helpers.entity_platform import AddEntitiesCallback +from . import DOMAIN as ALFEN_DOMAIN from .alfen import AlfenDevice - -from homeassistant.components.select import ( - SelectEntity, - SelectEntityDescription, +from .const import ( + ID, + SERVICE_DISABLE_RFID_AUTHORIZATION_MODE, + SERVICE_ENABLE_RFID_AUTHORIZATION_MODE, + SERVICE_SET_CURRENT_PHASE, + VALUE, ) - -from homeassistant.core import HomeAssistant, callback -from . import DOMAIN as ALFEN_DOMAIN - -import voluptuous as vol - +from .entity import AlfenEntity _LOGGER = logging.getLogger(__name__) @@ -369,6 +367,7 @@ def __init__( async def async_select_option(self, option: str) -> None: """Change the selected option.""" + value = {v: k for k, v in self.values_dict.items()}[option] await self._device.set_value(self.entity_description.api_param, value) self.async_write_ha_state() diff --git a/custom_components/alfen_wallbox/sensor.py b/custom_components/alfen_wallbox/sensor.py index c13b50b..118cfb8 100644 --- a/custom_components/alfen_wallbox/sensor.py +++ b/custom_components/alfen_wallbox/sensor.py @@ -1,13 +1,17 @@ -import logging -from typing import Final +"""Support for Alfen Eve Single Proline Wallbox.""" from dataclasses import dataclass +import datetime from datetime import timedelta +import logging +from typing import Final -from homeassistant.helpers.entity import DeviceInfo -from homeassistant.helpers.typing import StateType - -from .entity import AlfenEntity from homeassistant import const +from homeassistant.components.sensor import ( + SensorDeviceClass, + SensorEntity, + SensorEntityDescription, + SensorStateClass, +) from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( PERCENTAGE, @@ -17,33 +21,18 @@ UnitOfFrequency, UnitOfPower, UnitOfTemperature, - UnitOfTime + UnitOfTime, ) - -import datetime - from homeassistant.core import HomeAssistant, callback -from homeassistant.components.sensor import ( - DEVICE_CLASS_ENERGY, - DEVICE_CLASS_POWER, - SensorEntity, - SensorEntityDescription, - SensorStateClass, - SensorDeviceClass -) -from homeassistant.helpers.entity_platform import AddEntitiesCallback - from homeassistant.helpers import entity_platform +from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.typing import StateType from . import DOMAIN as ALFEN_DOMAIN - - from .alfen import AlfenDevice -from .const import ( - ID, - SERVICE_REBOOT_WALLBOX, - VALUE, -) +from .const import ID, SERVICE_REBOOT_WALLBOX, VALUE +from .entity import AlfenEntity _LOGGER = logging.getLogger(__name__) SCAN_INTERVAL = timedelta(seconds=5) @@ -1430,6 +1419,7 @@ async def async_setup_platform( config: ConfigEntry, async_add_entities: AddEntitiesCallback, discovery_info=None): + """Set up the Alfen sensor.""" pass @@ -1463,6 +1453,7 @@ async def async_setup_entry( class AlfenMainSensor(AlfenEntity): + """Representation of a Alfen Main Sensor.""" entity_description: AlfenSensorDescription @@ -1617,14 +1608,14 @@ def state(self) -> StateType: # some exception of return value # Display state status - if self.entity_description.api_param == "3190_1" or self.entity_description.api_param == "3191_1": + if self.entity_description.api_param in ("3190_1", "3191_1"): if prop[VALUE] == 28: return "See error Number" else: return STATUS_DICT.get(prop[VALUE], 'Unknown') # meter_reading from w to kWh - if self.entity_description.api_param == "2221_22" or self.entity_description.api_param == "3221_22": + if self.entity_description.api_param in ("2221_22", "3221_22"): return round((prop[VALUE] / 1000), 2) # Car PWM Duty cycle % @@ -1649,7 +1640,7 @@ def state(self) -> StateType: return result # change milliseconds to d/m/y HH:MM:SS - if self.entity_description.api_param == "2187_0" or self.entity_description.api_param == "2059_0": + if self.entity_description.api_param in ("2187_0", "2059_0"): return datetime.datetime.fromtimestamp(prop[VALUE] / 1000).strftime("%d/%m/%Y %H:%M:%S") # Allowed phase 1 or Allowed Phase 2 @@ -1660,15 +1651,15 @@ def state(self) -> StateType: return round(prop[VALUE], self.entity_description.round_digits) # mode3_state - if self.entity_description.api_param == "2501_4" or self.entity_description.api_param == "2502_4": + if self.entity_description.api_param in ("2501_4", "2502_4"): return MODE_3_STAT_DICT.get(prop[VALUE], 'Unknown') # Socket CPRO State - if self.entity_description.api_param == "2501_3" or self.entity_description.api_param == "2502_3": + if self.entity_description.api_param in ("2501_3", "2502_3"): return POWER_STATES_DICT.get(prop[VALUE], 'Unknown') # Main CSM State - if self.entity_description.api_param == "2501_1" or self.entity_description.api_param == "2502_1": + if self.entity_description.api_param in ("2501_1", "2502_1"): return MAIN_STATE_DICT.get(prop[VALUE], 'Unknown') # OCPP Boot notification @@ -1680,11 +1671,11 @@ def state(self) -> StateType: return MODBUS_CONNECTION_STATES_DICT.get(prop[VALUE], 'Unknown') # wallbox display message - if self.entity_description.api_param == "3190_2" or self.entity_description.api_param == "3191_2": + if self.entity_description.api_param in ("3190_2", "3191_2"): return str(prop[VALUE]) + ': ' + DISPLAY_ERROR_DICT.get(prop[VALUE], 'Unknown') # Status code - if self.entity_description.api_param == "2501_2" or self.entity_description.api_param == "2502_2": + if self.entity_description.api_param in ("2501_2", "2502_2"): return STATUS_DICT.get(prop[VALUE], 'Unknown') return prop[VALUE] diff --git a/custom_components/alfen_wallbox/switch.py b/custom_components/alfen_wallbox/switch.py index 14d997f..a666147 100644 --- a/custom_components/alfen_wallbox/switch.py +++ b/custom_components/alfen_wallbox/switch.py @@ -1,20 +1,22 @@ -import logging - from dataclasses import dataclass +import logging from typing import Any, Final -from homeassistant.helpers import entity_platform - -from .const import ID, SERVICE_DISABLE_PHASE_SWITCHING, SERVICE_ENABLE_PHASE_SWITCHING, VALUE -from .alfen import AlfenDevice -from .entity import AlfenEntity - from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_platform from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import DOMAIN as ALFEN_DOMAIN +from .alfen import AlfenDevice +from .const import ( + ID, + SERVICE_DISABLE_PHASE_SWITCHING, + SERVICE_ENABLE_PHASE_SWITCHING, + VALUE, +) +from .entity import AlfenEntity _LOGGER = logging.getLogger(__name__) @@ -104,6 +106,7 @@ async def async_setup_entry( class AlfenSwitchSensor(AlfenEntity, SwitchEntity): """Define an Alfen binary sensor.""" + entity_description: AlfenSwitchDescription def __init__(self, @@ -119,6 +122,7 @@ def __init__(self, @property def available(self) -> bool: + """Return True if entity is available.""" for prop in self._device.properties: if prop[ID] == self.entity_description.api_param: return True @@ -126,6 +130,7 @@ def available(self) -> bool: @property def is_on(self) -> bool: + """Return True if entity is on.""" for prop in self._device.properties: if prop[ID] == self.entity_description.api_param: return prop[VALUE] == 1 diff --git a/custom_components/alfen_wallbox/text.py b/custom_components/alfen_wallbox/text.py index 0f737c3..249d8c8 100644 --- a/custom_components/alfen_wallbox/text.py +++ b/custom_components/alfen_wallbox/text.py @@ -1,22 +1,19 @@ from __future__ import annotations -import logging from dataclasses import dataclass +import logging from typing import Final -from .const import ID from homeassistant.components.counter import VALUE - -from .alfen import AlfenDevice -from .entity import AlfenEntity - - from homeassistant.components.text import TextEntity, TextEntityDescription, TextMode from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import DOMAIN as ALFEN_DOMAIN +from .alfen import AlfenDevice +from .const import ID +from .entity import AlfenEntity _LOGGER = logging.getLogger(__name__) @@ -68,7 +65,7 @@ class AlfenTextDescription(TextEntityDescription, AlfenTextDescriptionMixin): async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: - """Add Alfen Select from a config_entry""" + """Add Alfen Select from a config_entry.""" device = hass.data[ALFEN_DOMAIN][entry.entry_id] texts = [AlfenText(device, description) @@ -85,6 +82,7 @@ class AlfenText(AlfenEntity, TextEntity): def __init__( self, device: AlfenDevice, description: AlfenTextDescription ) -> None: + """Initialize the Alfen text entity.""" super().__init__(device) self._device = device self._attr_name = f"{device.name} {description.name}"