Skip to content

Commit

Permalink
Merge pull request #160 from fwestenberg/master
Browse files Browse the repository at this point in the history
Configure categories and Diagnostics
  • Loading branch information
leeyuentuen authored Dec 20, 2024
2 parents d00eadc + 9a76c13 commit 40dfbbf
Show file tree
Hide file tree
Showing 16 changed files with 250 additions and 112 deletions.
9 changes: 7 additions & 2 deletions custom_components/alfen_wallbox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er

from .const import CONF_TRANSACTION_DATA, DEFAULT_SCAN_INTERVAL, DEFAULT_TIMEOUT
from .const import (
CONF_REFRESH_CATEGORIES,
DEFAULT_REFRESH_CATEGORIES,
DEFAULT_SCAN_INTERVAL,
DEFAULT_TIMEOUT,
)
from .coordinator import AlfenConfigEntry, AlfenCoordinator, options_update_listener

PLATFORMS = [
Expand All @@ -42,7 +47,7 @@ async def async_migrate_entry(
options = {
CONF_SCAN_INTERVAL: scan_interval,
CONF_TIMEOUT: DEFAULT_TIMEOUT,
CONF_TRANSACTION_DATA: False,
CONF_REFRESH_CATEGORIES: DEFAULT_REFRESH_CATEGORIES,
}
data = {
CONF_HOST: config_entry.data.get(CONF_HOST),
Expand Down
113 changes: 56 additions & 57 deletions custom_components/alfen_wallbox/alfen.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Alfen Wallbox API."""

import datetime
import json
import logging
import ssl
Expand All @@ -10,17 +11,8 @@
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_TRANSACTIONS,
CATEGORIES,
CMD,
DEFAULT_TIMEOUT,
DISPLAY_NAME_VALUE,
Expand Down Expand Up @@ -57,7 +49,7 @@ def __init__(
name: str,
username: str,
password: str,
get_transactions: bool,
category_options: list,
) -> None:
"""Init."""

Expand All @@ -66,6 +58,7 @@ def __init__(
self._status = None
self._session = session
self.username = username
self.category_options = category_options
self.info = None
self.id = None
if self.username is None:
Expand All @@ -80,7 +73,8 @@ def __init__(
self.latest_tag = None
self.transaction_offset = 0
self.transaction_counter = 0
self.get_transactions = get_transactions
self.static_properties = []
self.get_static_properties = True

# disable_warnings()

Expand Down Expand Up @@ -124,6 +118,7 @@ async def get_info(self) -> bool:
if response.status == 200:
resp = await response.json(content_type=None)
self.info = AlfenDeviceInfo(resp)

return True

_LOGGER.debug("Info API not available, use generic info")
Expand Down Expand Up @@ -155,15 +150,29 @@ def device_info(self) -> dict:

async def async_update(self) -> bool:
"""Update the device properties."""

if self.keep_logout:
return True

result = await self._get_all_properties_value()
if not result:
return False

if self.get_transactions:
dynamic_properties = []
self.properties = []
if self.get_static_properties:
self.static_properties = []

for cat in CATEGORIES:
if cat == CAT_TRANSACTIONS:
continue
if cat in self.category_options:
dynamic_properties = (
dynamic_properties + await self._get_all_properties_value(cat)
)
elif self.get_static_properties:
self.static_properties = (
self.static_properties + await self._get_all_properties_value(cat)
)
self.properties = self.static_properties + dynamic_properties
self.get_static_properties = False

if CAT_TRANSACTIONS in self.category_options:
if self.transaction_counter == 0:
await self._get_transaction()
self.transaction_counter += 1
Expand Down Expand Up @@ -296,48 +305,38 @@ async def _get_value(self, api_param):
prop[VALUE] = resp[VALUE]
break

async def _get_all_properties_value(self) -> bool:
async def _get_all_properties_value(self, category: str) -> list:
"""Get all properties from the API."""
_LOGGER.debug("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,
):
nextRequest = True
offset = 0
attempt = 0
while nextRequest:
attempt += 1
cmd = f"{PROP}?{CAT}={cat}&{OFFSET}={offset}"
response = await self._get(url=self.__get_url(cmd))
_LOGGER.debug("Status Response %s: %s", cmd, str(response))

if response is not None:
attempt = 0
properties += response[PROPERTIES]
nextRequest = response[TOTAL] > (offset + len(response[PROPERTIES]))
offset += len(response[PROPERTIES])
elif attempt >= 3:
# This only possible in case of series of timeouts or unknown exceptions in self._get()
# It's better to break completely, otherwise we can provide partial data in self.properties.
_LOGGER.debug("Returning earlier after %s attempts", str(attempt))
self.properties = []
return False
tx_start = datetime.datetime.now()
nextRequest = True
offset = 0
attempt = 0

while nextRequest:
attempt += 1
cmd = f"{PROP}?{CAT}={category}&{OFFSET}={offset}"
response = await self._get(url=self.__get_url(cmd))
_LOGGER.debug("Status Response %s: %s", cmd, str(response))

if response is not None:
attempt = 0
properties += response[PROPERTIES]
nextRequest = response[TOTAL] > (offset + len(response[PROPERTIES]))
offset += len(response[PROPERTIES])
elif attempt >= 3:
# This only possible in case of series of timeouts or unknown exceptions in self._get()
# It's better to break completely, otherwise we can provide partial data in self.properties.
_LOGGER.debug("Returning earlier after %s attempts", str(attempt))
self.properties = []
return False

_LOGGER.debug("Properties %s", str(properties))
self.properties = properties

return True
runtime = datetime.datetime.now() - tx_start
_LOGGER.info("Called %s in %.2f seconds", category, runtime.total_seconds())
return properties

async def reboot_wallbox(self):
"""Reboot the wallbox."""
Expand Down Expand Up @@ -516,7 +515,7 @@ async def set_value(self, api_param, value):

async def get_value(self, api_param):
"""Get a value from the API."""
await self._get_value(api_param)
return await self._get_value(api_param)

async def set_current_limit(self, limit) -> None:
"""Set the current limit."""
Expand Down
9 changes: 9 additions & 0 deletions custom_components/alfen_wallbox/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .const import (
CAT,
ID,
LICENSE_HIGH_POWER,
LICENSE_LOAD_BALANCING_ACTIVE,
Expand Down Expand Up @@ -196,3 +197,11 @@ def is_on(self) -> bool:
return False

return self._attr_is_on

@property
def extra_state_attributes(self):
"""Return the default attributes of the element."""
for prop in self.coordinator.device.properties:
if prop[ID] == self.entity_description.api_param:
return {"category": prop[CAT]}
return None
1 change: 1 addition & 0 deletions custom_components/alfen_wallbox/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def __init__(
async def async_press(self) -> None:
"""Press the button."""
if self.entity_description.url_action == FORCE_UPDATE:
self.coordinator.device.get_static_properties = True
await self.coordinator.device.async_update()
return

Expand Down
24 changes: 13 additions & 11 deletions custom_components/alfen_wallbox/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Config flow for the Alfen Wallbox platform."""

import logging
from typing import Any

import voluptuous as vol
Expand All @@ -22,15 +21,19 @@
from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv

from .const import CONF_TRANSACTION_DATA, DEFAULT_SCAN_INTERVAL, DEFAULT_TIMEOUT, DOMAIN

_LOGGER = logging.getLogger(__name__)

from .const import (
CATEGORIES,
CONF_REFRESH_CATEGORIES,
DEFAULT_REFRESH_CATEGORIES,
DEFAULT_SCAN_INTERVAL,
DEFAULT_TIMEOUT,
DOMAIN,
)

DEFAULT_OPTIONS = {
CONF_SCAN_INTERVAL: DEFAULT_SCAN_INTERVAL,
CONF_TIMEOUT: DEFAULT_TIMEOUT,
CONF_TRANSACTION_DATA: False,
CONF_REFRESH_CATEGORIES: DEFAULT_REFRESH_CATEGORIES,
}


Expand Down Expand Up @@ -61,12 +64,12 @@ async def async_step_init(
),
): vol.All(vol.Coerce(int), vol.Range(min=1, max=30)),
vol.Required(
CONF_TRANSACTION_DATA,
CONF_REFRESH_CATEGORIES,
default=self.config_entry.options.get(
CONF_TRANSACTION_DATA, True
CONF_REFRESH_CATEGORIES, DEFAULT_REFRESH_CATEGORIES
),
): cv.boolean,
}
): cv.multi_select(CATEGORIES),
},
),
)

Expand All @@ -77,7 +80,6 @@ class AlfenFlowHandler(ConfigFlow, domain=DOMAIN):
VERSION = 2
CONNECTION_CLASS = CONN_CLASS_LOCAL_POLL


@staticmethod
@callback
def async_get_options_flow(config_entry: ConfigEntry) -> AlfenOptionsFlowHandler:
Expand Down
49 changes: 43 additions & 6 deletions custom_components/alfen_wallbox/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,60 @@

DISPLAY_NAME_VALUE = "ha"

CAT_COMM = "comm"
CAT_DISPLAY = "display"
CAT_GENERIC = "generic"
CAT_GENERIC2 = "generic2"
CAT_MBUS_TCP = "MbusTCP"
CAT_METER1 = "meter1"
CAT_METER2 = "meter2"
CAT_METER4 = "meter4"
CAT_OCPP = "ocpp"
CAT_STATES = "states"
CAT_TEMP = "temp"
CAT_OCPP = "ocpp"
CAT_MBUS_TCP = "MbusTCP"
CAT_COMM = "comm"
CAT_DISPLAY = "display"
# CAT_LEDS = "leds"
# CAT_ACCELERO = "accelero"
CAT_METER2 = "meter2"
CAT_TRANSACTIONS = "transactions"

COMMAND_REBOOT = "reboot"

CONF_TRANSACTION_DATA = "get_transaction_data"
CONF_REFRESH_CATEGORIES = "refresh_categories"

DEFAULT_REFRESH_CATEGORIES = (
CAT_DISPLAY,
CAT_METER1,
CAT_METER2,
CAT_METER4,
CAT_STATES,
CAT_TEMP,
)

CATEGORIES = (
CAT_COMM,
CAT_DISPLAY,
CAT_GENERIC,
CAT_GENERIC2,
CAT_MBUS_TCP,
CAT_METER1,
CAT_METER2,
CAT_METER4,
CAT_OCPP,
CAT_STATES,
CAT_TEMP,
CAT_TRANSACTIONS,
)

# CONF_GENERIC = "get_generic"
# CONF_GENERIC2 = "get_generic2"
# CONF_METER1 = "get_meter1"
# CONF_METER2 = "get_meter2"
# CONF_METER4 = "get_meter4"
# CONF_STATES = "states"
# CONF_TEMP = "temp"
# CONF_OCPP = "ocpp"
# CONF_MBUSTCP = "MbusTCP"
# CONF_COMM = "comm"
# CONF_TRANSACTION_DATA = "display"

DEFAULT_SCAN_INTERVAL = 5
DEFAULT_TIMEOUT = 20
Expand Down
Loading

0 comments on commit 40dfbbf

Please sign in to comment.