|
| 1 | +# License: MIT |
| 2 | +# Copyright © 2022 Frequenz Energy-as-a-Service GmbH |
| 3 | + |
| 4 | +"""Tests for the microgrid component data.""" |
| 5 | + |
| 6 | +from datetime import datetime, timezone |
| 7 | + |
| 8 | +import pytest |
| 9 | + |
| 10 | +# pylint: disable=no-name-in-module |
| 11 | +from frequenz.api.common.metrics.electrical_pb2 import AC |
| 12 | +from frequenz.api.common.metrics_pb2 import Bounds, Metric |
| 13 | +from frequenz.api.microgrid.inverter_pb2 import ( |
| 14 | + COMPONENT_STATE_DISCHARGING, |
| 15 | + Data, |
| 16 | + Error, |
| 17 | + Inverter, |
| 18 | + State, |
| 19 | +) |
| 20 | +from frequenz.api.microgrid.microgrid_pb2 import ComponentData as PbComponentData |
| 21 | +from google.protobuf.timestamp_pb2 import Timestamp |
| 22 | + |
| 23 | +# pylint: enable=no-name-in-module |
| 24 | +from frequenz.client.microgrid import ComponentData, InverterData |
| 25 | + |
| 26 | + |
| 27 | +def test_component_data_abstract_class() -> None: |
| 28 | + """Verify the base class ComponentData may not be instantiated.""" |
| 29 | + with pytest.raises(TypeError): |
| 30 | + # pylint: disable=abstract-class-instantiated |
| 31 | + ComponentData(0, datetime.now(timezone.utc)) # type: ignore |
| 32 | + |
| 33 | + |
| 34 | +def test_inverter_data() -> None: |
| 35 | + """Verify the constructor for the InverterData class.""" |
| 36 | + seconds = 1234567890 |
| 37 | + |
| 38 | + raw = PbComponentData( |
| 39 | + id=5, |
| 40 | + ts=Timestamp(seconds=seconds), |
| 41 | + inverter=Inverter( |
| 42 | + state=State(component_state=COMPONENT_STATE_DISCHARGING), |
| 43 | + errors=[Error(msg="error message")], |
| 44 | + data=Data( |
| 45 | + dc_battery=None, |
| 46 | + dc_solar=None, |
| 47 | + temperature=None, |
| 48 | + ac=AC( |
| 49 | + frequency=Metric(value=50.1), |
| 50 | + power_active=Metric( |
| 51 | + value=100.2, |
| 52 | + system_exclusion_bounds=Bounds(lower=-501.0, upper=501.0), |
| 53 | + system_inclusion_bounds=Bounds(lower=-51_000.0, upper=51_000.0), |
| 54 | + ), |
| 55 | + phase_1=AC.ACPhase( |
| 56 | + current=Metric(value=12.3), |
| 57 | + voltage=Metric(value=229.8), |
| 58 | + power_active=Metric(value=33.1), |
| 59 | + ), |
| 60 | + phase_2=AC.ACPhase( |
| 61 | + current=Metric(value=23.4), |
| 62 | + voltage=Metric(value=230.0), |
| 63 | + power_active=Metric(value=33.3), |
| 64 | + ), |
| 65 | + phase_3=AC.ACPhase( |
| 66 | + current=Metric(value=34.5), |
| 67 | + voltage=Metric(value=230.2), |
| 68 | + power_active=Metric(value=33.8), |
| 69 | + ), |
| 70 | + ), |
| 71 | + ), |
| 72 | + ), |
| 73 | + ) |
| 74 | + |
| 75 | + inv_data = InverterData.from_proto(raw) |
| 76 | + assert inv_data.component_id == 5 |
| 77 | + assert inv_data.timestamp == datetime.fromtimestamp(seconds, timezone.utc) |
| 78 | + assert ( # pylint: disable=protected-access |
| 79 | + inv_data._component_state == COMPONENT_STATE_DISCHARGING |
| 80 | + ) |
| 81 | + assert inv_data._errors == [ # pylint: disable=protected-access |
| 82 | + Error(msg="error message") |
| 83 | + ] |
| 84 | + assert inv_data.frequency == pytest.approx(50.1) |
| 85 | + assert inv_data.active_power == pytest.approx(100.2) |
| 86 | + assert inv_data.active_power_per_phase == pytest.approx((33.1, 33.3, 33.8)) |
| 87 | + assert inv_data.current_per_phase == pytest.approx((12.3, 23.4, 34.5)) |
| 88 | + assert inv_data.voltage_per_phase == pytest.approx((229.8, 230.0, 230.2)) |
| 89 | + assert inv_data.active_power_inclusion_lower_bound == pytest.approx(-51_000.0) |
| 90 | + assert inv_data.active_power_inclusion_upper_bound == pytest.approx(51_000.0) |
| 91 | + assert inv_data.active_power_exclusion_lower_bound == pytest.approx(-501.0) |
| 92 | + assert inv_data.active_power_exclusion_upper_bound == pytest.approx(501.0) |
0 commit comments