Skip to content

Cover all microgrid client categories in category mapping#72

Merged
shsms merged 5 commits into
frequenz-floss:v0.x.xfrom
shsms:cover-all-categories
May 11, 2026
Merged

Cover all microgrid client categories in category mapping#72
shsms merged 5 commits into
frequenz-floss:v0.x.xfrom
shsms:cover-all-categories

Conversation

@shsms
Copy link
Copy Markdown
Collaborator

@shsms shsms commented May 7, 2026

Summary

category_from_python_component previously mapped only a subset of
cg::ComponentCategory. This PR makes it cover every variant.

Subtype-aware mapping

Concrete subtype classes from frequenz.client.microgrid.component
are now mapped to their cg-side subtypes instead of collapsing to
Unspecified:

  • LiIonBatteryBattery(LiIon)
  • NaIonBatteryBattery(NaIon)
  • AcEvChargerEvCharger(Ac)
  • DcEvChargerEvCharger(Dc)
  • HybridEvChargerEvCharger(Hybrid)
  • Inverter parent catches UnspecifiedInverter / UnrecognizedInverter
  • UnrecognizedComponent joins UnspecifiedComponentcg::Unspecified

Pass-through categories

Now mapped:

  • Converter, CryptoMiner, Electrolyzer, Hvac, Precharger
  • Relaycg::Breaker (the protobuf tag is BREAKER)
  • VoltageTransformercg::PowerTransformer (the protobuf
    enum was renamed VOLTAGE_TRANSFORMERPOWER_TRANSFORMER)

Forward compatibility

  • Field order in ComponentClasses mirrors the ComponentCategory
    enum in frequenz.client.microgrid.component._category so future
    client edits are obvious diffs.
  • Forward-compat aliases (Breaker, PowerTransformer) are probed
    optionally — they activate if the client ever renames its classes
    to match the protobuf-canonical names.
  • cg-only categories the client doesn't ship today (Plc,
    StaticTransferSwitch, UninterruptiblePowerSupply,
    CapacitorBank, SteamBoiler) are also probed optionally so an
    alternative provider that exposes them works with no code change.

Tests

Two new tests assert cg's pass-through behavior is observable
through the Python API (predecessors / successors walk past the
node; the PV formula doesn't reference it):

  • test_relay_is_passthrough
  • test_hvac_is_passthrough

@shsms shsms requested a review from a team as a code owner May 7, 2026 14:24
@shsms shsms requested review from simonvoelcker and removed request for a team May 7, 2026 14:24
@github-actions github-actions Bot added the part:tests Affects the unit, integration and performance (benchmarks) tests label May 7, 2026
@shsms shsms force-pushed the cover-all-categories branch from 59fca6b to 61598d9 Compare May 7, 2026 14:29
@github-actions github-actions Bot added the part:docs Affects the documentation label May 7, 2026
@shsms shsms force-pushed the cover-all-categories branch from 61598d9 to 74c72cb Compare May 7, 2026 14:31
Comment thread src/category.rs Outdated
static_transfer_switch: Option<Bound<'py, PyAny>>,
uninterruptible_power_supply: Option<Bound<'py, PyAny>>,
capacitor_bank: Option<Bound<'py, PyAny>>,
steam_boiler: Option<Bound<'py, PyAny>>,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SteamBoiler has been added to microgrid client in v0.18.3.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added as a required python type, but we can't release this PR until it is available as a type in the assets client as well.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm working on adding all this to the common API client repo (finally). Maybe I have some PR today.

Copy link
Copy Markdown
Collaborator Author

@shsms shsms May 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integrating the common API into the SDK and component-graph sounds like a bigger change, I'd rather wait for an update to the assets client, so we can get the pass-through stuff out already.

@shsms shsms force-pushed the cover-all-categories branch from 74c72cb to 30bd915 Compare May 7, 2026 14:52
@github-actions github-actions Bot added the part:tooling Affects the development tooling (CI, deployment, dependency management, etc.) label May 7, 2026
@shsms shsms force-pushed the cover-all-categories branch from 30bd915 to 5d3d17f Compare May 7, 2026 14:53
Comment thread RELEASE_NOTES.md
Comment thread tests/test_microgrid_component_graph.py
shsms added 2 commits May 8, 2026 12:29
category_from_python_component previously handled only a subset of
cg::ComponentCategory: GridConnectionPoint, Meter, Battery
(Unspecified), the three concrete inverter subtypes, EvCharger
(Unspecified), Chp, WindTurbine, and Unspecified. Cover everything
cg defines.

Concrete subtype classes from the microgrid client are checked
before their abstract parent so the cg-side subtype is preserved
instead of collapsing to Unspecified:

  * battery: LiIonBattery, NaIonBattery
  * ev_charger: AcEvCharger, DcEvCharger, HybridEvCharger
  * inverter: Inverter parent catches Unspecified/UnrecognizedInverter

Pass-through categories are also mapped: Converter, CryptoMiner,
Electrolyzer, Hvac, Precharger, Relay (-> cg::Breaker), and
VoltageTransformer (-> cg::PowerTransformer). UnrecognizedComponent
joins UnspecifiedComponent in mapping to cg::Unspecified.
SteamBoiler (new in frequenz-client-microgrid 0.18.3) is mapped to
cg::SteamBoiler; the `microgrid` extra's lower bound is bumped to
0.18.3 to match.

Field order mirrors the ComponentCategory enum in
frequenz.client.microgrid.component._category. Forward-compat
aliases (Breaker, PowerTransformer) and cg-only categories that no
provider exposes today (Plc, StaticTransferSwitch,
UninterruptiblePowerSupply, CapacitorBank) are probed optionally
so an alternative provider that exposes them works without a code
change.

Signed-off-by: Sahas Subramanian <sahas.subramanian@proton.me>
Build a Grid -> ... -> SolarInverter graph with each pass-through
category placed inline and assert that cg's pass-through behavior
is observable from the Python API:

  * predecessors/successors walk past the pass-through node
  * pv_ac_coalesce_formula doesn't reference the pass-through

Hvac is used rather than VoltageTransformer because the latter
maps to cg::PowerTransformer, which may stop being pass-through
once the Frequenz client gains transformer-specific handling.

Signed-off-by: Sahas Subramanian <sahas.subramanian@proton.me>
@shsms shsms force-pushed the cover-all-categories branch from 5d3d17f to 44547c5 Compare May 8, 2026 10:29
shsms added a commit to shsms/frequenz-microgrid-component-graph-python that referenced this pull request May 8, 2026
Parametrize a small graph over each Python component class the
category mapping handles, and assert the instance ends up in the
graph. Covers every concrete subtype 1594ad3 introduced -- not just
the hardcoded leaves -- so a future regression in the mapping would
fail loudly rather than only being caught once an instance flows
through end-to-end.

Topology per category, picking the smallest valid graph:

  * Battery subtypes (LiIonBattery, NaIonBattery, UnspecifiedBattery,
    UnrecognizedBattery): downstream of a BatteryInverter.
  * EV chargers (Ac/Dc/Hybrid/Unspecified/Unrecognized) and plain
    leaf consumers (Chp, SteamBoiler): leaf below a Meter.
  * Battery- and Hybrid-Inverters: between a Meter and a Battery.
  * Pass-through categories (Converter, CryptoMiner, Electrolyzer,
    Precharger, VoltageTransformer): inline with a SolarInverter
    consumer downstream.

Plus a paired rejection test for the classes whose mapping yields an
Unspecified category, which the cg crate refuses at construction:

  * cg::Unspecified -- UnspecifiedComponent, UnrecognizedComponent.
  * cg::Inverter(Unspecified) -- UnspecifiedInverter,
    UnrecognizedInverter (rejected under the default
    allow_unspecified_inverters=False).

GridConnectionPoint, Meter, SolarInverter, WindTurbine, Relay, and
Hvac are exercised by the existing topology-specific tests and so
aren't repeated here. Filtering via matching_types= isn't asserted
because the binding's class-object resolution doesn't follow the
Python class hierarchy for subtypes that aren't hardcoded in
ComponentClasses; plain set membership in graph.components() is
enough to prove acceptance.

Per review feedback on PR frequenz-floss#72.

Signed-off-by: Sahas Subramanian <sahas.subramanian@proton.me>
@shsms shsms force-pushed the cover-all-categories branch from 44547c5 to 58a0d41 Compare May 8, 2026 14:35
shsms added 3 commits May 11, 2026 11:11
Parametrize a small graph over each Python component class the
category mapping handles, and assert the instance ends up in the
graph. Covers every concrete subtype 1594ad3 introduced -- not just
the hardcoded leaves -- so a future regression in the mapping would
fail loudly rather than only being caught once an instance flows
through end-to-end.

Topology per category, picking the smallest valid graph:

  * Battery subtypes (LiIonBattery, NaIonBattery, UnspecifiedBattery,
    UnrecognizedBattery): downstream of a BatteryInverter.
  * EV chargers (Ac/Dc/Hybrid/Unspecified/Unrecognized) and plain
    leaf consumers (Chp, SteamBoiler): leaf below a Meter.
  * Battery- and Hybrid-Inverters: between a Meter and a Battery.
  * Pass-through categories (Converter, CryptoMiner, Electrolyzer,
    Precharger, VoltageTransformer): inline with a SolarInverter
    consumer downstream.

Plus a paired rejection test for the classes whose mapping yields an
Unspecified category, which the cg crate refuses at construction:

  * cg::Unspecified -- UnspecifiedComponent, UnrecognizedComponent.
  * cg::Inverter(Unspecified) -- UnspecifiedInverter,
    UnrecognizedInverter (rejected under the default
    allow_unspecified_inverters=False).

GridConnectionPoint, Meter, SolarInverter, WindTurbine, Relay, and
Hvac are exercised by the existing topology-specific tests and so
aren't repeated here. Filtering via matching_types= isn't asserted
because the binding's class-object resolution doesn't follow the
Python class hierarchy for subtypes that aren't hardcoded in
ComponentClasses; plain set membership in graph.components() is
enough to prove acceptance.

Per review feedback on PR frequenz-floss#72.

Signed-off-by: Sahas Subramanian <sahas.subramanian@proton.me>
Signed-off-by: Sahas Subramanian <sahas.subramanian@proton.me>
Signed-off-by: Sahas Subramanian <sahas.subramanian@proton.me>
@shsms shsms force-pushed the cover-all-categories branch from 58a0d41 to 41b363b Compare May 11, 2026 09:16
@shsms shsms requested review from llucax and simonvoelcker May 11, 2026 09:27
connections = {
ComponentConnection(source=ComponentId(1), destination=ComponentId(2)),
ComponentConnection(source=ComponentId(2), destination=ComponentId(3)),
ComponentConnection(source=ComponentId(3), destination=ComponentId(4)),
Copy link
Copy Markdown
Contributor

@simonvoelcker simonvoelcker May 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this way of wiring things up quite hard to read. I know it's everywhere already, but could we rather do something like this:

connections = {
    ComponentConnection(source=grid.id, destination=meter.id),
    ComponentConnection(source=meter.id, destination=inverter.id),
    ComponentConnection(source=inverter.id, destination=target.id),
}

Copy link
Copy Markdown
Collaborator Author

@shsms shsms May 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made an issue: #73

@shsms shsms added this pull request to the merge queue May 11, 2026
Merged via the queue into frequenz-floss:v0.x.x with commit e97265e May 11, 2026
8 checks passed
@shsms shsms deleted the cover-all-categories branch May 11, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

part:docs Affects the documentation part:tests Affects the unit, integration and performance (benchmarks) tests part:tooling Affects the development tooling (CI, deployment, dependency management, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants