Skip to content

Commit 895dc7a

Browse files
authored
Add CLI tool to print formulas (#17)
CLI tool which queries the component graph from the assets API and prints formulas for pre-defined assets to stdout.
2 parents b7139bc + 7402c80 commit 895dc7a

File tree

4 files changed

+80
-4
lines changed

4 files changed

+80
-4
lines changed

RELEASE_NOTES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
## New Features
1212

13+
* Add CLI tool to print formulas from assets API component graph.
14+
1315
<!-- Here goes the main new features and examples or instructions on how to use them -->
1416

1517
## Bug Fixes

pyproject.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ description = "High-level interface to grid pools for the Frequenz platform."
1515
readme = "README.md"
1616
license = { text = "MIT" }
1717
keywords = ["frequenz", "python", "lib", "library", "gridpool"]
18-
# TODO(cookiecutter): Remove and add more classifiers if appropriate
1918
classifiers = [
2019
"Development Status :: 3 - Alpha",
2120
"Intended Audience :: Developers",
@@ -26,20 +25,22 @@ classifiers = [
2625
"Typing :: Typed",
2726
]
2827
requires-python = ">= 3.11, < 4"
29-
# TODO(cookiecutter): Remove and add more dependencies if appropriate
3028
dependencies = [
31-
"marshmallow-dataclass>=8.7.1,<9",
29+
"marshmallow-dataclass >= 8.7.1, < 9",
30+
"asyncclick >= 8.3.0.4, < 9",
3231
"typing-extensions >= 4.14.1, < 5",
3332
"frequenz-microgrid-component-graph >= 0.2.0, < 0.3",
3433
"frequenz-client-assets >= 0.2.0, < 0.3",
3534
]
3635
dynamic = ["version"]
3736

37+
[project.scripts]
38+
gridpool-cli = "frequenz.gridpool.cli.__main__:main"
39+
3840
[[project.authors]]
3941
name = "Frequenz Energy-as-a-Service GmbH"
4042
email = "floss@frequenz.com"
4143

42-
# TODO(cookiecutter): Remove and add more optional dependencies if appropriate
4344
[project.optional-dependencies]
4445
dev-flake8 = [
4546
"flake8 == 7.3.0",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Package for CLI tool for gridpool functionality."""
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# License: MIT
2+
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3+
4+
"""CLI tool for gridpool functionality."""
5+
6+
import os
7+
8+
import asyncclick as click
9+
from frequenz.client.assets import AssetsApiClient
10+
from frequenz.client.common.microgrid import MicrogridId
11+
12+
from frequenz.gridpool import ComponentGraphGenerator
13+
14+
15+
@click.group()
16+
async def cli() -> None:
17+
"""CLI tool for gridpool functionality."""
18+
19+
20+
@cli.command()
21+
@click.argument("microgrid_id", type=int)
22+
@click.option(
23+
"--prefix",
24+
type=str,
25+
default="{component}",
26+
help="Prefix format for the output (Supports {microgrid_id} and {component} placeholders).",
27+
)
28+
async def print_formulas(
29+
microgrid_id: int,
30+
prefix: str,
31+
) -> None:
32+
"""Fetch and print component graph formulas for a microgrid."""
33+
url = os.environ.get("ASSETS_API_URL")
34+
key = os.environ.get("ASSETS_API_AUTH_KEY")
35+
secret = os.environ.get("ASSETS_API_SIGN_SECRET")
36+
if not url or not key or not secret:
37+
raise click.ClickException(
38+
"ASSETS_API_URL, ASSETS_API_AUTH_KEY, ASSETS_API_SIGN_SECRET must be set."
39+
)
40+
41+
async with AssetsApiClient(
42+
url,
43+
auth_key=key,
44+
sign_secret=secret,
45+
) as client:
46+
cgg = ComponentGraphGenerator(client)
47+
48+
graph = await cgg.get_component_graph(MicrogridId(microgrid_id))
49+
power_formulas = {
50+
"consumption": graph.consumer_formula(),
51+
"generation": graph.producer_formula(),
52+
"grid": graph.grid_formula(),
53+
"pv": graph.pv_formula(None),
54+
"battery": graph.battery_formula(None),
55+
"chp": graph.chp_formula(None),
56+
"ev": graph.ev_charger_formula(None),
57+
}
58+
59+
for component, formula in power_formulas.items():
60+
print(
61+
prefix.format(component=component, microgrid_id=microgrid_id)
62+
+ f' = "{formula}"'
63+
)
64+
65+
66+
def main() -> None:
67+
"""Run the CLI tool."""
68+
cli(_anyio_backend="asyncio")
69+
70+
71+
if __name__ == "__main__":
72+
main()

0 commit comments

Comments
 (0)