Skip to content

Commit

Permalink
- support for II Wallbox
Browse files Browse the repository at this point in the history
- make lala.cgi requests also dependant from active sensors (currently only wallbox)
  • Loading branch information
marq24 committed Sep 23, 2023
1 parent fe489ac commit fa7ba52
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 35 deletions.
19 changes: 18 additions & 1 deletion custom_components/senec/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
CONF_SYSTYPE_INVERTER,
CONF_SYSTYPE_WEB,
CONF_DEV_MASTER_NUM,
MAIN_SENSOR_TYPES,
QUERY_WALLBOX_KEY,
QUERY_SPARE_CAPACITY_KEY,
)

Expand Down Expand Up @@ -141,7 +143,22 @@ def __init__(self, hass: HomeAssistant, session, config_entry):
else:
self._use_https = False

self.senec = Senec(host=self._host, use_https=self._use_https, websession=session)
# check if any of the wallbox-sensors is enabled... and only THEN
# we will include the 'WALLBOX' in our POST to the lala.cgi
opt = {QUERY_WALLBOX_KEY: False}
if hass is not None and config_entry.title is not None:
registry = entity_registry.async_get(hass)
if registry is not None:
sluged_title = slugify(config_entry.title)
for description in MAIN_SENSOR_TYPES:
if not opt[QUERY_WALLBOX_KEY] and 'wallbox_' in description.key:
a_sensor_id = f"sensor.{sluged_title}_{description.key}"
a_entity = registry.async_get(a_sensor_id)
if a_entity is not None and a_entity.disabled_by is None:
_LOGGER.info("***** QUERY_WALLBOX-DATA ********")
opt[QUERY_WALLBOX_KEY] = True

self.senec = Senec(host=self._host, use_https=self._use_https, websession=session, options=opt)

self.name = config_entry.title
self._config_entry = config_entry
Expand Down
26 changes: 26 additions & 0 deletions custom_components/senec/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
DEFAULT_SCAN_INTERVAL_WEB = 300
DEFAULT_SCAN_INTERVAL_WEB_SENECV4 = 60

QUERY_WALLBOX_KEY = "query_wallbox_data"
QUERY_SPARE_CAPACITY_KEY = "query_spare_capacity"

@dataclass
Expand Down Expand Up @@ -1590,6 +1591,31 @@ class ExtBinarySensorEntityDescription(BinarySensorEntityDescription):
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
ExtSensorEntityDescription(
entity_registry_enabled_default=False,
key="wallbox_2_power",
name="Wallbox II Power",
native_unit_of_measurement=POWER_WATT,
icon="mdi:car-arrow-left",
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
),
ExtSensorEntityDescription(
entity_registry_enabled_default=False,
key="wallbox_2_ev_connected",
name="Wallbox II EV Connected",
icon="mdi:car-electric",
),
ExtSensorEntityDescription(
entity_registry_enabled_default=False,
controls=("require_stats_fields"),
key="wallbox_2_energy",
name="Wallbox II charged",
native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
icon="mdi:ev-station",
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
]

INVERTER_SENSOR_TYPES = [
Expand Down
107 changes: 73 additions & 34 deletions custom_components/senec/pysenec_ha/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from yarl import URL
from typing import Union, cast


from custom_components.senec.const import (
QUERY_WALLBOX_KEY,
QUERY_SPARE_CAPACITY_KEY,
)

Expand Down Expand Up @@ -46,7 +46,16 @@
class Senec:
"""Senec Home Battery Sensor"""

def __init__(self, host, use_https, websession):
def __init__(self, host, use_https, websession, options: dict = None):
_LOGGER.info("restarting Senec... with options: " + str(options))

self._QUERY_BMS = True
self._QUERY_STATS = True
if options is not None and QUERY_WALLBOX_KEY in options:
self._QUERY_WALLBOX = options[QUERY_WALLBOX_KEY]
else:
self._QUERY_WALLBOX = False

self.host = host
self.websession: aiohttp.websession = websession
if use_https:
Expand Down Expand Up @@ -865,6 +874,31 @@ def wallbox_energy(self) -> float:
if hasattr(self, '_raw') and "STATISTIC" in self._raw and "LIVE_WB_ENERGY" in self._raw["STATISTIC"]:
return self._raw["STATISTIC"]["LIVE_WB_ENERGY"][0]

@property
def wallbox_2_power(self) -> float:
"""
Wallbox Total Charging Power (W)
Derived from the 3 phase voltages multiplied with the phase currents from the wallbox
"""
return self._raw["WALLBOX"]["L1_CHARGING_CURRENT"][1] * self._raw["PM1OBJ1"]["U_AC"][0] + \
self._raw["WALLBOX"]["L2_CHARGING_CURRENT"][1] * self._raw["PM1OBJ1"]["U_AC"][1] + \
self._raw["WALLBOX"]["L3_CHARGING_CURRENT"][1] * self._raw["PM1OBJ1"]["U_AC"][2]

@property
def wallbox_2_ev_connected(self) -> bool:
"""
Wallbox EV Connected
"""
return self._raw["WALLBOX"]["EV_CONNECTED"][1]

@property
def wallbox_2_energy(self) -> float:
"""
Wallbox Total Energy
"""
if hasattr(self, '_raw') and "STATISTIC" in self._raw and "LIVE_WB_ENERGY" in self._raw["STATISTIC"]:
return self._raw["STATISTIC"]["LIVE_WB_ENERGY"][1]

@property
def fan_inv_lv(self) -> bool:
if hasattr(self, '_raw') and "FAN_SPEED" in self._raw and "INV_LV" in self._raw["FAN_SPEED"]:
Expand Down Expand Up @@ -901,15 +935,15 @@ async def read_senec_v31(self):
"SAFE_CHARGE_RUNNING": "",
"LI_STORAGE_MODE_RUNNING": "",
},
"STATISTIC": {
"LIVE_BAT_CHARGE": "",
"LIVE_BAT_DISCHARGE": "",
"LIVE_GRID_EXPORT": "",
"LIVE_GRID_IMPORT": "",
"LIVE_HOUSE_CONS": "",
"LIVE_PV_GEN": "",
"LIVE_WB_ENERGY": "",
},
# "STATISTIC": {
# "LIVE_BAT_CHARGE": "",
# "LIVE_BAT_DISCHARGE": "",
# "LIVE_GRID_EXPORT": "",
# "LIVE_GRID_IMPORT": "",
# "LIVE_HOUSE_CONS": "",
# "LIVE_PV_GEN": "",
# "LIVE_WB_ENERGY": "",
# },
"TEMPMEASURE": {
"BATTERY_TEMP": "",
"CASE_TEMP": "",
Expand All @@ -925,29 +959,35 @@ async def read_senec_v31(self):
"PWR_UNIT": {"POWER_L1": "", "POWER_L2": "", "POWER_L3": ""},
"PM1OBJ1": {"FREQ": "", "U_AC": "", "I_AC": "", "P_AC": "", "P_TOTAL": ""},
"PM1OBJ2": {"FREQ": "", "U_AC": "", "I_AC": "", "P_AC": "", "P_TOTAL": ""},
"BMS": {
"CELL_TEMPERATURES_MODULE_A": "",
"CELL_TEMPERATURES_MODULE_B": "",
"CELL_TEMPERATURES_MODULE_C": "",
"CELL_TEMPERATURES_MODULE_D": "",
"CELL_VOLTAGES_MODULE_A": "",
"CELL_VOLTAGES_MODULE_B": "",
"CELL_VOLTAGES_MODULE_C": "",
"CELL_VOLTAGES_MODULE_D": "",
"CURRENT": "",
"VOLTAGE": "",
"SOC": "",
"SOH": "",
"CYCLES": "",
},
"WALLBOX": {
"L1_CHARGING_CURRENT": "",
"L2_CHARGING_CURRENT": "",
"L3_CHARGING_CURRENT": "",
"EV_CONNECTED": ""
},
# "BMS": {
# "CELL_TEMPERATURES_MODULE_A": "",
# "CELL_TEMPERATURES_MODULE_B": "",
# "CELL_TEMPERATURES_MODULE_C": "",
# "CELL_TEMPERATURES_MODULE_D": "",
# "CELL_VOLTAGES_MODULE_A": "",
# "CELL_VOLTAGES_MODULE_B": "",
# "CELL_VOLTAGES_MODULE_C": "",
# "CELL_VOLTAGES_MODULE_D": "",
# "CURRENT": "",
# "VOLTAGE": "",
# "SOC": "",
# "SOH": "",
# "CYCLES": "",
# },
# "WALLBOX": {
# "L1_CHARGING_CURRENT": "",
# "L2_CHARGING_CURRENT": "",
# "L3_CHARGING_CURRENT": "",
# "EV_CONNECTED": ""
# },
"FAN_SPEED": {},
}
if self._QUERY_BMS:
form.update({"BMS": {}})
if self._QUERY_STATS:
form.update({"STATISTIC": {}})
if self._QUERY_WALLBOX:
form.update({"WALLBOX": {}})

async with self.websession.post(self.url, json=form, ssl=False) as res:
res.raise_for_status()
Expand Down Expand Up @@ -1013,7 +1053,6 @@ async def read_senec_v21_all(self):
"BAT1": {},
"BAT1OBJ1": {},
"BAT1OBJ2": {},
"BAT1OBJ2": {},
"BAT1OBJ3": {},
"BAT1OBJ4": {},
"PWR_UNIT": {},
Expand Down Expand Up @@ -1351,7 +1390,7 @@ def derating(self) -> float:
class MySenecWebPortal:

def __init__(self, user, pwd, websession, master_plant_number: int = 0, options: dict = None):
_LOGGER.info("restarting... with options: "+str(options))
_LOGGER.info("restarting MySenecWebPortal... with options: " + str(options))
if options is not None and QUERY_SPARE_CAPACITY_KEY in options:
self._QUERY_SPARE_CAPACITY = options[QUERY_SPARE_CAPACITY_KEY]

Expand Down

0 comments on commit fa7ba52

Please sign in to comment.