Skip to content

Commit

Permalink
- Implemented logic for Data Evento and Tempo Residuo
Browse files Browse the repository at this point in the history
- Moved helper functions to a separate file
  • Loading branch information
alexdelprete committed Feb 28, 2024
1 parent 6bb1fef commit ad772d3
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 22 deletions.
19 changes: 19 additions & 0 deletions custom_components/sinapsi_alfa/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from pymodbus.payload import BinaryPayloadDecoder

from .const import MANUFACTURER, MODEL, SENSOR_ENTITIES
from .helpers import unix_timestamp_to_iso8601_local_tz

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -256,19 +257,37 @@ def read_modbus_alfa(self):
decoder = BinaryPayloadDecoder.fromRegisters(
read_data.registers, byteorder=Endian.BIG
)

# decode the register based on type
if reg_type == "uint16":
value = round(float(decoder.decode_16bit_uint()), 2)
elif reg_type == "uint32":
value = round(float(decoder.decode_32bit_uint()), 2)
_LOGGER.debug(f"(read_modbus_alfa) Raw Value: {value}")

# Alfa provides power/energy data in W/Wh, we want kW/kWh
if reg_dev_class in [
SensorDeviceClass.ENERGY,
SensorDeviceClass.POWER,
]:
value = round(float(value / 1000), 2)
# if not power/energy type, it's an integer
else:
value = int(value)

# if distacco is 65535 set it to 0
if reg_key == "tempo_residuo_distacco":
if value == 65535:
value = 0
# if data_evento is > 4294967294 then no event
if reg_key == "data_evento":
if value > 4294967294:
value = "None"
else:
# convert timestamp to ISO8601
value = unix_timestamp_to_iso8601_local_tz(
value + self.data["tempo_residuo_distacco"]
)
self.data[reg_key] = value
_LOGGER.debug(f"(read_modbus_alfa) Data: {self.data[reg_key]}")
except Exception as modbus_error:
Expand Down
13 changes: 1 addition & 12 deletions custom_components/sinapsi_alfa/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
https://github.com/alexdelprete/ha-sinapsi-alfa
"""

import ipaddress
import logging
import re

import voluptuous as vol
from homeassistant import config_entries
Expand All @@ -26,20 +24,11 @@
DEFAULT_SCAN_INTERVAL,
DOMAIN,
)
from .helpers import host_valid

_LOGGER = logging.getLogger(__name__)


def host_valid(host):
"""Return True if hostname or IP address is valid."""
try:
if ipaddress.ip_address(host).version == (4 or 6):
return True
except ValueError:
disallowed = re.compile(r"[^a-zA-Z\d\-]")
return all(x and not disallowed.search(x) for x in host.split("."))


@callback
def get_host_from_config(hass: HomeAssistant):
"""Return the hosts already configured."""
Expand Down
20 changes: 10 additions & 10 deletions custom_components/sinapsi_alfa/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,16 +253,6 @@
"modbus_type": "uint16",
"modbus_addr": 203,
},
{
"name": "Data Evento",
"key": "data_evento",
"icon": "mdi:calendar-outline",
"device_class": None,
"state_class": None,
"unit": None,
"modbus_type": "uint32",
"modbus_addr": 780,
},
{
"name": "Tempo Residuo Distacco",
"key": "tempo_residuo_distacco",
Expand All @@ -273,6 +263,16 @@
"modbus_type": "uint16",
"modbus_addr": 782,
},
{
"name": "Data Evento",
"key": "data_evento",
"icon": "mdi:calendar-outline",
"device_class": None,
"state_class": None,
"unit": None,
"modbus_type": "uint32",
"modbus_addr": 780,
},
{
"name": "Potenza Consumata",
"key": "potenza_consumata",
Expand Down
58 changes: 58 additions & 0 deletions custom_components/sinapsi_alfa/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""Helper functions for Sinapsi Alfa.
https://github.com/alexdelprete/ha-sinapsi-alfa
"""

import ipaddress
import re
import time
from datetime import datetime, timedelta, timezone


def host_valid(host):
"""Return True if hostname or IP address is valid."""
try:
if ipaddress.ip_address(host).version == (4 or 6):
return True
except ValueError:
disallowed = re.compile(r"[^a-zA-Z\d\-]")
return all(x and not disallowed.search(x) for x in host.split("."))


def get_local_timezone_offset() -> float:
"""Get local timezone offset."""
# Get the current time in seconds since the epoch
current_time = time.time()

# Get the local timezone offset in seconds
local_timezone_offset_seconds = (
-time.timezone
if (time.localtime(current_time).tm_isdst == 0)
else -time.altzone
)

# Convert the offset to hours
local_timezone_offset_hours = local_timezone_offset_seconds / 3600

return local_timezone_offset_hours


def unix_timestamp_to_iso8601_local_tz(unix_timestamp: int) -> str:
"""Convert timestamp to ISO8601."""

# Convert Unix timestamp to datetime object in UTC
dt_utc = datetime.utcfromtimestamp(unix_timestamp).replace(tzinfo=timezone.utc) # noqa: UP017

# Get the local timezone offset
local_timezone_offset_hours = get_local_timezone_offset()

# Create a timezone object with the local offset
local_timezone = timezone(timedelta(hours=local_timezone_offset_hours))

# Convert UTC datetime to local datetime
dt_local = dt_utc.astimezone(local_timezone)

# Format local datetime object as ISO8601 string
iso8601_format = dt_local.isoformat()

return iso8601_format

0 comments on commit ad772d3

Please sign in to comment.