Skip to content

Commit 10cd5c1

Browse files
authored
Add missing state and error wrappers (#54)
- **Remove some unnecessary pylint exceptions** - **Add a missing `UNKNOWN` EV charger component state** - **Return `UNKNOWN` instead of `UNSPECIFIED` for unknown states** - **Wrap missing component errors** - **Wrap missing component states** - **Unify the style with the new wrappers** - **Update release notes** - **Prepare release notes for the v0.4.0 release**
2 parents 01a741e + 00f14e7 commit 10cd5c1

File tree

6 files changed

+454
-40
lines changed

6 files changed

+454
-40
lines changed

RELEASE_NOTES.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Summary
44

5-
<!-- Here goes a general summary of what this release is about -->
5+
This release migrates to use `betterproto` and `grpclib` instead of `grpcio` and `protobuf` internally. It also stops *leaking* these internal libraries to downstream users. It should now be possible to use the client without having to use `grpclib` or `betterproto` directly.
66

77
## Upgrading
88

@@ -16,6 +16,8 @@
1616

1717
- The client now uses protobuf/grpc bindings generated [betterproto](https://github.com/danielgtaylor/python-betterproto) ([frequenz-microgrid-betterproto](https://github.com/frequenz-floss/frequenz-microgrid-betterproto-python)) instead of [grpcio](https://pypi.org/project/grpcio/) ([frequenz-api-microgrid](https://github.com/frequenz-floss/frequenz-api-microgrid)). If you were using the bindings directly, you might need to do some minor adjustments to your code.
1818

19+
- If an unknown EV charger component state is received, it will now be set to `EVChargerComponentState.UNKNOWN` instead of `EVChargerComponentState.UNSPECIFIED`.
20+
1921
## New Features
2022

2123
- The client now raises more specific exceptions based on the gRPC status code, so you can more easily handle different types of errors.
@@ -39,6 +41,18 @@
3941
...
4042
```
4143

44+
- We now expose component errors as part of the streamed component data:
45+
46+
* `BatteryData.errors`
47+
* `InverterData.errors`
48+
49+
- We now expose component states as part of the streamed component data:
50+
51+
* `BatteryData.component_state` and `BatteryData.relay_state`
52+
* `InverterData.component_state`
53+
54+
- Added the missing `EVChargerComponentState.UNKNOWN` state.
55+
4256
## Bug Fixes
4357

4458
- Fix a leakage of `GrpcStreamBroadcaster` instances.

src/frequenz/client/microgrid/__init__.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,20 @@
2525
InverterData,
2626
MeterData,
2727
)
28-
from ._component_states import EVChargerCableState, EVChargerComponentState
28+
from ._component_error import (
29+
BatteryError,
30+
BatteryErrorCode,
31+
ErrorLevel,
32+
InverterError,
33+
InverterErrorCode,
34+
)
35+
from ._component_states import (
36+
BatteryComponentState,
37+
BatteryRelayState,
38+
EVChargerCableState,
39+
EVChargerComponentState,
40+
InverterComponentState,
41+
)
2942
from ._connection import Connection
3043
from ._exception import (
3144
ClientError,
@@ -52,7 +65,11 @@
5265

5366
__all__ = [
5467
"ApiClient",
68+
"BatteryComponentState",
5569
"BatteryData",
70+
"BatteryError",
71+
"BatteryErrorCode",
72+
"BatteryRelayState",
5673
"ClientError",
5774
"Component",
5875
"ComponentCategory",
@@ -67,12 +84,16 @@
6784
"EVChargerData",
6885
"EntityAlreadyExists",
6986
"EntityNotFound",
87+
"ErrorLevel",
7088
"Fuse",
7189
"GridMetadata",
7290
"GrpcError",
7391
"InternalError",
7492
"InvalidArgument",
93+
"InverterComponentState",
7594
"InverterData",
95+
"InverterError",
96+
"InverterErrorCode",
7697
"InverterType",
7798
"Location",
7899
"Metadata",

src/frequenz/client/microgrid/_component_data.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@
99
from typing import Self
1010

1111
from frequenz.microgrid.betterproto.frequenz.api import microgrid
12-
from frequenz.microgrid.betterproto.frequenz.api.microgrid import battery, inverter
1312

14-
from ._component_states import EVChargerCableState, EVChargerComponentState
13+
from ._component_error import BatteryError, InverterError
14+
from ._component_states import (
15+
BatteryComponentState,
16+
BatteryRelayState,
17+
EVChargerCableState,
18+
EVChargerComponentState,
19+
InverterComponentState,
20+
)
1521

1622

1723
@dataclass(frozen=True)
@@ -173,7 +179,6 @@ class BatteryData(ComponentData): # pylint: disable=too-many-instance-attribute
173179
capacity: float
174180
"""The capacity of the battery in Wh (Watt-hour)."""
175181

176-
# pylint: disable=line-too-long
177182
power_inclusion_lower_bound: float
178183
"""Lower inclusion bound for battery power in watts.
179184
@@ -217,18 +222,17 @@ class BatteryData(ComponentData): # pylint: disable=too-many-instance-attribute
217222
[`frequenz.api.common.metrics_pb2.Metric.system_exclusion_bounds`][] for more
218223
details.
219224
"""
220-
# pylint: enable=line-too-long
221225

222226
temperature: float
223227
"""The (average) temperature reported by the battery, in Celsius (°C)."""
224228

225-
_relay_state: battery.RelayState
229+
relay_state: BatteryRelayState
226230
"""State of the battery relay."""
227231

228-
_component_state: battery.ComponentState
232+
component_state: BatteryComponentState
229233
"""State of the battery."""
230234

231-
_errors: list[battery.Error]
235+
errors: list[BatteryError]
232236
"""List of errors in protobuf struct."""
233237

234238
@classmethod
@@ -254,9 +258,11 @@ def from_proto(cls, raw: microgrid.ComponentData) -> Self:
254258
power_inclusion_upper_bound=raw_power.system_inclusion_bounds.upper,
255259
power_exclusion_upper_bound=raw_power.system_exclusion_bounds.upper,
256260
temperature=raw.battery.data.temperature.avg,
257-
_relay_state=raw.battery.state.relay_state,
258-
_component_state=raw.battery.state.component_state,
259-
_errors=list(raw.battery.errors),
261+
relay_state=BatteryRelayState.from_pb(raw.battery.state.relay_state),
262+
component_state=BatteryComponentState.from_pb(
263+
raw.battery.state.component_state
264+
),
265+
errors=[BatteryError.from_pb(e) for e in raw.battery.errors],
260266
)
261267
battery_data._set_raw(raw=raw)
262268
return battery_data
@@ -314,7 +320,6 @@ class InverterData(ComponentData): # pylint: disable=too-many-instance-attribut
314320
phase/line 1, 2 and 3 respectively.
315321
"""
316322

317-
# pylint: disable=line-too-long
318323
active_power_inclusion_lower_bound: float
319324
"""Lower inclusion bound for inverter power in watts.
320325
@@ -358,15 +363,14 @@ class InverterData(ComponentData): # pylint: disable=too-many-instance-attribut
358363
[`frequenz.api.common.metrics_pb2.Metric.system_exclusion_bounds`][] for more
359364
details.
360365
"""
361-
# pylint: enable=line-too-long
362366

363367
frequency: float
364368
"""AC frequency, in Hertz (Hz)."""
365369

366-
_component_state: inverter.ComponentState
370+
component_state: InverterComponentState
367371
"""State of the inverter."""
368372

369-
_errors: list[inverter.Error]
373+
errors: list[InverterError]
370374
"""List of errors from the component."""
371375

372376
@classmethod
@@ -410,8 +414,10 @@ def from_proto(cls, raw: microgrid.ComponentData) -> Self:
410414
active_power_inclusion_upper_bound=raw_power.system_inclusion_bounds.upper,
411415
active_power_exclusion_upper_bound=raw_power.system_exclusion_bounds.upper,
412416
frequency=raw.inverter.data.ac.frequency.value,
413-
_component_state=raw.inverter.state.component_state,
414-
_errors=list(raw.inverter.errors),
417+
component_state=InverterComponentState.from_pb(
418+
raw.inverter.state.component_state
419+
),
420+
errors=[InverterError.from_pb(e) for e in raw.inverter.errors],
415421
)
416422

417423
inverter_data._set_raw(raw=raw)

0 commit comments

Comments
 (0)