Cover all microgrid client categories in category mapping#72
Conversation
59fca6b to
61598d9
Compare
61598d9 to
74c72cb
Compare
| 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>>, |
There was a problem hiding this comment.
SteamBoiler has been added to microgrid client in v0.18.3.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I'm working on adding all this to the common API client repo (finally). Maybe I have some PR today.
There was a problem hiding this comment.
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.
74c72cb to
30bd915
Compare
30bd915 to
5d3d17f
Compare
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>
5d3d17f to
44547c5
Compare
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>
44547c5 to
58a0d41
Compare
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>
58a0d41 to
41b363b
Compare
| connections = { | ||
| ComponentConnection(source=ComponentId(1), destination=ComponentId(2)), | ||
| ComponentConnection(source=ComponentId(2), destination=ComponentId(3)), | ||
| ComponentConnection(source=ComponentId(3), destination=ComponentId(4)), |
There was a problem hiding this comment.
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),
}
Summary
category_from_python_componentpreviously mapped only a subset ofcg::ComponentCategory. This PR makes it cover every variant.Subtype-aware mapping
Concrete subtype classes from
frequenz.client.microgrid.componentare now mapped to their cg-side subtypes instead of collapsing to
Unspecified:LiIonBattery→Battery(LiIon)NaIonBattery→Battery(NaIon)AcEvCharger→EvCharger(Ac)DcEvCharger→EvCharger(Dc)HybridEvCharger→EvCharger(Hybrid)Inverterparent catchesUnspecifiedInverter/UnrecognizedInverterUnrecognizedComponentjoinsUnspecifiedComponent→cg::UnspecifiedPass-through categories
Now mapped:
Converter,CryptoMiner,Electrolyzer,Hvac,PrechargerRelay→cg::Breaker(the protobuf tag isBREAKER)VoltageTransformer→cg::PowerTransformer(the protobufenum was renamed
VOLTAGE_TRANSFORMER→POWER_TRANSFORMER)Forward compatibility
ComponentClassesmirrors theComponentCategoryenum in
frequenz.client.microgrid.component._categoryso futureclient edits are obvious diffs.
Breaker,PowerTransformer) are probedoptionally — they activate if the client ever renames its classes
to match the protobuf-canonical names.
Plc,StaticTransferSwitch,UninterruptiblePowerSupply,CapacitorBank,SteamBoiler) are also probed optionally so analternative 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/successorswalk past thenode; the PV formula doesn't reference it):
test_relay_is_passthroughtest_hvac_is_passthrough