|
1 | 1 | import logging |
2 | 2 | from operator import add |
3 | | -from typing import Optional |
| 3 | +from typing import Dict, Optional |
4 | 4 |
|
5 | 5 | from control import data |
6 | 6 | from helpermodules import compatibility |
@@ -71,54 +71,101 @@ def calc_virtual(self, state: CounterState) -> CounterState: |
71 | 71 | if self.add_child_values: |
72 | 72 | self.currents = state.currents if state.currents else [0.0]*3 |
73 | 73 | self.power = state.power |
| 74 | + self.imported = state.imported if state.imported else 0 |
| 75 | + self.exported = state.exported if state.exported else 0 |
74 | 76 | self.incomplete_currents = False |
75 | | - |
76 | | - def add_current_power(element): |
77 | | - if hasattr(element, "currents") and element.currents is not None: |
78 | | - if sum(element.currents) == 0 and element.power != 0: |
79 | | - self.currents = [0, 0, 0] |
80 | | - self.incomplete_currents = True |
81 | | - else: |
82 | | - self.currents = list(map(add, self.currents, element.currents)) |
83 | | - else: |
84 | | - self.currents = [0, 0, 0] |
85 | | - self.incomplete_currents = True |
86 | | - self.power += element.power |
87 | | - |
88 | 77 | counter_all = data.data.counter_all_data |
89 | 78 | elements = counter_all.get_elements_for_downstream_calculation(self.delegate.delegate.num) |
90 | | - for element in elements: |
91 | | - try: |
92 | | - if element["type"] == ComponentType.CHARGEPOINT.value: |
93 | | - chargepoint = data.data.cp_data[f"cp{element['id']}"] |
94 | | - chargepoint_state = chargepoint.chargepoint_module.store.delegate.state |
95 | | - try: |
96 | | - self.currents = list(map(add, |
97 | | - self.currents, |
98 | | - convert_cp_currents_to_evu_currents( |
99 | | - chargepoint.data.config.phase_1, |
100 | | - chargepoint_state.currents))) |
101 | | - except KeyError: |
102 | | - raise KeyError("Für den virtuellen Zähler muss der Anschluss der Phasen von Ladepunkt" |
103 | | - f" {chargepoint.data.config.name} an die Phasen des EVU Zählers " |
104 | | - "angegeben werden.") |
105 | | - self.power += chargepoint_state.power |
106 | | - else: |
107 | | - component = get_component_obj_by_id(element['id']) |
108 | | - add_current_power(component.store.delegate.delegate.state) |
109 | | - except Exception: |
110 | | - log.exception(f"Fehler beim Hinzufügen der Werte für Element {element}") |
111 | | - |
112 | | - imported, exported = self.sim_counter.sim_count(self.power) |
113 | | - if self.incomplete_currents: |
114 | | - self.currents = None |
115 | | - return CounterState(currents=self.currents, |
116 | | - power=self.power, |
117 | | - exported=exported, |
118 | | - imported=imported) |
| 79 | + if len(elements) == 0: |
| 80 | + return self.calc_uncounted_consumption() |
| 81 | + else: |
| 82 | + return self.calc_consumers(elements) |
119 | 83 | else: |
120 | 84 | return state |
121 | 85 |
|
| 86 | + def _add_values(self, element, calc_imported_exported: bool): |
| 87 | + if hasattr(element, "currents") and element.currents is not None: |
| 88 | + if sum(element.currents) == 0 and element.power != 0: |
| 89 | + self.currents = [0, 0, 0] |
| 90 | + self.incomplete_currents = True |
| 91 | + else: |
| 92 | + self.currents = list(map(add, self.currents, element.currents)) |
| 93 | + else: |
| 94 | + self.currents = [0, 0, 0] |
| 95 | + self.incomplete_currents = True |
| 96 | + if calc_imported_exported: |
| 97 | + if hasattr(element, "imported") and element.imported is not None: |
| 98 | + self.imported += element.imported |
| 99 | + if hasattr(element, "exported") and element.exported is not None: |
| 100 | + self.exported += element.exported |
| 101 | + self.power += element.power |
| 102 | + |
| 103 | + def calc_consumers(self, elements: Dict, calc_imported_exported: bool = False) -> CounterState: |
| 104 | + for element in elements: |
| 105 | + try: |
| 106 | + if element["type"] == ComponentType.CHARGEPOINT.value: |
| 107 | + chargepoint = data.data.cp_data[f"cp{element['id']}"] |
| 108 | + chargepoint_state = chargepoint.chargepoint_module.store.delegate.state |
| 109 | + try: |
| 110 | + self.currents = list(map(add, |
| 111 | + self.currents, |
| 112 | + convert_cp_currents_to_evu_currents( |
| 113 | + chargepoint.data.config.phase_1, |
| 114 | + chargepoint_state.currents))) |
| 115 | + except KeyError: |
| 116 | + raise KeyError("Für den virtuellen Zähler muss der Anschluss der Phasen von Ladepunkt" |
| 117 | + f" {chargepoint.data.config.name} an die Phasen des EVU Zählers " |
| 118 | + "angegeben werden.") |
| 119 | + self.power += chargepoint_state.power |
| 120 | + if calc_imported_exported: |
| 121 | + self.imported += chargepoint_state.imported |
| 122 | + self.exported += chargepoint_state.exported |
| 123 | + else: |
| 124 | + component = get_component_obj_by_id(element['id']) |
| 125 | + self._add_values(component.store.delegate.delegate.state, calc_imported_exported) |
| 126 | + except Exception: |
| 127 | + log.exception(f"Fehler beim Hinzufügen der Werte für Element {element}") |
| 128 | + |
| 129 | + if calc_imported_exported is False or self.imported is None or self.exported is None: |
| 130 | + if self.imported is None and calc_imported_exported: |
| 131 | + log.debug("Mind eine Komponente liefert keinen Zählestand für den Bezug, berechne Zählerstände") |
| 132 | + if self.exported is None and calc_imported_exported: |
| 133 | + log.debug("Mind eine Komponente liefert keinen Zählestand für die Einspeisung, berechne Zählerstände") |
| 134 | + self.imported, self.exported = self.sim_counter.sim_count(self.power) |
| 135 | + if self.incomplete_currents: |
| 136 | + self.currents = None |
| 137 | + return CounterState(currents=self.currents, |
| 138 | + power=self.power, |
| 139 | + exported=self.exported, |
| 140 | + imported=self.imported) |
| 141 | + |
| 142 | + def calc_uncounted_consumption(self) -> CounterState: |
| 143 | + """Berechnet den nicht-gezählten Verbrauch für einen virtuellen Zähler. |
| 144 | + Dazu wird der Zählerstand des übergeordneten Zählers herangezogen und davon die |
| 145 | + Werte aller anderen untergeordneten Komponenten abgezogen.""" |
| 146 | + parent_id = data.data.counter_all_data.get_entry_of_parent(self.delegate.delegate.num)["id"] |
| 147 | + parent_component = get_component_obj_by_id(parent_id) |
| 148 | + if "counter" not in parent_component.component_config.type: |
| 149 | + raise Exception("Die übergeordnete Komponente des virtuellen Zählers muss ein Zähler sein.") |
| 150 | + if parent_component.store.add_child_values: |
| 151 | + raise Exception("Der übergeordnete Zähler des virtuellen Zählers darf nicht " |
| 152 | + "auch ein virtueller Zähler sein.") |
| 153 | + elements = data.data.counter_all_data.get_elements_for_downstream_calculation(parent_id) |
| 154 | + # entferne den eigenen Zähler aus der Liste |
| 155 | + elements = [el for el in elements if el["id"] != self.delegate.delegate.num] |
| 156 | + self.calc_consumers(elements, calc_imported_exported=True) |
| 157 | + log.debug(f"Erfasster Verbrauch virtueller Zähler {self.delegate.delegate.num}: " |
| 158 | + f"{self.currents}A, {self.power}W, {self.exported}Wh, {self.imported}Wh") |
| 159 | + parent_counter_get = data.data.counter_data[f"counter{parent_id}"].data.get |
| 160 | + return CounterState( |
| 161 | + currents=[parent_counter_get.currents[i] - self.currents[i] |
| 162 | + for i in range(0, 3)] if self.currents is not None else None, |
| 163 | + power=parent_counter_get.power - self.power, |
| 164 | + exported=0, |
| 165 | + imported=(parent_counter_get.imported + self.exported - self.imported - |
| 166 | + parent_counter_get.exported) if self.imported is not None else None |
| 167 | + ) |
| 168 | + |
122 | 169 |
|
123 | 170 | def get_counter_value_store(component_num: int, |
124 | 171 | add_child_values: bool = False, |
|
0 commit comments