Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E3DC nun komplett auf openwb V2.0 Struktur umgestellt #2449

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 0 additions & 44 deletions modules/bezug_e3dc/e3dc.py

This file was deleted.

2 changes: 1 addition & 1 deletion modules/bezug_e3dc/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ else
MYLOGFILE="${RAMDISKDIR}/evu.log"
fi

bash "$OPENWBBASEDIR/packages/legacy_run.sh" "bezug_e3dc.e3dc" "${e3dcip}" >>"${MYLOGFILE}" 2>&1
bash "$OPENWBBASEDIR/packages/legacy_run.sh" "modules.e3dc.device" "counter" "$e3dcip" "$e3dc2ip" "$e3dcextprod" "$pvwattmodul" "1">>"${MYLOGFILE}" 2>&1
ret=$?

openwbDebugLog ${DMOD} 2 "EVU RET: ${ret}"
Expand Down
78 changes: 0 additions & 78 deletions modules/speicher_e3dc/e3dc.py

This file was deleted.

2 changes: 1 addition & 1 deletion modules/speicher_e3dc/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ else
MYLOGFILE="${RAMDISKDIR}/bat.log"
fi

bash "$OPENWBBASEDIR/packages/legacy_run.sh" "speicher_e3dc.e3dc" "$e3dcip" "$e3dc2ip" "$e3dcextprod" "$pvwattmodul" >>"${MYLOGFILE}" 2>&1
bash "$OPENWBBASEDIR/packages/legacy_run.sh" "modules.e3dc.device" "batv19" "$e3dcip" "$e3dc2ip" "$e3dcextprod" "$pvwattmodul" "1">>"${MYLOGFILE}" 2>&1
ret=$?

openwbDebugLog "${DMOD}" 2 "BAT RET: ${ret}"
55 changes: 55 additions & 0 deletions packages/modules/e3dc/bat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
from typing import Dict, Union
import logging

from dataclass_utils import dataclass_from_dict
from modules.common import modbus
from modules.common.component_state import BatState
from modules.common.component_type import ComponentDescriptor
from modules.common.modbus import ModbusDataType, Endian
from modules.common.fault_state import ComponentInfo
from modules.common.store import get_bat_value_store
from modules.common.simcount._simcounter import SimCounter
from modules.e3dc.config import E3dcBatSetup


log = logging.getLogger(__name__)


def read_bat(client: modbus.ModbusTcpClient_):
# 40082 SoC
soc = client.read_holding_registers(40082, ModbusDataType.INT_16, unit=1)
# 40069 Speicherleistung
power = client.read_holding_registers(40069, ModbusDataType.INT_32, wordorder=Endian.Little, unit=1)
return soc, power
okaegi marked this conversation as resolved.
Show resolved Hide resolved


class E3dcBat:
def __init__(self,
device_id: int,
ip_address: str,
component_config: Union[Dict, E3dcBatSetup]) -> None:
self.__device_id = device_id
self.component_config = dataclass_from_dict(E3dcBatSetup, component_config)
okaegi marked this conversation as resolved.
Show resolved Hide resolved
# bat
self.__sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher")
self.__store = get_bat_value_store(self.component_config.id)
self.component_info = ComponentInfo.from_component_config(self.component_config)
self.__ip_address = ip_address
okaegi marked this conversation as resolved.
Show resolved Hide resolved

def update(self, client: modbus.ModbusTcpClient_) -> None:

soc, power = read_bat(client)
log.debug("Ip: %s, soc %d power %d", self.__ip_address,
soc, power)
imported, exported = self.__sim_counter.sim_count(power)
bat_state = BatState(
power=power,
soc=soc,
imported=imported,
exported=exported
)
self.__store.set(bat_state)


component_descriptor = ComponentDescriptor(configuration_factory=E3dcBatSetup)
72 changes: 72 additions & 0 deletions packages/modules/e3dc/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from modules.common.component_setup import ComponentSetup
from modules.common import modbus


class E3dcConfiguration:
def __init__(self, ip_address1: str = None,
ip_address2: str = None,
read_ext: int = 0,
pvmodul: str = None
okaegi marked this conversation as resolved.
Show resolved Hide resolved
):
self.ip_address1 = ip_address1
self.ip_address2 = ip_address2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hier sollte nur eine Adresse sein. Die ich auch wieder nur address nennen würde, denn es könnte auch ein hostname sein.

self.read_ext = read_ext
self.pvmodul = pvmodul
# nur init hier
self.client = modbus.ModbusTcpClient_('127.0.0.1', 502)


class E3dc:
def __init__(self,
name: str = "e3dc",
type: str = "e3dc",
id: int = 0,
configuration: E3dcConfiguration = None) -> None:
self.name = name
self.type = type
self.id = id
self.configuration = configuration or E3dcConfiguration()


class E3dcBatConfiguration:
def __init__(self):
pass


class E3dcBatSetup(ComponentSetup[E3dcBatConfiguration]):
def __init__(self,
name: str = "e3dc Speicher",
type: str = "bat",
id: int = 0,
configuration: E3dcBatConfiguration = None) -> None:
super().__init__(name, type, id, configuration
or E3dcBatConfiguration())


class E3dcCounterConfiguration:
def __init__(self):
pass


class E3dcCounterSetup(ComponentSetup[E3dcCounterConfiguration]):
def __init__(self,
name: str = "e3dc Zähler",
type: str = "counter",
id: int = 0,
configuration: E3dcCounterConfiguration = None) -> None:
super().__init__(name, type, id, configuration or
E3dcCounterConfiguration())


class E3dcInverterConfiguration:
def __init__(self):
pass


class E3dcInverterSetup(ComponentSetup[E3dcInverterConfiguration]):
def __init__(self,
name: str = "E3dc Wechselrichter",
type: str = "inverter",
id: int = 0,
configuration: E3dcInverterConfiguration = None) -> None:
super().__init__(name, type, id, configuration or E3dcInverterConfiguration())
70 changes: 70 additions & 0 deletions packages/modules/e3dc/counter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env python3
import logging
from typing import Dict, Union

from dataclass_utils import dataclass_from_dict
from modules.common import modbus
from modules.common.component_state import CounterState
from modules.common.component_type import ComponentDescriptor
from modules.common.fault_state import ComponentInfo
from modules.common.simcount._simcounter import SimCounter
from modules.common.modbus import ModbusDataType, Endian
from modules.common.store import get_counter_value_store
from modules.e3dc.config import E3dcCounterSetup
from modules.common.store.ramdisk.io import ramdisk_write, ramdisk_read_int

log = logging.getLogger(__name__)


def read_counter(client: modbus.ModbusTcpClient_, ip_address):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ich frage mich bei dieser Funktion immernoch, ob das cachen des nötigen Registers tatsächlich ein Vorteil ist. So könnte die Funktion ohne aussehen:

def read_counter(client: modbus.ModbusTcpClient_):
    log.debug("Beginning EVU update")
    power = client.read_holding_registers(40073, ModbusDataType.INT_32, wordorder=Endian.Little, unit=1)
    meters = client.read_holding_registers(40104, [ModbusDataType.INT_16] * 28, unit=1)
    log.debug("power: %d, meters: %s", power, meters)
    powers = next(meters[i+1:i+4] for i in reversed(range(0, len(meters), 4)) if meters[i] == 1)
    return power, powers

Das ist schon deutlich weniger (der Kommentar der erklärt was der Kram soll mit den meters sollte da natürlich wieder rein, müsste dafür aber stimmen.). Dazu kommt noch, dass die Funktion in V2 so nicht funktioniert, weil es keine Ramdisk mehr gibt. Das kann man natürlich lösen indem das Register als Eigenschaft auf dem Counter-Objekt gespeichert wird, was allerdings in V1 nicht geht. Also muss da wieder eine Unterscheidung rein, wodurch es noch mehr Code wird.

Die Kosten für die kürzere Variante ist etwas Performance. Das ganze kostet ein paar zusätzliche Millisekunden (wenn man davon ausgeht, dass dass da ein Modbus-RS485-Kopple mit 9600 Baud hinter hängt komme ich auf eine ganze grobe Größenordnung von 20 Millisekunden). Mir erscheint das die Vereinfachung wert zu sein.
Natürlich funktioniert meine Vereinfachung nur, wenn der Server es erlaubt 28 Register auf einen Schlag auszulesen. Das müsstest du ggf. nachlesen oder ausprobieren.

log.debug("Beginning EVU update")
try:
foundreg = ramdisk_read_int("e3dc_evu_addr." + ip_address)
except FileNotFoundError:
foundreg = 0
power = client.read_holding_registers(40073, ModbusDataType.INT_32, wordorder=Endian.Little, unit=1)
# 40130 Phasenleistung in Watt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Phasenleistung"? Auf einem Register? Sollte wohl eher 40130-40132. 1 register je Phase.

Stimmt das wirklich? Gibt der e3dc da nur einen Ganzzahligen Wert raus? Das wäre ziemlich ungenau.

# max 6 Leistungsmesser verbaut ab 410105, typ 1 ist evu
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

max 6 Leistungsmesser? Die Schleife liest aber 7 aus.

# bei den meisten e3dc auf 40128
# for register in range (40104,40132,4):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# for register in range (40104,40132,4):

Diese Zeile vom Kommentar scheint mir keine Hilfe zu sein.

if foundreg == 0:
for register in range(40128, 40103, -4):
powers = client.read_holding_registers(register, [ModbusDataType.INT_16] * 4, unit=1)
log.debug("register: %d, powers %s",
register, powers)
if powers[0] == 1:
okaegi marked this conversation as resolved.
Show resolved Hide resolved
log.debug("Evu counter found, save %d", register)
ramdisk_write("e3dc_evu_addr." + ip_address, register)
break
else:
powers = client.read_holding_registers(foundreg, [ModbusDataType.INT_16] * 4, unit=1)
log.debug("foundreg: %d, powers %s", foundreg, powers)
return power, powers


class E3dcCounter:
def __init__(self,
device_id: int,
ip_address: str,
component_config: Union[Dict, E3dcCounterSetup]) -> None:
self.__device_id = device_id
self.component_config = dataclass_from_dict(E3dcCounterSetup, component_config)
self.__sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug")
self.__store = get_counter_value_store(self.component_config.id)
self.component_info = ComponentInfo.from_component_config(self.component_config)
self.__ip_address = ip_address
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gleicher Kommentar zu ip_address wie in E3dcBat


def update(self, client: modbus.ModbusTcpClient_):
power, powers = read_counter(client, self.__ip_address)
imported, exported = self.__sim_counter.sim_count(power)
counter_state = CounterState(
imported=imported,
exported=exported,
powers=powers[1:],
power=power
)
self.__store.set(counter_state)
log.debug("Update completed successfully")


component_descriptor = ComponentDescriptor(configuration_factory=E3dcCounterSetup)
Loading