Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion packages/control/counter_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def __init__(self):
self.connected_counters = []
self.connected_chargepoints = []
self.childless = []
self.sim_counter = SimCounter("", "", prefix="bezug")
self.sim_counter = SimCounter("", "", ComponentType.COUNTER)
self.sim_counter.topic = "openWB/set/counter/set/"

def get_evu_counter(self) -> Counter:
Expand Down
6 changes: 5 additions & 1 deletion packages/modules/common/configurable_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,17 @@ def error_handler(self) -> None:
self.error_timestamp = None
Pub().pub(error_timestamp_topic, self.error_timestamp)

def add_component(self, component_config: T_COMPONENT_CONFIG) -> None:
def add_component(self,
component_config: T_COMPONENT_CONFIG,
component_dependency_injection: Optional[Callable] = None) -> None:
with SingleComponentUpdateContext(FaultState(ComponentInfo.from_component_config(component_config))):
component = self.__component_factory(component_config)
component.initialized = False
self.components["component" + str(component_config.id)] = component
component.initialize()
component.initialized = True
if component_dependency_injection is not None:
component = component_dependency_injection(component)

def update(self):
initialized_components = []
Expand Down
20 changes: 12 additions & 8 deletions packages/modules/common/simcount/_simcount.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@
import logging
import math
import time
from typing import Optional

from control import data as data_module
from modules.common.component_type import ComponentType
from modules.common.simcount._calculate import calculate_import_export
from modules.common.simcount.simcounter_state import SimCounterState
from modules.common.simcount._simcounter_store import get_sim_counter_store, restore_last_energy
from modules.common.simcount._simcounter_store import SimCounterStoreBroker, restore_last_energy

log = logging.getLogger(__name__)


def sim_count(power_present: float, topic: str = "", data: SimCounterState = None, prefix: str = "") -> SimCounterState:
def sim_count(power_present: float,
topic: str = "",
previous_state: SimCounterState = None,
component_type: Optional[ComponentType] = None) -> SimCounterState:
""" emulate import export

Parameters
Expand All @@ -27,25 +32,24 @@ def sim_count(power_present: float, topic: str = "", data: SimCounterState = Non
------
neuer state
"""
store = get_sim_counter_store()
store = SimCounterStoreBroker()
timestamp_present = time.time()
previous_state = store.load(prefix, topic) if data is None else data

if math.isnan(power_present):
raise ValueError("power_present is NaN.")

if isinstance(power_present, (int, float)):
if previous_state is None:
log.debug("No previous state found. Starting new simulation.")
return store.initialize(prefix, topic, power_present, timestamp_present)
return store.initialize(component_type, topic, power_present, timestamp_present)
else:
log.debug("Previous state: %s", previous_state)
if math.isnan(previous_state.imported):
log.error("imported is NaN. Reset simcount state.")
previous_state.imported = restore_last_energy(topic, "imported")
previous_state.imported = restore_last_energy(topic, "imported", component_type)
if math.isnan(previous_state.exported):
log.error("exported is NaN. Reset simcount state.")
previous_state.exported = restore_last_energy(topic, "exported")
previous_state.exported = restore_last_energy(topic, "exported", component_type)
control_interval = data_module.data.general_data.data.control_interval
if 2 * control_interval < timestamp_present - previous_state.timestamp:
log.warning("Time difference between previous state and current state is too large. "
Expand All @@ -63,5 +67,5 @@ def sim_count(power_present: float, topic: str = "", data: SimCounterState = Non
previous_state.exported + exported
)
log.debug("imported: %g Wh, exported: %g Wh, new state: %s", imported, exported, current_state)
store.save(prefix, topic, current_state)
store.save(topic, current_state)
return current_state
12 changes: 7 additions & 5 deletions packages/modules/common/simcount/_simcounter.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
from typing import Tuple, Optional

from modules.common.component_type import ComponentType, special_to_general_type_mapping
from modules.common.simcount._simcount import sim_count
from modules.common.simcount.simcounter_state import SimCounterState


class SimCounter:
def __init__(self, device_id: int, component_id: int, prefix: str):
def __init__(self, device_id: int, component_id: int, component_type: str):
self.topic = "openWB/set/system/device/{}/component/{}/".format(device_id, component_id)
self.prefix = "pv2" if prefix == "pv" and component_id != 1 else prefix
self.component_type = special_to_general_type_mapping(
component_type.value if isinstance(component_type, ComponentType) else component_type)
self.data: Optional[SimCounterState] = None

def sim_count(self, power: float, dc_power: Optional[float] = None) -> Tuple[float, float]:
if (self.prefix == "pv" or self.prefix == "pv2") and dc_power is not None and dc_power == 0:
if self.component_type != ComponentType.INVERTER and dc_power is not None and dc_power == 0:
power = 0
self.data = sim_count(power, self.topic, self.data, self.prefix)
self.data = sim_count(power, self.topic, self.data, self.component_type)
return self.data.imported, self.data.exported


Expand All @@ -23,5 +25,5 @@ def __init__(self, chargepoint_id: int):
self.data = None # type: Optional[SimCounterState]

def sim_count(self, power: float) -> Tuple[float, float]:
self.data = sim_count(power, self.topic, self.data, "")
self.data = sim_count(power, self.topic, self.data, None)
return self.data.imported, self.data.exported
53 changes: 14 additions & 39 deletions packages/modules/common/simcount/_simcounter_store.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import logging
from abc import abstractmethod
from typing import Optional


from control import data
from helpermodules import pub
from helpermodules.utils.topic_parser import get_index, get_second_index
from modules.common.component_type import type_to_topic_mapping
from helpermodules.utils.topic_parser import get_second_index
from modules.common.component_type import ComponentType, type_to_topic_mapping
from modules.common.simcount.simcounter_state import SimCounterState

POSTFIX_EXPORT = "watt0neg"
Expand All @@ -15,46 +13,27 @@
log = logging.getLogger(__name__)


class SimCounterStore:
@abstractmethod
def load(self, prefix: str, topic: str) -> Optional[SimCounterState]:
pass

@abstractmethod
def save(self, prefix: str, topic: str, state: SimCounterState):
pass

@abstractmethod
def initialize(self, prefix: str, topic: str, power: float, timestamp: float) -> SimCounterState:
pass


class SimCounterStoreBroker(SimCounterStore):
def initialize(self, prefix: str, topic: str, power: float, timestamp: float) -> SimCounterState:
state = SimCounterState(timestamp, power, imported=restore_last_energy(
topic, "imported") if "pv" not in prefix else 0, exported=restore_last_energy(topic, "exported"))
self.save(prefix, topic, state)
class SimCounterStoreBroker:
def initialize(self, component_type: ComponentType, topic: str, power: float, timestamp: float) -> SimCounterState:
state = SimCounterState(
timestamp, power,
imported=restore_last_energy(
topic, "imported", component_type) if component_type != ComponentType.INVERTER else 0,
exported=restore_last_energy(topic, "exported", component_type))
self.save(topic, state)
return state

def load(self, prefix: str, topic: str) -> Optional[SimCounterState]:
return None

def save(self, prefix: str, topic: str, state: SimCounterState):
def save(self, topic: str, state: SimCounterState):
pub.Pub().pub(topic + "simulation", vars(state))


def restore_last_energy(topic: str, value: str):
def restore_last_energy(topic: str, value: str, component_type: ComponentType):
try:
device_id = get_index(topic)
component_id = get_second_index(topic)
module_type = type_to_topic_mapping(
data.data.system_data[f"device{device_id}"].components[f"component{component_id}"].component_config.type)
module_type = type_to_topic_mapping(component_type)
module = getattr(data.data, f"{module_type}_data")[f"{module_type}{get_second_index(topic)}"].data.get
return getattr(module, value)
except AttributeError:
if (value == "imported" and
"inverter" in data.data.system_data[f"device{device_id}"].components[
f"component{component_id}"].component_config.type):
if (value == "imported" and component_type == ComponentType.INVERTER):
return 0
except ValueError:
# Wenn kein Index enthalten, ist es Hausverbrauch.
Expand All @@ -63,7 +42,3 @@ def restore_last_energy(topic: str, value: str):
return 0
elif value == "imported":
return data.data.counter_all_data.data.set.imported_home_consumption


def get_sim_counter_store() -> SimCounterStore:
return SimCounterStoreBroker()
1 change: 1 addition & 0 deletions packages/modules/common/store/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from modules.common.store._chargepoint import get_chargepoint_value_store
from modules.common.store._chargepoint_internal import get_internal_chargepoint_value_store
from modules.common.store._counter import get_counter_value_store
from modules.common.store._factory import get_component_value_store
from modules.common.store._inverter import get_inverter_value_store
from modules.common.store._io import get_io_value_store
from modules.common.store._tariff import get_flexible_tariff_value_store, get_grid_fee_value_store
Expand Down
5 changes: 3 additions & 2 deletions packages/modules/common/store/_counter_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from control.counter_all import CounterAll
from modules.chargepoints.mqtt.chargepoint_module import ChargepointModule
from modules.common.component_state import BatState, ChargepointState, CounterState, InverterState
from modules.common.component_type import ComponentType
from modules.common.simcount._simcounter import SimCounter
from modules.common.store import _counter
from modules.common.store._api import LoggingValueStore
Expand Down Expand Up @@ -129,7 +130,7 @@ def test_calc_virtual(params: Params, monkeypatch):
params.mock_data()
purge = PurgeCounterState(delegate=Mock(delegate=Mock(num=0)),
add_child_values=True,
simcounter=SimCounter(0, 0, prefix="bezug"))
simcounter=SimCounter(0, 0, ComponentType.COUNTER))
mock_comp_obj = Mock(side_effect=params.mock_comp)
monkeypatch.setattr(_counter, "get_component_obj_by_id", mock_comp_obj)

Expand Down Expand Up @@ -239,7 +240,7 @@ def mock_get_component_obj_by_id(component_id):
virtual_counter_purge = PurgeCounterState(
delegate=Mock(delegate=Mock(num=3)),
add_child_values=True,
simcounter=SimCounter(0, 0, prefix="virtual")
simcounter=SimCounter(0, 0, "counter")
)

# execution
Expand Down
18 changes: 18 additions & 0 deletions packages/modules/common/store/_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from typing import Optional
from modules.common.component_type import ComponentType
from modules.common.simcount._simcounter import SimCounter
from modules.common.store._battery import get_bat_value_store
from modules.common.store._counter import get_counter_value_store
from modules.common.store._inverter import get_inverter_value_store


def get_component_value_store(component_type: str,
component_num: int,
add_child_values: bool = False,
simcounter: Optional[SimCounter] = None):
if ComponentType.BAT.value in component_type:
return get_bat_value_store(component_num)
elif ComponentType.COUNTER.value in component_type:
return get_counter_value_store(component_num, add_child_values, simcounter)
elif ComponentType.INVERTER.value in component_type:
return get_inverter_value_store(component_num)
6 changes: 3 additions & 3 deletions packages/modules/devices/algodue/algodue/bat.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from modules.common.fault_state import ComponentInfo, FaultState
from modules.common.modbus import ModbusDataType
from modules.common.simcount import SimCounter
from modules.common.store import get_bat_value_store
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from modules.common.store import get_component_value_store


class KwargsDict(TypedDict):
Expand All @@ -29,8 +29,8 @@ def initialize(self) -> None:
self.__device_id: int = self.kwargs['device_id']
self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client']
self.__modbus_id: int = self.kwargs['modbus_id']
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher")
self.store = get_bat_value_store(self.component_config.id)
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, self.component_config.type)
self.store = get_component_value_store(self.component_config.type, self.component_config.id)
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state)

Expand Down
6 changes: 3 additions & 3 deletions packages/modules/devices/algodue/algodue/counter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from modules.common.fault_state import ComponentInfo, FaultState
from modules.common.modbus import ModbusDataType
from modules.common.simcount import SimCounter
from modules.common.store import get_counter_value_store
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from modules.common.store import get_component_value_store


class KwargsDict(TypedDict):
Expand All @@ -29,8 +29,8 @@ def initialize(self) -> None:
self.__device_id: int = self.kwargs['device_id']
self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client']
self.__modbus_id: int = self.kwargs['modbus_id']
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug")
self.store = get_counter_value_store(self.component_config.id)
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, self.component_config.type)
self.store = get_component_value_store(self.component_config.type, self.component_config.id)
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state)

Expand Down
6 changes: 3 additions & 3 deletions packages/modules/devices/algodue/algodue/inverter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from modules.common.fault_state import ComponentInfo, FaultState
from modules.common.modbus import ModbusDataType
from modules.common.simcount import SimCounter
from modules.common.store import get_inverter_value_store
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from modules.common.store import get_component_value_store


class KwargsDict(TypedDict):
Expand All @@ -29,8 +29,8 @@ def initialize(self) -> None:
self.__device_id: int = self.kwargs['device_id']
self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client']
self.__modbus_id: int = self.kwargs['modbus_id']
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv")
self.store = get_inverter_value_store(self.component_config.id)
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, self.component_config.type)
self.store = get_component_value_store(self.component_config.type, self.component_config.id)
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.peak_filter = PeakFilter(ComponentType.INVERTER, self.component_config.id, self.fault_state)

Expand Down
6 changes: 3 additions & 3 deletions packages/modules/devices/alpha_ess/alpha_ess/bat.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from modules.common.fault_state import ComponentInfo, FaultState
from modules.common.modbus import ModbusDataType, ModbusTcpClient_
from modules.common.simcount import SimCounter
from modules.common.store import get_bat_value_store
from modules.common.store import get_component_value_store
from modules.devices.alpha_ess.alpha_ess.config import AlphaEssBatSetup
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
Expand All @@ -29,8 +29,8 @@ def __init__(self, component_config: AlphaEssBatSetup, **kwargs: Any) -> None:
def initialize(self) -> None:
self.__tcp_client: ModbusTcpClient_ = self.kwargs['tcp_client']
self.__modbus_id: int = self.kwargs['modbus_id']
self.sim_counter = SimCounter(self.kwargs['device_id'], self.component_config.id, prefix="speicher")
self.store = get_bat_value_store(self.component_config.id)
self.sim_counter = SimCounter(self.kwargs['device_id'], self.component_config.id, self.component_config.type)
self.store = get_component_value_store(self.component_config.type, self.component_config.id)
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.peak_filter = PeakFilter(ComponentType.BAT, self.component_config.id, self.fault_state)
self.last_mode = 'Undefined'
Expand Down
4 changes: 2 additions & 2 deletions packages/modules/devices/alpha_ess/alpha_ess/counter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from modules.common.component_type import ComponentDescriptor
from modules.common.fault_state import ComponentInfo, FaultState
from modules.common.modbus import ModbusDataType
from modules.common.store import get_counter_value_store
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from modules.common.store import get_component_value_store


class KwargsDict(TypedDict):
Expand All @@ -29,7 +29,7 @@ def initialize(self) -> None:
self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client']
self.__device_config: AlphaEssConfiguration = self.kwargs['device_config']
self.__modbus_id: int = self.kwargs['modbus_id']
self.store = get_counter_value_store(self.component_config.id)
self.store = get_component_value_store(self.component_config.type, self.component_config.id)
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.peak_filter = PeakFilter(ComponentType.COUNTER, self.component_config.id, self.fault_state)

Expand Down
6 changes: 3 additions & 3 deletions packages/modules/devices/alpha_ess/alpha_ess/inverter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from modules.common.fault_state import ComponentInfo, FaultState
from modules.common.modbus import ModbusDataType, Number
from modules.common.simcount._simcounter import SimCounter
from modules.common.store import get_inverter_value_store
from modules.common.utils.peak_filter import PeakFilter
from modules.common.component_type import ComponentType
from modules.common.store import get_component_value_store


class KwargsDict(TypedDict):
Expand All @@ -31,8 +31,8 @@ def initialize(self) -> None:
self.__tcp_client: modbus.ModbusTcpClient_ = self.kwargs['tcp_client']
self.__device_config: AlphaEssConfiguration = self.kwargs['device_config']
self.__modbus_id: int = self.kwargs['modbus_id']
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv")
self.store = get_inverter_value_store(self.component_config.id)
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, self.component_config.type)
self.store = get_component_value_store(self.component_config.type, self.component_config.id)
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
self.peak_filter = PeakFilter(ComponentType.INVERTER, self.component_config.id, self.fault_state)

Expand Down
Loading
Loading