diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f80f12e..1c67c43 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -2,11 +2,12 @@ ## Summary - +> **Warning:** This client is compatible *only* with Reporting API `v1alpha10` or later. +> Using with services that use an older API version **will cause failures**. ## Upgrading - +* Breaking change to reporting API v1alpha10. ## New Features diff --git a/pyproject.toml b/pyproject.toml index c979f2c..630ea6c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,12 +26,12 @@ classifiers = [ ] requires-python = ">= 3.11, < 4" dependencies = [ - "typing_extensions >= 4.6.1, < 5", + "typing_extensions >= 4.13.0, < 5", "grpc-stubs == 1.53.0.6", - "frequenz-api-reporting >= 0.8.0, < 0.9", - "frequenz-client-common >= 0.3.0, < 0.4", + "frequenz-api-reporting >= 0.10.0, < 0.11", + "frequenz-client-common >= 0.3.7, < 0.4", "grpcio >=1.72.1, < 2", - "protobuf >=6.31.1, < 7", + "protobuf >=6.33.1, < 7", "frequenz-client-base >= 0.11.0, < 0.12.0", ] dynamic = ["version"] diff --git a/src/frequenz/client/reporting/_client.py b/src/frequenz/client/reporting/_client.py index c0398b5..7a8a42f 100644 --- a/src/frequenz/client/reporting/_client.py +++ b/src/frequenz/client/reporting/_client.py @@ -8,48 +8,50 @@ from typing import cast # pylint: disable=no-name-in-module -from frequenz.api.common.v1.microgrid.microgrid_pb2 import ( - MicrogridComponentIDs as PBMicrogridComponentIDs, +from frequenz.api.common.v1alpha8.microgrid.microgrid_pb2 import ( + MicrogridElectricalComponentIDs as PBMicrogridComponentIDs, ) -from frequenz.api.common.v1.microgrid.microgrid_pb2 import ( +from frequenz.api.common.v1alpha8.microgrid.microgrid_pb2 import ( MicrogridSensorIDs as PBMicrogridSensorIDs, ) -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( AggregationConfig as PBAggregationConfig, ) -from frequenz.api.reporting.v1.reporting_pb2 import FilterOption as PBFilterOption -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( + FilterOption as PBFilterOption, +) +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( MetricConnections as PBMetricConnections, ) -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( ReceiveAggregatedMicrogridComponentsDataStreamRequest as PBAggregatedStreamRequest, ) -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( ReceiveAggregatedMicrogridComponentsDataStreamResponse as PBAggregatedStreamResponse, ) -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( ReceiveMicrogridComponentsDataStreamRequest as PBReceiveMicrogridComponentsDataStreamRequest, ) -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( ReceiveMicrogridComponentsDataStreamResponse as PBReceiveMicrogridComponentsDataStreamResponse, ) -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( ReceiveMicrogridSensorsDataStreamRequest as PBReceiveMicrogridSensorsDataStreamRequest, ) -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( ReceiveMicrogridSensorsDataStreamResponse as PBReceiveMicrogridSensorsDataStreamResponse, ) -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( ResamplingOptions as PBResamplingOptions, ) -from frequenz.api.reporting.v1.reporting_pb2 import TimeFilter as PBTimeFilter -from frequenz.api.reporting.v1.reporting_pb2_grpc import ReportingStub +from frequenz.api.reporting.v1alpha10.reporting_pb2 import TimeFilter as PBTimeFilter +from frequenz.api.reporting.v1alpha10.reporting_pb2_grpc import ReportingStub from frequenz.channels import Receiver from frequenz.client.base.channel import ChannelOptions from frequenz.client.base.client import BaseApiClient from frequenz.client.base.exception import ClientNotConnected from frequenz.client.base.streaming import GrpcStreamBroadcaster -from frequenz.client.common.metric import Metric +from frequenz.client.common.metrics import Metric from google.protobuf.timestamp_pb2 import Timestamp as PBTimestamp from ._batch_unroll_receiver import BatchUnrollReceiver @@ -250,7 +252,7 @@ def _receive_microgrid_components_data_batch( or not self._components_data_streams[stream_key].is_running ): microgrid_components_pb = [ - PBMicrogridComponentIDs(microgrid_id=mid, component_ids=cids) + PBMicrogridComponentIDs(microgrid_id=mid, electrical_component_ids=cids) for mid, cids in microgrid_components ] @@ -294,7 +296,7 @@ def dt2ts(dt: datetime) -> PBTimestamp: ) metric_conns_pb = [ - PBMetricConnections(metric=metric.to_proto(), connections=[]) + PBMetricConnections(metric=metric.value, connections=[]) for metric in metrics ] @@ -477,7 +479,7 @@ def dt2ts(dt: datetime) -> PBTimestamp: metric_conns_pb = [ PBMetricConnections( - metric=metric.to_proto(), + metric=metric.value, connections=[], ) for metric in metrics @@ -556,7 +558,7 @@ def receive_aggregated_data( aggregation_config = PBAggregationConfig( microgrid_id=microgrid_id, - metric=metric.to_proto(), + metric=metric.value, aggregation_formula=aggregation_formula, ) diff --git a/src/frequenz/client/reporting/_types.py b/src/frequenz/client/reporting/_types.py index 4a3e52f..81473cc 100644 --- a/src/frequenz/client/reporting/_types.py +++ b/src/frequenz/client/reporting/_types.py @@ -5,22 +5,23 @@ from collections.abc import Iterable, Iterator from dataclasses import dataclass -from datetime import datetime, timezone +from datetime import datetime from typing import Any, NamedTuple # pylint: disable=no-name-in-module -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( ReceiveAggregatedMicrogridComponentsDataStreamResponse as PBAggregatedStreamResponse, ) -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( ReceiveMicrogridComponentsDataStreamResponse as PBReceiveMicrogridComponentsDataStreamResponse, ) -from frequenz.api.reporting.v1.reporting_pb2 import ( +from frequenz.api.reporting.v1alpha10.reporting_pb2 import ( ReceiveMicrogridSensorsDataStreamResponse as PBReceiveMicrogridSensorsDataStreamResponse, ) # pylint: enable=no-name-in-module -from frequenz.client.common.metric import Metric +from frequenz.client.common.metrics import Metric +from frequenz.client.common.proto import datetime_from_proto, enum_from_proto class MetricSample(NamedTuple): @@ -92,8 +93,8 @@ def __iter__(self) -> Iterator[MetricSample]: for item in items: cid = getattr(item, self.id_attr) for sample in getattr(item, "metric_samples", []): - ts = sample.sampled_at.ToDatetime().replace(tzinfo=timezone.utc) - met = Metric.from_proto(sample.metric).name + ts = datetime_from_proto(sample.sample_time) + met = enum_from_proto(sample.metric, Metric, allow_invalid=False).name # Handle simple_metric if sample.value.HasField("simple_metric"): @@ -126,8 +127,8 @@ def __iter__(self) -> Iterator[MetricSample]: ts, mid, cid, f"{met}_bound_{i}_upper", bound.upper ) - for state in getattr(item, "states", []): - ts = state.sampled_at.ToDatetime().replace(tzinfo=timezone.utc) + for state in getattr(item, "state_snapshots", []): + ts = datetime_from_proto(state.origin_time) for category, category_items in { "state": getattr(state, "states", []), "warning": getattr(state, "warnings", []), @@ -150,7 +151,10 @@ def __init__(self, data_pb: PBReceiveMicrogridComponentsDataStreamResponse): data_pb: The underlying protobuf message. """ super().__init__( - data_pb, id_attr="component_id", items_attr="components", has_bounds=True + data_pb, + id_attr="electrical_component_id", + items_attr="components", + has_bounds=True, ) @@ -177,9 +181,7 @@ class AggregatedMetric: def sample(self) -> MetricSample: """Return the aggregated metric sample.""" return MetricSample( - timestamp=self._data_pb.sample.sample_time.ToDatetime().replace( - tzinfo=timezone.utc - ), + timestamp=datetime_from_proto(self._data_pb.sample.sample_time), microgrid_id=self._data_pb.aggregation_config.microgrid_id, component_id=self._data_pb.aggregation_config.aggregation_formula, metric=Metric(self._data_pb.aggregation_config.metric).name, diff --git a/src/frequenz/client/reporting/cli/__main__.py b/src/frequenz/client/reporting/cli/__main__.py index 9085055..aab08b9 100644 --- a/src/frequenz/client/reporting/cli/__main__.py +++ b/src/frequenz/client/reporting/cli/__main__.py @@ -8,7 +8,7 @@ from datetime import datetime, timedelta from typing import AsyncIterator -from frequenz.client.common.metric import Metric +from frequenz.client.common.metrics import Metric from frequenz.client.reporting import ReportingApiClient from frequenz.client.reporting._types import MetricSample diff --git a/tests/test_client_reporting.py b/tests/test_client_reporting.py index a054c48..0f59ab9 100644 --- a/tests/test_client_reporting.py +++ b/tests/test_client_reporting.py @@ -5,7 +5,7 @@ from unittest.mock import MagicMock, patch import pytest -from frequenz.api.reporting.v1.reporting_pb2_grpc import ReportingStub +from frequenz.api.reporting.v1alpha10.reporting_pb2_grpc import ReportingStub from frequenz.client.base.channel import ChannelOptions from frequenz.client.base.client import BaseApiClient