diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 3cb68666..7b5e6079 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -7,6 +7,9 @@ ## Upgrading - The `typing-extensions` dependency minimum version was bumped to 4.6 to support Python 3.12. +- Changed the dependency reference for frequenz-api-common +- Renamed the old components module since it is replaced by electrical_components +- Updated tests to use the new electrical_components enums ## New Features diff --git a/pyproject.toml b/pyproject.toml index 9d1a52f9..2d0dc841 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ classifiers = [ requires-python = ">= 3.11, < 4" dependencies = [ "typing-extensions >= 4.6.0, < 5", - "frequenz-api-common >= 0.6.0, < 7", + "frequenz-api-common @ git+https://github.com/frequenz-floss/frequenz-api-common.git@2e89add6a16d42b23612f0f791a499919f3738ed", ] dynamic = ["version"] @@ -144,7 +144,7 @@ disable = [ ] [tool.pytest.ini_options] -addopts = "-W=all -Werror -Wdefault::DeprecationWarning -Wdefault::PendingDeprecationWarning '-Wdefault:Protobuf gencode version 5.27.2 is exactly one major version older than the runtime version:UserWarning' -vv" +addopts = "-W=all -Werror -Wdefault::DeprecationWarning -Wdefault::PendingDeprecationWarning '-Wdefault:Protobuf gencode version 5.29.0 is exactly one major version older than the runtime version:UserWarning' -vv" testpaths = ["tests", "src"] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" diff --git a/src/frequenz/client/common/microgrid/components/__init__.py b/src/frequenz/client/common/microgrid/components/__init__.py deleted file mode 100644 index 013c26af..00000000 --- a/src/frequenz/client/common/microgrid/components/__init__.py +++ /dev/null @@ -1,354 +0,0 @@ -# License: MIT -# Copyright © 2022 Frequenz Energy-as-a-Service GmbH - -"""Defines the components that can be used in a microgrid.""" -from __future__ import annotations - -from enum import Enum - -# pylint: disable=no-name-in-module -from frequenz.api.common.v1.microgrid.components.components_pb2 import ( - ComponentCategory as PBComponentCategory, -) -from frequenz.api.common.v1.microgrid.components.components_pb2 import ( - ComponentErrorCode as PBComponentErrorCode, -) -from frequenz.api.common.v1.microgrid.components.components_pb2 import ( - ComponentStateCode as PBComponentStateCode, -) - -# pylint: enable=no-name-in-module - - -class ComponentCategory(Enum): - """Possible types of microgrid component.""" - - UNSPECIFIED = PBComponentCategory.COMPONENT_CATEGORY_UNSPECIFIED - """An unknown component category. - - Useful for error handling, and marking unknown components in - a list of components with otherwise known categories. - """ - - GRID = PBComponentCategory.COMPONENT_CATEGORY_GRID - """The point where the local microgrid is connected to the grid.""" - - METER = PBComponentCategory.COMPONENT_CATEGORY_METER - """A meter, for measuring electrical metrics, e.g., current, voltage, etc.""" - - INVERTER = PBComponentCategory.COMPONENT_CATEGORY_INVERTER - """An electricity generator, with batteries or solar energy.""" - - BATTERY = PBComponentCategory.COMPONENT_CATEGORY_BATTERY - """A storage system for electrical energy, used by inverters.""" - - EV_CHARGER = PBComponentCategory.COMPONENT_CATEGORY_EV_CHARGER - """A station for charging electrical vehicles.""" - - CHP = PBComponentCategory.COMPONENT_CATEGORY_CHP - """A heat and power combustion plant (CHP stands for combined heat and power).""" - - @classmethod - def from_proto( - cls, component_category: PBComponentCategory.ValueType - ) -> ComponentCategory: - """Convert a protobuf ComponentCategory message to ComponentCategory enum. - - Args: - component_category: protobuf enum to convert - - Returns: - Enum value corresponding to the protobuf message. - """ - if not any(t.value == component_category for t in ComponentCategory): - return ComponentCategory.UNSPECIFIED - return cls(component_category) - - def to_proto(self) -> PBComponentCategory.ValueType: - """Convert a ComponentCategory enum to protobuf ComponentCategory message. - - Returns: - Enum value corresponding to the protobuf message. - """ - return self.value - - -class ComponentStateCode(Enum): - """All possible states of a microgrid component.""" - - UNSPECIFIED = PBComponentStateCode.COMPONENT_STATE_CODE_UNSPECIFIED - """Default value when the component state is not explicitly set.""" - - UNKNOWN = PBComponentStateCode.COMPONENT_STATE_CODE_UNKNOWN - """State when the component is in an unknown or undefined condition. - - This is used when the sender is unable to classify the component into any - other state. - """ - SWITCHING_OFF = PBComponentStateCode.COMPONENT_STATE_CODE_SWITCHING_OFF - """State when the component is in the process of switching off.""" - - OFF = PBComponentStateCode.COMPONENT_STATE_CODE_OFF - """State when the component has successfully switched off.""" - - SWITCHING_ON = PBComponentStateCode.COMPONENT_STATE_CODE_SWITCHING_ON - """State when the component is in the process of switching on from an off state.""" - - STANDBY = PBComponentStateCode.COMPONENT_STATE_CODE_STANDBY - """State when the component is in standby mode, and not immediately ready for operation.""" - - READY = PBComponentStateCode.COMPONENT_STATE_CODE_READY - """State when the component is fully operational and ready for use.""" - - CHARGING = PBComponentStateCode.COMPONENT_STATE_CODE_CHARGING - """State when the component is actively consuming energy.""" - - DISCHARGING = PBComponentStateCode.COMPONENT_STATE_CODE_DISCHARGING - """State when the component is actively producing or releasing energy.""" - - ERROR = PBComponentStateCode.COMPONENT_STATE_CODE_ERROR - """State when the component is in an error state and may need attention.""" - - EV_CHARGING_CABLE_UNPLUGGED = ( - PBComponentStateCode.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_UNPLUGGED - ) - """The Electric Vehicle (EV) charging cable is unplugged from the charging station.""" - - EV_CHARGING_CABLE_PLUGGED_AT_STATION = ( - PBComponentStateCode.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_STATION - ) - """The EV charging cable is plugged into the charging station.""" - - EV_CHARGING_CABLE_PLUGGED_AT_EV = ( - PBComponentStateCode.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_EV - ) - """The EV charging cable is plugged into the vehicle.""" - - EV_CHARGING_CABLE_LOCKED_AT_STATION = ( - PBComponentStateCode.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_STATION - ) - """The EV charging cable is locked at the charging station end, indicating - readiness for charging.""" - - EV_CHARGING_CABLE_LOCKED_AT_EV = ( - PBComponentStateCode.COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_EV - ) - """The EV charging cable is locked at the vehicle end, indicating that charging is active.""" - - RELAY_OPEN = PBComponentStateCode.COMPONENT_STATE_CODE_RELAY_OPEN - """The relay is in an open state, meaning no current can flow through.""" - - RELAY_CLOSED = PBComponentStateCode.COMPONENT_STATE_CODE_RELAY_CLOSED - """The relay is in a closed state, allowing current to flow.""" - - PRECHARGER_OPEN = PBComponentStateCode.COMPONENT_STATE_CODE_PRECHARGER_OPEN - """The precharger circuit is open, meaning it's not currently active.""" - - PRECHARGER_PRECHARGING = ( - PBComponentStateCode.COMPONENT_STATE_CODE_PRECHARGER_PRECHARGING - ) - """The precharger is in a precharging state, preparing the main circuit for activation.""" - - PRECHARGER_CLOSED = PBComponentStateCode.COMPONENT_STATE_CODE_PRECHARGER_CLOSED - """The precharger circuit is closed, allowing full current to flow to the main circuit.""" - - @classmethod - def from_proto( - cls, component_state: PBComponentStateCode.ValueType - ) -> ComponentStateCode: - """Convert a protobuf ComponentStateCode message to ComponentStateCode enum. - - Args: - component_state: protobuf enum to convert - - Returns: - Enum value corresponding to the protobuf message. - """ - if not any(c.value == component_state for c in ComponentStateCode): - return ComponentStateCode.UNSPECIFIED - return cls(component_state) - - def to_proto(self) -> PBComponentStateCode.ValueType: - """Convert a ComponentStateCode enum to protobuf ComponentStateCode message. - - Returns: - Enum value corresponding to the protobuf message. - """ - return self.value - - -class ComponentErrorCode(Enum): - """All possible errors that can occur across all microgrid component categories.""" - - UNSPECIFIED = PBComponentErrorCode.COMPONENT_ERROR_CODE_UNSPECIFIED - """Default value. No specific error is specified.""" - - UNKNOWN = PBComponentErrorCode.COMPONENT_ERROR_CODE_UNKNOWN - """The component is reporting an unknown or an undefined error, and the sender - cannot parse the component error to any of the variants below.""" - - SWITCH_ON_FAULT = PBComponentErrorCode.COMPONENT_ERROR_CODE_SWITCH_ON_FAULT - """Error indicating that the component could not be switched on.""" - - UNDERVOLTAGE = PBComponentErrorCode.COMPONENT_ERROR_CODE_UNDERVOLTAGE - """Error indicating that the component is operating under the minimum rated - voltage.""" - - OVERVOLTAGE = PBComponentErrorCode.COMPONENT_ERROR_CODE_OVERVOLTAGE - """Error indicating that the component is operating over the maximum rated - voltage.""" - - OVERCURRENT = PBComponentErrorCode.COMPONENT_ERROR_CODE_OVERCURRENT - """Error indicating that the component is drawing more current than the - maximum rated value.""" - - OVERCURRENT_CHARGING = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_OVERCURRENT_CHARGING - ) - """Error indicating that the component's consumption current is over the - maximum rated value during charging.""" - - OVERCURRENT_DISCHARGING = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_OVERCURRENT_DISCHARGING - ) - """Error indicating that the component's production current is over the - maximum rated value during discharging.""" - - OVERTEMPERATURE = PBComponentErrorCode.COMPONENT_ERROR_CODE_OVERTEMPERATURE - """Error indicating that the component is operating over the maximum rated - temperature.""" - - UNDERTEMPERATURE = PBComponentErrorCode.COMPONENT_ERROR_CODE_UNDERTEMPERATURE - """Error indicating that the component is operating under the minimum rated - temperature.""" - - HIGH_HUMIDITY = PBComponentErrorCode.COMPONENT_ERROR_CODE_HIGH_HUMIDITY - """Error indicating that the component is exposed to high humidity levels over - the maximum rated value.""" - - FUSE_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_FUSE_ERROR - """Error indicating that the component's fuse has blown.""" - - PRECHARGE_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_PRECHARGE_ERROR - """Error indicating that the component's precharge unit has failed.""" - - PLAUSIBILITY_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_PLAUSIBILITY_ERROR - """Error indicating plausibility issues within the system involving this - component.""" - - UNDERVOLTAGE_SHUTDOWN = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_UNDERVOLTAGE_SHUTDOWN - ) - """Error indicating system shutdown due to undervoltage involving this - component.""" - - EV_UNEXPECTED_PILOT_FAILURE = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_UNEXPECTED_PILOT_FAILURE - ) - """Error indicating unexpected pilot failure in an electric vehicle (EV) - component.""" - - FAULT_CURRENT = PBComponentErrorCode.COMPONENT_ERROR_CODE_FAULT_CURRENT - """Error indicating fault current detected in the component.""" - - SHORT_CIRCUIT = PBComponentErrorCode.COMPONENT_ERROR_CODE_SHORT_CIRCUIT - """Error indicating a short circuit detected in the component.""" - - CONFIG_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_CONFIG_ERROR - """Error indicating a configuration error related to the component.""" - - ILLEGAL_COMPONENT_STATE_CODE_REQUESTED = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_ILLEGAL_COMPONENT_STATE_CODE_REQUESTED - ) - """Error indicating an illegal state requested for the component.""" - - HARDWARE_INACCESSIBLE = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_HARDWARE_INACCESSIBLE - ) - """Error indicating that the hardware of the component is inaccessible.""" - - INTERNAL = PBComponentErrorCode.COMPONENT_ERROR_CODE_INTERNAL - """Error indicating an internal error within the component.""" - - UNAUTHORIZED = PBComponentErrorCode.COMPONENT_ERROR_CODE_UNAUTHORIZED - """Error indicating that the component is unauthorized to perform the - last requested action.""" - - EV_CHARGING_CABLE_UNPLUGGED_FROM_STATION = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_STATION - ) - """Error indicating electric vehicle (EV) cable was abruptly unplugged from - the charging station.""" - - EV_CHARGING_CABLE_UNPLUGGED_FROM_EV = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_EV - ) - """Error indicating electric vehicle (EV) cable was abruptly unplugged from - the vehicle.""" - - EV_CHARGING_CABLE_LOCK_FAILED = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_LOCK_FAILED - ) - """Error indicating electric vehicle (EV) cable lock failure.""" - - EV_CHARGING_CABLE_INVALID = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_CHARGING_CABLE_INVALID - ) - """Error indicating an invalid electric vehicle (EV) cable.""" - - EV_CONSUMER_INCOMPATIBLE = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_EV_CONSUMER_INCOMPATIBLE - ) - """Error indicating an incompatible electric vehicle (EV) plug.""" - - BATTERY_IMBALANCE = PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_IMBALANCE - """Error indicating a battery system imbalance.""" - - BATTERY_LOW_SOH = PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_LOW_SOH - """Error indicating a low state of health (SOH) detected in the battery.""" - - BATTERY_BLOCK_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_BLOCK_ERROR - """Error indicating a battery block error.""" - - BATTERY_CONTROLLER_ERROR = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_CONTROLLER_ERROR - ) - """Error indicating a battery controller error.""" - - BATTERY_RELAY_ERROR = PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_RELAY_ERROR - """Error indicating a battery relay error.""" - - BATTERY_CALIBRATION_NEEDED = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_BATTERY_CALIBRATION_NEEDED - ) - """Error indicating that battery calibration is needed.""" - - RELAY_CYCLE_LIMIT_REACHED = ( - PBComponentErrorCode.COMPONENT_ERROR_CODE_RELAY_CYCLE_LIMIT_REACHED - ) - """Error indicating that the relays have been cycled for the maximum number of - times.""" - - @classmethod - def from_proto( - cls, component_error_code: PBComponentErrorCode.ValueType - ) -> ComponentErrorCode: - """Convert a protobuf ComponentErrorCode message to ComponentErrorCode enum. - - Args: - component_error_code: protobuf enum to convert - - Returns: - Enum value corresponding to the protobuf message. - """ - if not any(c.value == component_error_code for c in ComponentErrorCode): - return ComponentErrorCode.UNSPECIFIED - return cls(component_error_code) - - def to_proto(self) -> PBComponentErrorCode.ValueType: - """Convert a ComponentErrorCode enum to protobuf ComponentErrorCode message. - - Returns: - Enum value corresponding to the protobuf message. - """ - return self.value diff --git a/src/frequenz/client/common/microgrid/electrical_components/__init__.py b/src/frequenz/client/common/microgrid/electrical_components/__init__.py new file mode 100644 index 00000000..4110a0d9 --- /dev/null +++ b/src/frequenz/client/common/microgrid/electrical_components/__init__.py @@ -0,0 +1,452 @@ +# License: MIT +# Copyright © 2022 Frequenz Energy-as-a-Service GmbH + +"""Defines the electrical components that can be used in a microgrid.""" +from __future__ import annotations + +from enum import Enum + +# pylint: disable=no-name-in-module +from frequenz.api.common.v1.microgrid.electrical_components.electrical_components_pb2 import ( + ElectricalComponentCategory as PBElectricalComponentCategory, +) +from frequenz.api.common.v1.microgrid.electrical_components.electrical_components_pb2 import ( + ElectricalComponentDiagnosticCode as PBElectricalComponentDiagnosticCode, +) +from frequenz.api.common.v1.microgrid.electrical_components.electrical_components_pb2 import ( + ElectricalComponentStateCode as PBElectricalComponentStateCode, +) + +# pylint: enable=no-name-in-module + + +class ElectricalComponentCategory(Enum): + """Possible types of microgrid electrical component.""" + + UNSPECIFIED = ( + PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_UNSPECIFIED + ) + """An unknown component category. + + Useful for error handling, and marking unknown components in + a list of components with otherwise known categories. + """ + + GRID = PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_GRID + """The point where the local microgrid is connected to the grid.""" + + METER = PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_METER + """A meter, for measuring electrical metrics, e.g., current, voltage, etc.""" + + INVERTER = PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_INVERTER + """An electricity generator, with batteries or solar energy.""" + + CONVERTER = PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_CONVERTER + """An electricity converter, e.g., a DC-DC converter.""" + + BATTERY = PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_BATTERY + """A storage system for electrical energy, used by inverters.""" + + EV_CHARGER = PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_EV_CHARGER + """A station for charging electrical vehicles.""" + + CRYPTO_MINER = ( + PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_CRYPTO_MINER + ) + """A device for mining cryptocurrencies.""" + + ELECTROLYZER = ( + PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_ELECTROLYZER + ) + """A device for splitting water into hydrogen and oxygen using electricity.""" + + CHP = PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_CHP + """A heat and power combustion plant (CHP stands for combined heat and power).""" + + RELAY = PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_RELAY + """A relay, used for switching electrical circuits on and off.""" + + PRECHARGER = PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_PRECHARGER + """A precharger, used for preparing electrical circuits for switching on.""" + + FUSE = PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_FUSE + """A fuse, used for protecting electrical circuits from overcurrent.""" + + TRANSFORMER = ( + PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_VOLTAGE_TRANSFORMER + ) + """A transformer, used for changing the voltage of electrical circuits.""" + + HVAC = PBElectricalComponentCategory.ELECTRICAL_COMPONENT_CATEGORY_HVAC + """A heating, ventilation, and air conditioning (HVAC) system.""" + + @classmethod + def from_proto( + cls, component_category: PBElectricalComponentCategory.ValueType + ) -> ElectricalComponentCategory: + """Convert a protobuf ElectricalComponentCategory message to enum. + + Args: + component_category: protobuf enum to convert + + Returns: + Enum value corresponding to the protobuf message. + """ + if not any(t.value == component_category for t in ElectricalComponentCategory): + return ElectricalComponentCategory.UNSPECIFIED + return cls(component_category) + + def to_proto(self) -> PBElectricalComponentCategory.ValueType: + """Convert a ElectricalComponentCategory enum to protobuf message. + + Returns: + Enum value corresponding to the protobuf message. + """ + return self.value + + +class ElectricalComponentStateCode(Enum): + """All possible states of a microgrid electrical component.""" + + UNSPECIFIED = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_UNSPECIFIED + ) + """Default value when the component state is not explicitly set.""" + + UNKNOWN = PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_UNKNOWN + """State when the component is in an unknown or undefined condition. + + This is used when the sender is unable to classify the component into any + other state. + """ + + UNAVAILABLE = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_UNAVAILABLE + ) + """State when the component is not available for use.""" + + SWITCHING_OFF = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_SWITCHING_OFF + ) + """State when the component is in the process of switching off.""" + + OFF = PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_OFF + """State when the component has successfully switched off.""" + + SWITCHING_ON = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_SWITCHING_ON + ) + """State when the component is in the process of switching on from an off state.""" + + STANDBY = PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_STANDBY + """State when the component is in standby mode, and not immediately ready for operation.""" + + READY = PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_READY + """State when the component is fully operational and ready for use.""" + + CHARGING = PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_CHARGING + """State when the component is actively consuming energy.""" + + DISCHARGING = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_DISCHARGING + ) + """State when the component is actively producing or releasing energy.""" + + ERROR = PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_ERROR + """State when the component is in an error state and may need attention.""" + + EV_CHARGING_CABLE_UNPLUGGED = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_EV_CHARGING_CABLE_UNPLUGGED + ) + """The Electric Vehicle (EV) charging cable is unplugged from the charging station.""" + + EV_CHARGING_CABLE_PLUGGED_AT_STATION = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_STATION # noqa: E501 + ) + """The EV charging cable is plugged into the charging station.""" + + EV_CHARGING_CABLE_PLUGGED_AT_EV = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_EV_CHARGING_CABLE_PLUGGED_AT_EV # noqa: E501 + ) + """The EV charging cable is plugged into the vehicle.""" + + EV_CHARGING_CABLE_LOCKED_AT_STATION = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_STATION # noqa: E501 + ) + """The EV charging cable is locked at the charging station end, indicating + readiness for charging.""" + + EV_CHARGING_CABLE_LOCKED_AT_EV = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_EV_CHARGING_CABLE_LOCKED_AT_EV # noqa: E501 + ) + """The EV charging cable is locked at the vehicle end, indicating that charging is active.""" + + RELAY_OPEN = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_RELAY_OPEN + ) + """The relay is in an open state, meaning no current can flow through.""" + + RELAY_CLOSED = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_RELAY_CLOSED + ) + """The relay is in a closed state, allowing current to flow.""" + + PRECHARGER_OPEN = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_PRECHARGER_OPEN + ) + """The precharger circuit is open, meaning it's not currently active.""" + + PRECHARGER_PRECHARGING = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_PRECHARGER_PRECHARGING + ) + """The precharger is in a precharging state, preparing the main circuit for activation.""" + + PRECHARGER_CLOSED = ( + PBElectricalComponentStateCode.ELECTRICAL_COMPONENT_STATE_CODE_PRECHARGER_CLOSED + ) + """The precharger circuit is closed, allowing full current to flow to the main circuit.""" + + @classmethod + def from_proto( + cls, component_state: PBElectricalComponentStateCode.ValueType + ) -> ElectricalComponentStateCode: + """Convert a protobuf ElectricalComponentStateCode message to enum. + + Args: + component_state: protobuf enum to convert + + Returns: + Enum value corresponding to the protobuf message. + """ + if not any(c.value == component_state for c in ElectricalComponentStateCode): + return ElectricalComponentStateCode.UNSPECIFIED + return cls(component_state) + + def to_proto(self) -> PBElectricalComponentStateCode.ValueType: + """Convert a ElectricalComponentStateCode enum to protobuf message. + + Returns: + Enum value corresponding to the protobuf message. + """ + return self.value + + +class ElectricalComponentDiagnosticCode(Enum): + """All diagnostics that can occur across electrical component categories.""" + + UNSPECIFIED = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNSPECIFIED + ) + """Default value. No specific error is specified.""" + + UNKNOWN = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNKNOWN + ) + """The component is reporting an unknown or an undefined error, and the sender + cannot parse the component error to any of the variants below.""" + + SWITCH_ON_FAULT = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_SWITCH_ON_FAULT + ) + """Error indicating that the component could not be switched on.""" + + UNDERVOLTAGE = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNDERVOLTAGE + ) + """Error indicating that the component is operating under the minimum rated + voltage.""" + + OVERVOLTAGE = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_OVERVOLTAGE + ) + """Error indicating that the component is operating over the maximum rated + voltage.""" + + OVERCURRENT = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_OVERCURRENT + ) + """Error indicating that the component is drawing more current than the + maximum rated value.""" + + OVERCURRENT_CHARGING = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_OVERCURRENT_CHARGING # noqa: E501 + ) + """Error indicating that the component's consumption current is over the + maximum rated value during charging.""" + + OVERCURRENT_DISCHARGING = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_OVERCURRENT_DISCHARGING # noqa: E501 + ) + """Error indicating that the component's production current is over the + maximum rated value during discharging.""" + + OVERTEMPERATURE = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_OVERTEMPERATURE + ) + """Error indicating that the component is operating over the maximum rated + temperature.""" + + UNDERTEMPERATURE = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNDERTEMPERATURE + ) + """Error indicating that the component is operating under the minimum rated + temperature.""" + + HIGH_HUMIDITY = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_HIGH_HUMIDITY + ) + """Error indicating that the component is exposed to high humidity levels over + the maximum rated value.""" + + FUSE_ERROR = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_FUSE_ERROR + ) + """Error indicating that the component's fuse has blown.""" + + PRECHARGE_ERROR = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_PRECHARGE_ERROR + ) + """Error indicating that the component's precharge unit has failed.""" + + PLAUSIBILITY_ERROR = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_PLAUSIBILITY_ERROR + ) + """Error indicating plausibility issues within the system involving this + component.""" + + UNDERVOLTAGE_SHUTDOWN = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNDERVOLTAGE_SHUTDOWN # noqa: E501 + ) + """Error indicating system shutdown due to undervoltage involving this + component.""" + + EV_UNEXPECTED_PILOT_FAILURE = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_UNEXPECTED_PILOT_FAILURE # noqa: E501 + ) + """Error indicating unexpected pilot failure in an electric vehicle (EV) + component.""" + + FAULT_CURRENT = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_FAULT_CURRENT + ) + """Error indicating fault current detected in the component.""" + + SHORT_CIRCUIT = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_SHORT_CIRCUIT + ) + """Error indicating a short circuit detected in the component.""" + + CONFIG_ERROR = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_CONFIG_ERROR + ) + """Error indicating a configuration error related to the component.""" + + ILLEGAL_COMPONENT_STATE_CODE_REQUESTED = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_ILLEGAL_COMPONENT_STATE_CODE_REQUESTED # noqa: E501 + ) + """Error indicating an illegal state requested for the component.""" + + HARDWARE_INACCESSIBLE = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_HARDWARE_INACCESSIBLE # noqa: E501 + ) + """Error indicating that the hardware of the component is inaccessible.""" + + INTERNAL = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_INTERNAL + ) + """Error indicating an internal error within the component.""" + + UNAUTHORIZED = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_UNAUTHORIZED + ) + """Error indicating that the component is unauthorized to perform the + last requested action.""" + + EV_CHARGING_CABLE_UNPLUGGED_FROM_STATION = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_STATION # noqa: E501 + ) + """Error indicating electric vehicle (EV) cable was abruptly unplugged from + the charging station.""" + + EV_CHARGING_CABLE_UNPLUGGED_FROM_EV = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_CHARGING_CABLE_UNPLUGGED_FROM_EV # noqa: E501 + ) + """Error indicating electric vehicle (EV) cable was abruptly unplugged from + the vehicle.""" + + EV_CHARGING_CABLE_LOCK_FAILED = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_CHARGING_CABLE_LOCK_FAILED # noqa: E501 + ) + """Error indicating electric vehicle (EV) cable lock failure.""" + + EV_CHARGING_CABLE_INVALID = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_CHARGING_CABLE_INVALID # noqa: E501 + ) + """Error indicating an invalid electric vehicle (EV) cable.""" + + EV_CONSUMER_INCOMPATIBLE = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_EV_CONSUMER_INCOMPATIBLE # noqa: E501 + ) + """Error indicating an incompatible electric vehicle (EV) plug.""" + + BATTERY_IMBALANCE = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_IMBALANCE + ) + """Error indicating a battery system imbalance.""" + + BATTERY_LOW_SOH = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_LOW_SOH + ) + """Error indicating a low state of health (SOH) detected in the battery.""" + + BATTERY_BLOCK_ERROR = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_BLOCK_ERROR + ) + """Error indicating a battery block error.""" + + BATTERY_CONTROLLER_ERROR = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_CONTROLLER_ERROR # noqa: E501 + ) + """Error indicating a battery controller error.""" + + BATTERY_RELAY_ERROR = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_RELAY_ERROR + ) + """Error indicating a battery relay error.""" + + BATTERY_CALIBRATION_NEEDED = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_BATTERY_CALIBRATION_NEEDED # noqa: E501 + ) + """Error indicating that battery calibration is needed.""" + + RELAY_CYCLE_LIMIT_REACHED = ( + PBElectricalComponentDiagnosticCode.ELECTRICAL_COMPONENT_DIAGNOSTIC_CODE_RELAY_CYCLE_LIMIT_REACHED # noqa: E501 + ) + """Error indicating that the relays have been cycled for the maximum number of + times.""" + + @classmethod + def from_proto( + cls, component_error_code: PBElectricalComponentDiagnosticCode.ValueType + ) -> ElectricalComponentDiagnosticCode: + """Convert a protobuf ElectricalComponentDiagnosticCode message to enum. + + Args: + component_error_code: protobuf enum to convert + + Returns: + Enum value corresponding to the protobuf message. + """ + if not any( + c.value == component_error_code for c in ElectricalComponentDiagnosticCode + ): + return ElectricalComponentDiagnosticCode.UNSPECIFIED + return cls(component_error_code) + + def to_proto(self) -> PBElectricalComponentDiagnosticCode.ValueType: + """Convert a ElectricalComponentDiagnosticCode enum to protobuf message. + + Returns: + Enum value corresponding to the protobuf message. + """ + return self.value diff --git a/tests/test_client_common.py b/tests/test_client_common.py index e9d865db..b932bf0b 100644 --- a/tests/test_client_common.py +++ b/tests/test_client_common.py @@ -3,26 +3,31 @@ """Tests for the frequenz.client.common package.""" -from frequenz.client.common.microgrid.components import ( - ComponentCategory, - ComponentErrorCode, - ComponentStateCode, +from frequenz.client.common.microgrid.electrical_components import ( + ElectricalComponentCategory, + ElectricalComponentDiagnosticCode, + ElectricalComponentStateCode, ) def test_components() -> None: """Test the components.""" - for category in ComponentCategory: - assert ComponentCategory.from_proto(category.to_proto()) == category + for category in ElectricalComponentCategory: + assert ElectricalComponentCategory.from_proto(category.to_proto()) == category def test_component_state_code() -> None: """Test the component state code.""" - for state_code in ComponentStateCode: - assert ComponentStateCode.from_proto(state_code.to_proto()) == state_code + for state_code in ElectricalComponentStateCode: + assert ( + ElectricalComponentStateCode.from_proto(state_code.to_proto()) == state_code + ) def test_component_error_code() -> None: - """Test the component error code.""" - for error_code in ComponentErrorCode: - assert ComponentErrorCode.from_proto(error_code.to_proto()) == error_code + """Test the component diagnostic code.""" + for diagnostic_code in ElectricalComponentDiagnosticCode: + assert ( + ElectricalComponentDiagnosticCode.from_proto(diagnostic_code.to_proto()) + == diagnostic_code + )