Skip to content

Commit 13dadc8

Browse files
authored
Add component states and error codes (#44)
Add component state codes and error codes similar to #11
2 parents bfbb694 + dbc6d51 commit 13dadc8

File tree

3 files changed

+307
-2
lines changed

3 files changed

+307
-2
lines changed

RELEASE_NOTES.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ Update of the Pagination `Params` data class.
1010

1111
## New Features
1212

13-
* Additional information for energy metric
13+
* Additional information for energy metric.
14+
* Add component state codes.
15+
* Add component error codes.
1416

1517
## Bug Fixes
1618

src/frequenz/client/common/microgrid/components/__init__.py

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
from frequenz.api.common.v1.microgrid.components.components_pb2 import (
1111
ComponentCategory as PBComponentCategory,
1212
)
13+
from frequenz.api.common.v1.microgrid.components.components_pb2 import (
14+
ComponentErrorCode as PBComponentErrorCode,
15+
)
16+
from frequenz.api.common.v1.microgrid.components.components_pb2 import (
17+
ComponentStateCode as PBComponentStateCode,
18+
)
1319

1420
# pylint: enable=no-name-in-module
1521

@@ -65,3 +71,284 @@ def to_proto(self) -> PBComponentCategory.ValueType:
6571
Enum value corresponding to the protobuf message.
6672
"""
6773
return self.value
74+
75+
76+
class ComponentStateCode(Enum):
77+
"""All possible states of a microgrid component."""
78+
79+
UNSPECIFIED = PBComponentStateCode.COMPONENT_STATE_CODE_UNSPECIFIED
80+
"""Default value when the component state is not explicitly set."""
81+
82+
UNKNOWN = PBComponentStateCode.COMPONENT_STATE_CODE_UNKNOWN
83+
"""State when the component is in an unknown or undefined condition.
84+
85+
This is used when the sender is unable to classify the component into any
86+
other state.
87+
"""
88+
SWITCHING_OFF = PBComponentStateCode.COMPONENT_STATE_CODE_SWITCHING_OFF
89+
"""State when the component is in the process of switching off."""
90+
91+
OFF = PBComponentStateCode.COMPONENT_STATE_CODE_OFF
92+
"""State when the component has successfully switched off."""
93+
94+
SWITCHING_ON = PBComponentStateCode.COMPONENT_STATE_CODE_SWITCHING_ON
95+
"""State when the component is in the process of switching on from an off state."""
96+
97+
STANDBY = PBComponentStateCode.COMPONENT_STATE_CODE_STANDBY
98+
"""State when the component is in standby mode, and not immediately ready for operation."""
99+
100+
READY = PBComponentStateCode.COMPONENT_STATE_CODE_READY
101+
"""State when the component is fully operational and ready for use."""
102+
103+
CHARGING = PBComponentStateCode.COMPONENT_STATE_CODE_CHARGING
104+
"""State when the component is actively consuming energy."""
105+
106+
DISCHARGING = PBComponentStateCode.COMPONENT_STATE_CODE_DISCHARGING
107+
"""State when the component is actively producing or releasing energy."""
108+
109+
ERROR = PBComponentStateCode.COMPONENT_STATE_CODE_ERROR
110+
"""State when the component is in an error state and may need attention."""
111+
112+
EV_CHARGING_CABLE_UNPLUGGED = (
113+
PBComponentStateCode.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_UNPLUGGED
114+
)
115+
"""The Electric Vehicle (EV) charging cable is unplugged from the charging station."""
116+
117+
EV_CHARGING_CABLE_PLUGGED_AT_STATION = (
118+
PBComponentStateCode.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_STATION
119+
)
120+
"""The EV charging cable is plugged into the charging station."""
121+
122+
EV_CHARGING_CABLE_PLUGGED_AT_EV = (
123+
PBComponentStateCode.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_EV
124+
)
125+
"""The EV charging cable is plugged into the vehicle."""
126+
127+
EV_CHARGING_CABLE_LOCKED_AT_STATION = (
128+
PBComponentStateCode.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_STATION
129+
)
130+
"""The EV charging cable is locked at the charging station end, indicating
131+
readiness for charging."""
132+
133+
EV_CHARGING_CABLE_LOCKED_AT_EV = (
134+
PBComponentStateCode.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_EV
135+
)
136+
"""The EV charging cable is locked at the vehicle end, indicating that charging is active."""
137+
138+
RELAY_OPEN = PBComponentStateCode.COMPONENT_STATE_CODE_RELAY_OPEN
139+
"""The relay is in an open state, meaning no current can flow through."""
140+
141+
RELAY_CLOSED = PBComponentStateCode.COMPONENT_STATE_CODE_RELAY_CLOSED
142+
"""The relay is in a closed state, allowing current to flow."""
143+
144+
PRECHARGER_OPEN = PBComponentStateCode.COMPONENT_STATE_CODE_PRECHARGER_OPEN
145+
"""The precharger circuit is open, meaning it's not currently active."""
146+
147+
PRECHARGER_PRECHARGING = (
148+
PBComponentStateCode.COMPONENT_STATE_CODE_PRECHARGER_PRECHARGING
149+
)
150+
"""The precharger is in a precharging state, preparing the main circuit for activation."""
151+
152+
PRECHARGER_CLOSED = PBComponentStateCode.COMPONENT_STATE_CODE_PRECHARGER_CLOSED
153+
"""The precharger circuit is closed, allowing full current to flow to the main circuit."""
154+
155+
@classmethod
156+
def from_proto(
157+
cls, component_state: PBComponentStateCode.ValueType
158+
) -> ComponentStateCode:
159+
"""Convert a protobuf ComponentStateCode message to ComponentStateCode enum.
160+
161+
Args:
162+
component_state: protobuf enum to convert
163+
164+
Returns:
165+
Enum value corresponding to the protobuf message.
166+
"""
167+
if not any(c.value == component_state for c in ComponentStateCode):
168+
return ComponentStateCode.UNSPECIFIED
169+
return cls(component_state)
170+
171+
def to_proto(self) -> PBComponentStateCode.ValueType:
172+
"""Convert a ComponentStateCode enum to protobuf ComponentStateCode message.
173+
174+
Returns:
175+
Enum value corresponding to the protobuf message.
176+
"""
177+
return self.value
178+
179+
180+
class ComponentErrorCode(Enum):
181+
"""All possible errors that can occur across all microgrid component categories."""
182+
183+
UNSPECIFIED = PBComponentErrorCode.COMPONENT_ERROR_CODE_UNSPECIFIED
184+
"""Default value. No specific error is specified."""
185+
186+
UNKNOWN = PBComponentErrorCode.COMPONENT_ERROR_CODE_UNKNOWN
187+
"""The component is reporting an unknown or an undefined error, and the sender
188+
cannot parse the component error to any of the variants below."""
189+
190+
SWITCH_ON_FAULT = PBComponentErrorCode.COMPONENT_ERROR_CODE_SWITCH_ON_FAULT
191+
"""Error indicating that the component could not be switched on."""
192+
193+
UNDERVOLTAGE = PBComponentErrorCode.COMPONENT_ERROR_CODE_UNDERVOLTAGE
194+
"""Error indicating that the component is operating under the minimum rated
195+
voltage."""
196+
197+
OVERVOLTAGE = PBComponentErrorCode.COMPONENT_ERROR_CODE_OVERVOLTAGE
198+
"""Error indicating that the component is operating over the maximum rated
199+
voltage."""
200+
201+
OVERCURRENT = PBComponentErrorCode.COMPONENT_ERROR_CODE_OVERCURRENT
202+
"""Error indicating that the component is drawing more current than the
203+
maximum rated value."""
204+
205+
OVERCURRENT_CHARGING = (
206+
PBComponentErrorCode.COMPONENT_ERROR_CODE_OVERCURRENT_CHARGING
207+
)
208+
"""Error indicating that the component's consumption current is over the
209+
maximum rated value during charging."""
210+
211+
OVERCURRENT_DISCHARGING = (
212+
PBComponentErrorCode.COMPONENT_ERROR_CODE_OVERCURRENT_DISCHARGING
213+
)
214+
"""Error indicating that the component's production current is over the
215+
maximum rated value during discharging."""
216+
217+
OVERTEMPERATURE = PBComponentErrorCode.COMPONENT_ERROR_CODE_OVERTEMPERATURE
218+
"""Error indicating that the component is operating over the maximum rated
219+
temperature."""
220+
221+
UNDERTEMPERATURE = PBComponentErrorCode.COMPONENT_ERROR_CODE_UNDERTEMPERATURE
222+
"""Error indicating that the component is operating under the minimum rated
223+
temperature."""
224+
225+
HIGH_HUMIDITY = PBComponentErrorCode.COMPONENT_ERROR_CODE_HIGH_HUMIDITY
226+
"""Error indicating that the component is exposed to high humidity levels over
227+
the maximum rated value."""
228+
229+
FUSE_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_FUSE_ERROR
230+
"""Error indicating that the component's fuse has blown."""
231+
232+
PRECHARGE_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_PRECHARGE_ERROR
233+
"""Error indicating that the component's precharge unit has failed."""
234+
235+
PLAUSIBILITY_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_PLAUSIBILITY_ERROR
236+
"""Error indicating plausibility issues within the system involving this
237+
component."""
238+
239+
UNDERVOLTAGE_SHUTDOWN = (
240+
PBComponentErrorCode.COMPONENT_ERROR_CODE_UNDERVOLTAGE_SHUTDOWN
241+
)
242+
"""Error indicating system shutdown due to undervoltage involving this
243+
component."""
244+
245+
EV_UNEXPECTED_PILOT_FAILURE = (
246+
PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_UNEXPECTED_PILOT_FAILURE
247+
)
248+
"""Error indicating unexpected pilot failure in an electric vehicle (EV)
249+
component."""
250+
251+
FAULT_CURRENT = PBComponentErrorCode.COMPONENT_ERROR_CODE_FAULT_CURRENT
252+
"""Error indicating fault current detected in the component."""
253+
254+
SHORT_CIRCUIT = PBComponentErrorCode.COMPONENT_ERROR_CODE_SHORT_CIRCUIT
255+
"""Error indicating a short circuit detected in the component."""
256+
257+
CONFIG_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_CONFIG_ERROR
258+
"""Error indicating a configuration error related to the component."""
259+
260+
ILLEGAL_COMPONENT_STATE_CODE_REQUESTED = (
261+
PBComponentErrorCode.COMPONENT_ERROR_CODE_ILLEGAL_COMPONENT_STATE_CODE_REQUESTED
262+
)
263+
"""Error indicating an illegal state requested for the component."""
264+
265+
HARDWARE_INACCESSIBLE = (
266+
PBComponentErrorCode.COMPONENT_ERROR_CODE_HARDWARE_INACCESSIBLE
267+
)
268+
"""Error indicating that the hardware of the component is inaccessible."""
269+
270+
INTERNAL = PBComponentErrorCode.COMPONENT_ERROR_CODE_INTERNAL
271+
"""Error indicating an internal error within the component."""
272+
273+
UNAUTHORIZED = PBComponentErrorCode.COMPONENT_ERROR_CODE_UNAUTHORIZED
274+
"""Error indicating that the component is unauthorized to perform the
275+
last requested action."""
276+
277+
EV_CHARGING_CABLE_UNPLUGGED_FROM_STATION = (
278+
PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_STATION
279+
)
280+
"""Error indicating electric vehicle (EV) cable was abruptly unplugged from
281+
the charging station."""
282+
283+
EV_CHARGING_CABLE_UNPLUGGED_FROM_EV = (
284+
PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_EV
285+
)
286+
"""Error indicating electric vehicle (EV) cable was abruptly unplugged from
287+
the vehicle."""
288+
289+
EV_CHARGING_CABLE_LOCK_FAILED = (
290+
PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_LOCK_FAILED
291+
)
292+
"""Error indicating electric vehicle (EV) cable lock failure."""
293+
294+
EV_CHARGING_CABLE_INVALID = (
295+
PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_INVALID
296+
)
297+
"""Error indicating an invalid electric vehicle (EV) cable."""
298+
299+
EV_CONSUMER_INCOMPATIBLE = (
300+
PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_CONSUMER_INCOMPATIBLE
301+
)
302+
"""Error indicating an incompatible electric vehicle (EV) plug."""
303+
304+
BATTERY_IMBALANCE = PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_IMBALANCE
305+
"""Error indicating a battery system imbalance."""
306+
307+
BATTERY_LOW_SOH = PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_LOW_SOH
308+
"""Error indicating a low state of health (SOH) detected in the battery."""
309+
310+
BATTERY_BLOCK_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_BLOCK_ERROR
311+
"""Error indicating a battery block error."""
312+
313+
BATTERY_CONTROLLER_ERROR = (
314+
PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_CONTROLLER_ERROR
315+
)
316+
"""Error indicating a battery controller error."""
317+
318+
BATTERY_RELAY_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_RELAY_ERROR
319+
"""Error indicating a battery relay error."""
320+
321+
BATTERY_CALIBRATION_NEEDED = (
322+
PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_CALIBRATION_NEEDED
323+
)
324+
"""Error indicating that battery calibration is needed."""
325+
326+
RELAY_CYCLE_LIMIT_REACHED = (
327+
PBComponentErrorCode.COMPONENT_ERROR_CODE_RELAY_CYCLE_LIMIT_REACHED
328+
)
329+
"""Error indicating that the relays have been cycled for the maximum number of
330+
times."""
331+
332+
@classmethod
333+
def from_proto(
334+
cls, component_error_code: PBComponentErrorCode.ValueType
335+
) -> ComponentErrorCode:
336+
"""Convert a protobuf ComponentErrorCode message to ComponentErrorCode enum.
337+
338+
Args:
339+
component_error_code: protobuf enum to convert
340+
341+
Returns:
342+
Enum value corresponding to the protobuf message.
343+
"""
344+
if not any(c.value == component_error_code for c in ComponentErrorCode):
345+
return ComponentErrorCode.UNSPECIFIED
346+
return cls(component_error_code)
347+
348+
def to_proto(self) -> PBComponentErrorCode.ValueType:
349+
"""Convert a ComponentErrorCode enum to protobuf ComponentErrorCode message.
350+
351+
Returns:
352+
Enum value corresponding to the protobuf message.
353+
"""
354+
return self.value

tests/test_client_common.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,26 @@
33

44
"""Tests for the frequenz.client.common package."""
55

6-
from frequenz.client.common.microgrid.components import ComponentCategory
6+
from frequenz.client.common.microgrid.components import (
7+
ComponentCategory,
8+
ComponentErrorCode,
9+
ComponentStateCode,
10+
)
711

812

913
def test_components() -> None:
1014
"""Test the components."""
1115
for category in ComponentCategory:
1216
assert ComponentCategory.from_proto(category.to_proto()) == category
17+
18+
19+
def test_component_state_code() -> None:
20+
"""Test the component state code."""
21+
for state_code in ComponentStateCode:
22+
assert ComponentStateCode.from_proto(state_code.to_proto()) == state_code
23+
24+
25+
def test_component_error_code() -> None:
26+
"""Test the component error code."""
27+
for error_code in ComponentErrorCode:
28+
assert ComponentErrorCode.from_proto(error_code.to_proto()) == error_code

0 commit comments

Comments
 (0)