Skip to content

Commit 2e8ddf6

Browse files
committed
Implement a ComponentGraphGenerator from the assets API
Signed-off-by: Sahas Subramanian <[email protected]>
1 parent 8b7552f commit 2e8ddf6

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

src/frequenz/gridpool/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@
22
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
33

44
"""High-level interface to grid pools for the Frequenz platform."""
5+
6+
from ._graph_generator import ComponentGraphGenerator
7+
8+
__all__ = ["ComponentGraphGenerator"]
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# License: MIT
2+
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3+
4+
"""Formula generation from assets API component/connection configurations."""
5+
6+
from typing import cast
7+
8+
from frequenz.client.assets import AssetsApiClient
9+
from frequenz.client.assets.electrical_component import (
10+
ComponentConnection,
11+
ElectricalComponent,
12+
)
13+
from frequenz.client.base import channel
14+
from frequenz.client.common.microgrid import MicrogridId
15+
from frequenz.client.common.microgrid.electrical_components import ElectricalComponentId
16+
from frequenz.microgrid_component_graph import ComponentGraph
17+
18+
19+
class ComponentGraphGenerator:
20+
"""Generates component graphs for microgrids using the Assets API."""
21+
22+
def __init__( # pylint: disable=too-many-arguments
23+
self,
24+
server_url: str,
25+
*,
26+
auth_key: str | None = None,
27+
sign_secret: str | None = None,
28+
channel_defaults: channel.ChannelOptions = channel.ChannelOptions(),
29+
connect: bool = True,
30+
) -> None:
31+
"""Initialize this instance.
32+
33+
Args:
34+
server_url: The location of the microgrid API server in the form of a URL.
35+
The following format is expected:
36+
"grpc://hostname{:`port`}{?ssl=`ssl`}",
37+
where the `port` should be an int between 0 and 65535 (defaulting to
38+
9090) and `ssl` should be a boolean (defaulting to `true`).
39+
For example: `grpc://localhost:1090?ssl=true`.
40+
auth_key: The authentication key to use for the connection.
41+
sign_secret: The secret to use for signing requests.
42+
channel_defaults: The default options use to create the channel when not
43+
specified in the URL.
44+
connect: Whether to connect to the server as soon as a client instance is
45+
created. If `False`, the client will not connect to the server until
46+
[connect()][frequenz.client.base.client.BaseApiClient.connect] is
47+
called.
48+
"""
49+
self._client: AssetsApiClient = AssetsApiClient(
50+
server_url,
51+
auth_key=auth_key,
52+
sign_secret=sign_secret,
53+
channel_defaults=channel_defaults,
54+
connect=connect,
55+
)
56+
57+
async def get_component_graph(
58+
self, microgrid_id: MicrogridId
59+
) -> ComponentGraph[
60+
ElectricalComponent, ComponentConnection, ElectricalComponentId
61+
]:
62+
"""Generate a component graph for the given microgrid ID.
63+
64+
Args:
65+
microgrid_id: The ID of the microgrid to generate the graph for.
66+
67+
Returns:
68+
The component graph representing the microgrid's electrical
69+
components and their connections.
70+
71+
Raises:
72+
ValueError: If any component connections could not be loaded.
73+
"""
74+
components = await self._client.list_microgrid_electrical_components(
75+
microgrid_id
76+
)
77+
connections = (
78+
await self._client.list_microgrid_electrical_component_connections(
79+
microgrid_id
80+
)
81+
)
82+
83+
if any(c is None for c in connections):
84+
raise ValueError("Failed to load all electrical component connections.")
85+
86+
graph = ComponentGraph[
87+
ElectricalComponent, ComponentConnection, ElectricalComponentId
88+
](components, cast(list[ComponentConnection], connections))
89+
90+
return graph

0 commit comments

Comments
 (0)