Skip to content

Commit 8656116

Browse files
committed
rewrite configuration
1 parent 0ead1f0 commit 8656116

7 files changed

Lines changed: 91 additions & 63 deletions

File tree

packages/control/io_device.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,10 @@ def ripple_control_receiver(self, device: Dict) -> float:
101101
else:
102102
return 1
103103

104-
def stepwise_control(self, device_id: int) -> Optional[str]:
104+
def stepwise_control(self, device_id: int) -> Optional[float]:
105105
for action in self.actions.values():
106106
if isinstance(action, StepwiseControl):
107-
if device_id == action.config.configuration.pv_id:
107+
if device_id in [component["id"] for component in action.config.configuration.devices]:
108108
self._check_fault_state_io_device(action.config.configuration.io_device)
109109
return action.control_stepwise()
110110
else:

packages/control/pv_all.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,13 @@ def calc_power_for_all_components(self) -> None:
6868
else:
6969
if fault_state < module_data.get.fault_state:
7070
fault_state = module_data.get.fault_state
71-
msg = data.data.io_actions.stepwise_control(data.data.pv_data[module].num)
72-
if msg is not None and data.data.pv_data[module].data.get.fault_state == 0:
71+
limit_value = data.data.io_actions.stepwise_control(data.data.pv_data[module].num)
72+
if limit_value is not None and data.data.pv_data[module].data.get.fault_state == 0:
73+
msg = (
74+
f"Leistung begrenzt auf {int(limit_value * 100)}%"
75+
if limit_value < 1
76+
else "Keine Leistungsbegrenzung aktiv."
77+
)
7378
data.data.pv_data[module].data.get.fault_str = msg
7479
Pub().pub(f"openWB/set/pv/{data.data.pv_data[module].num}/get/fault_str", msg)
7580
except Exception:

packages/dataclass_utils/factories.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def voltages_list_factory() -> List[float]:
1717
return [230.0]*3
1818

1919

20-
def empty_io_pattern_factory():
20+
def empty_io_pattern_boolean_factory():
2121
return [
2222
{
2323
"value": True, # dimmen
@@ -28,3 +28,20 @@ def empty_io_pattern_factory():
2828
"input_matrix": {}
2929
}
3030
]
31+
32+
33+
def empty_io_pattern_stepwise_factory():
34+
return [
35+
{
36+
"value": 0.6, # Stufe 1
37+
"input_matrix": {}
38+
},
39+
{
40+
"value": 0.3, # Stufe 2
41+
"input_matrix": {}
42+
},
43+
{
44+
"value": 0, # Stufe 3
45+
"input_matrix": {}
46+
}
47+
]

packages/modules/io_actions/controllable_consumers/dimming/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
from dataclasses import dataclass, field
22
from typing import Dict, List, Optional
3-
from dataclass_utils.factories import empty_io_pattern_factory, empty_list_factory
3+
from dataclass_utils.factories import empty_io_pattern_boolean_factory, empty_list_factory
44
from modules.io_actions.groups import ActionGroup
55

66

77
@dataclass
88
class DimmingConfig:
99
io_device: Optional[int] = None
10-
input_pattern: List[Dict] = field(default_factory=empty_io_pattern_factory)
10+
input_pattern: List[Dict] = field(default_factory=empty_io_pattern_boolean_factory)
1111
devices: List[Dict] = field(default_factory=empty_list_factory)
1212
# [{"type": "cp", "id": 0},
1313
# {"type": "io", "id": 1, "digital_output": "SofortLa"}]

packages/modules/io_actions/controllable_consumers/dimming_direct_control/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
from dataclasses import dataclass, field
22
from typing import Dict, List, Optional
3-
from dataclass_utils.factories import empty_io_pattern_factory, empty_list_factory
3+
from dataclass_utils.factories import empty_io_pattern_boolean_factory, empty_list_factory
44
from modules.io_actions.groups import ActionGroup
55

66

77
@dataclass
88
class DimmingDirectControlConfig:
99
io_device: Optional[int] = None
10-
input_pattern: List[Dict] = field(default_factory=empty_io_pattern_factory)
10+
input_pattern: List[Dict] = field(default_factory=empty_io_pattern_boolean_factory)
1111
devices: List[Dict] = field(default_factory=empty_list_factory)
1212
# [{"type": "cp", "id": 0},
1313
# {"type": "io", "id": 1, "digital_output": "SofortLa"}]

packages/modules/io_actions/generator_systems/stepwise_control/api.py

Lines changed: 53 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import logging
2-
from control import data
32
from typing import Optional
3+
from control import data
44
from helpermodules.logger import ModifyLoglevelContext
5+
from helpermodules.pub import Pub
6+
from helpermodules.timecheck import create_timestamp
57
from modules.common.abstract_device import DeviceDescriptor
68
from modules.common.abstract_io import AbstractIoAction
7-
from modules.common.utils.component_parser import get_component_name_by_id
89
from modules.io_actions.generator_systems.stepwise_control.config import StepwiseControlSetup
910

1011
control_command_log = logging.getLogger("steuve_control_command")
@@ -13,57 +14,62 @@
1314
class StepwiseControl(AbstractIoAction):
1415
def __init__(self, config: StepwiseControlSetup):
1516
self.config = config
16-
control_command_log.info(f"Stufenweise Steuerung einer EZA: Eingang {self.config.configuration.s1} für S1, "
17-
f"Eingang {self.config.configuration.s2} für S2, und Eingang "
18-
f"{self.config.configuration.w3} für W3 wird überwacht. Die Beschränkung muss in "
19-
"der EZA vorgenommen werden.")
17+
self.__unique_inputs = []
18+
for pattern in self.config.configuration.input_pattern:
19+
for key in pattern["input_matrix"].keys():
20+
if key not in self.__unique_inputs:
21+
self.__unique_inputs.append(key)
22+
assigned_devices = [io_device["id"] for io_device in self.config.configuration.devices]
23+
control_command_log.info(
24+
f"Stufenweise Steuerung von EZA: I/O-Gerät: {self.config.configuration.io_device}, "
25+
f"Überwachte digitale Eingänge: {self.__unique_inputs}, "
26+
f"zugeordnete Erzeugungsanlagen: {assigned_devices} "
27+
"Die Begrenzung muss in den EZA vorgenommen werden!"
28+
)
2029
super().__init__()
2130

2231
def setup(self) -> None:
23-
pass
24-
25-
def control_stepwise(self) -> Optional[str]:
26-
text = (f"Die Einspeiseleistung von {get_component_name_by_id(self.config.configuration.pv_id)} ist auf "
27-
"{} % beschränkt. Die Beschränkung muss in der EZA vorgenommen werden.")
28-
msg = None
29-
digital_input = data.data.io_states[f"io_states{self.config.configuration.io_device}"].data.get.digital_input
30-
digital_input_prev = data.data.io_states[
31-
f"io_states{self.config.configuration.io_device}"].data.get.digital_input_prev
32+
with ModifyLoglevelContext(control_command_log, logging.DEBUG):
33+
digital_input = (
34+
data.data.io_states[
35+
f"io_states{self.config.configuration.io_device}"
36+
].data.get.digital_input
37+
)
38+
digital_input_prev = data.data.io_states[
39+
f"io_states{self.config.configuration.io_device}"].data.get.digital_input_prev
40+
changed = len([
41+
input_name for input_name in self.__unique_inputs
42+
if digital_input[input_name] != digital_input_prev[input_name]
43+
]) > 0
3244

33-
active_inputs = [
34-
digital_input[self.config.configuration.s1],
35-
digital_input[self.config.configuration.s2],
36-
digital_input[self.config.configuration.w3]
37-
]
38-
num_active = sum(1 for v in active_inputs if v)
45+
for pattern in self.config.configuration.input_pattern:
46+
for action_input, value in pattern["input_matrix"].items():
47+
if digital_input[action_input] != value:
48+
break
49+
else:
50+
# Alle digitalen Eingänge entsprechen dem Pattern
51+
if pattern["value"] != 1:
52+
if changed:
53+
Pub().pub(f"openWB/set/io/action/{self.config.id}/timestamp", create_timestamp())
54+
control_command_log.info(f"EZA-Begrenzung mit Wert {int(pattern['value']*100)}% aktiviert.")
55+
break
56+
else:
57+
if changed:
58+
Pub().pub(f"openWB/set/io/action/{self.config.id}/timestamp", None)
59+
control_command_log.info("EZA-Begrenzung aufgehoben.")
3960

40-
if num_active > 1:
41-
error_msg = (f"Fehler: Mehr als ein Eingang ist aktiv für die stufenweise Steuerung der EZA! "
42-
f"S1: {digital_input[self.config.configuration.s1]}, "
43-
f"S2: {digital_input[self.config.configuration.s2]}, "
44-
f"W3: {digital_input[self.config.configuration.w3]}")
45-
with ModifyLoglevelContext(control_command_log, logging.ERROR):
46-
control_command_log.error(error_msg)
47-
raise ValueError(error_msg)
48-
49-
if digital_input[self.config.configuration.s1]:
50-
msg = text.format(60)
51-
elif digital_input[self.config.configuration.s2]:
52-
msg = text.format(30)
53-
elif digital_input[self.config.configuration.w3]:
54-
msg = text.format(0)
61+
def control_stepwise(self) -> Optional[float]:
62+
for pattern in self.config.configuration.input_pattern:
63+
for digital_input, value in pattern["input_matrix"].items():
64+
if data.data.io_states[f"io_states{self.config.configuration.io_device}"
65+
].data.get.digital_input[digital_input] != value:
66+
break
67+
else:
68+
# Alle digitalen Eingänge entsprechen dem Pattern
69+
return pattern['value']
5570
else:
56-
# Keine Beschränkung soll nicht dauerhaft im WR angezeigt werden.
57-
msg = (f"Die Einspeiseleistung von {get_component_name_by_id(self.config.configuration.pv_id)} ist "
58-
"nicht beschränkt. Die Beschränkung muss in der EZA vorgenommen werden.")
59-
60-
if not (digital_input[self.config.configuration.s1] == digital_input_prev[self.config.configuration.s1] and
61-
digital_input[self.config.configuration.s2] == digital_input_prev[self.config.configuration.s2] and
62-
digital_input[self.config.configuration.w3] == digital_input_prev[self.config.configuration.w3]):
63-
# Wenn sich was geändert hat, loggen
64-
with ModifyLoglevelContext(control_command_log, logging.DEBUG):
65-
control_command_log.info(msg)
66-
return msg
71+
# Zustand entspricht keinem Pattern, Leistungsbegrenzung aufheben
72+
return 1
6773

6874

6975
def create_action(config: StepwiseControlSetup):

packages/modules/io_actions/generator_systems/stepwise_control/config.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
from dataclasses import dataclass
2-
from typing import Optional
1+
from dataclasses import dataclass, field
2+
from typing import Dict, List, Optional
3+
from dataclass_utils.factories import empty_list_factory, empty_io_pattern_stepwise_factory
34
from modules.io_actions.groups import ActionGroup
45

56

67
@dataclass
78
class StepwiseControlConfig:
89
io_device: Optional[int] = None
9-
s1: str = None
10-
s2: str = None
11-
w3: str = None
12-
pv_id: int = None
10+
input_pattern: List[Dict] = field(default_factory=empty_io_pattern_stepwise_factory)
11+
devices: List[Dict] = field(default_factory=empty_list_factory)
12+
# [{"type": "inverter", "id": 1},...]
1313

1414

1515
class StepwiseControlSetup:
1616
def __init__(self,
17-
name: str = "Stufenweise Steuerung einer EZA",
17+
name: str = "Stufenweise Steuerung von EZA",
1818
type: str = "stepwise_control",
1919
id: int = 0,
2020
configuration: StepwiseControlConfig = None):

0 commit comments

Comments
 (0)