Skip to content

Introduce the BatteryPool, and implement power bounds calculation for the pool#32

Merged
shsms merged 18 commits into
frequenz-floss:v0.x.xfrom
shsms:pool
Apr 22, 2026
Merged

Introduce the BatteryPool, and implement power bounds calculation for the pool#32
shsms merged 18 commits into
frequenz-floss:v0.x.xfrom
shsms:pool

Conversation

@shsms
Copy link
Copy Markdown
Collaborator

@shsms shsms commented Apr 20, 2026

This PR introduces a high-level BatteryPool API and supporting telemetry/bounds trackers to compute aggregated dispatch power bounds for a pool of batteries (grouped by inverter↔battery topology), along with a refactor of formula streaming APIs to use metric generics.

Changes:

  • Add battery pool telemetry tracking (healthy/unhealthy partitioning with latest telemetry) and bounds aggregation across inverter-battery groups.
  • Expose Microgrid/BatteryPool as public high-level APIs and add a bounds example.

@shsms
Copy link
Copy Markdown
Collaborator Author

shsms commented Apr 20, 2026

Based on #31

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a high-level BatteryPool API and supporting telemetry/bounds trackers to compute aggregated dispatch power bounds for a pool of batteries (grouped by inverter↔battery topology), along with a refactor of formula streaming APIs to use metric generics.

Changes:

  • Add battery pool snapshot tracking (healthy/unhealthy partitioning with latest telemetry) and bounds aggregation across inverter-battery groups.
  • Expose Microgrid/BatteryPool as public high-level APIs and add a bounds example.
  • Refactor LogicalMeterHandle formula constructors to take metrics as generic parameters (and adjust metric/formula plumbing accordingly).

Reviewed changes

Copilot reviewed 29 out of 29 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/quantity.rs Extend Quantity with min/max constants and float-like ops used by bounds logic.
src/bounds.rs Add bounds set operations (add/intersect/squash) and PbBounds conversions.
src/microgrid/battery_pool.rs New BatteryPool API exposing pool power and power-bounds streams.
src/microgrid/battery_bounds_tracker.rs Aggregate bounds from telemetry snapshots across groups (parallel/series topology).
src/microgrid/telemetry_tracker.rs New module root for telemetry trackers.
src/microgrid/telemetry_tracker/battery_pool_snapshot_tracker.rs Build inverter-battery groups from the graph; broadcast pool snapshots.
src/microgrid/telemetry_tracker/inverter_battery_group_telemetry_tracker.rs Track telemetry/health for each inverter-battery group and emit group status.
src/microgrid/telemetry_tracker/component_telemetry_tracker.rs Classify a component stream as healthy/unhealthy based on state codes and freshness.
src/microgrid.rs Introduce Microgrid high-level entry point and wire up battery pool creation.
src/metric.rs Add metric string name helper and new DcPower metric.
src/logical_meter/logical_meter_handle.rs Switch formula constructors to generic metrics and expose graph() accessor.
src/logical_meter/logical_meter_actor.rs Update proto import paths.
src/logical_meter/formula/graph_formula_provider.rs Remove metric value plumbing from formula params; rely on metric type instead.
src/logical_meter/formula/coalesce_formula.rs Replace stored metric value with PhantomData.
src/logical_meter/formula/aggregation_formula.rs Replace stored metric value with PhantomData.
src/logical_meter/formula.rs Update FormulaParams to remove metric value and use PhantomData.
src/logical_meter/config.rs Update proto import path.
src/lib.rs Export new Microgrid and BatteryPool public API.
src/error.rs Add ComponentDataError and conversion from component-graph errors.
src/client/test_utils.rs Extend mocks with state overrides and silent streams for timeout testing.
src/client/proto/electrical_component.rs Import path cleanups.
src/client/microgrid_client_handle.rs Import path cleanups in implementation and tests.
src/client/microgrid_client_actor.rs Import path cleanups and request type path fix.
src/client/microgrid_api_client.rs Import path cleanups for generated client type.
src/client/instruction.rs Import path cleanups.
src/client.rs Make client::proto public.
examples/logical_meter.rs Update example to new generic-metric formula API.
examples/bounds.rs New example demonstrating battery pool power bounds streaming.
RELEASE_NOTES.md Document the LogicalMeterHandle API change to generic metric arguments.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/microgrid/battery_pool.rs Outdated
Comment thread src/bounds.rs Outdated
Comment thread src/bounds.rs Outdated
Comment thread src/microgrid/battery_bounds_tracker.rs
Comment thread src/microgrid/telemetry_tracker/component_telemetry_tracker.rs
Comment thread src/microgrid/telemetry_tracker/battery_pool_telemetry_tracker.rs
Comment thread src/microgrid/telemetry_tracker/battery_pool_telemetry_tracker.rs
@shsms shsms force-pushed the pool branch 5 times, most recently from a4b8447 to e2a3f27 Compare April 21, 2026 13:26
@shsms shsms requested a review from Copilot April 21, 2026 13:30
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 30 out of 30 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/microgrid/telemetry_tracker/component_telemetry_tracker.rs
Comment thread src/logical_meter/formula/graph_formula_provider.rs
Comment thread src/bounds.rs
Comment thread src/microgrid/battery_pool.rs
Comment thread RELEASE_NOTES.md
shsms added 18 commits April 21, 2026 16:44
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>
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>
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>
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>
This returns `BatteryPoolSnapshot` instances with the latest telemetry
from all batteries and attached inverters, grouped by whether they're
healthy or not.

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>
Signed-off-by: Sahas Subramanian <sahas.subramanian@proton.me>
This way, they don't have to be specified from the CLI each time.

Signed-off-by: Sahas Subramanian <sahas.subramanian@proton.me>
Signed-off-by: Sahas Subramanian <sahas.subramanian@proton.me>
@shsms shsms marked this pull request as ready for review April 21, 2026 14:45
Comment on lines +116 to +120
/// Returns a receiver for a stream of [`BatteryPoolSnapshot`] values,
/// each reflecting the latest component telemetry partitioned into
/// healthy and unhealthy sets.
///
/// Reuses the running tracker if one exists and still has active receivers
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This reuse condition means a late subscriber can keep the existing tracker alive indefinitely. In practice the task lifetime becomes "someone still has a receiver" rather than "the original caller still cares". That may be fine, but it would be good to call it out explicitly in the API/docs so the lifecycle is clear.

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.

Yes, but I'd say it is irrelevant to the user of the high level API. Now that I think about it, the Reuses* line is also too much info. That was not me, that was the AI. But will cleanup later.

Comment on lines +162 to +175
match battery_status {
ComponentHealthStatus::Healthy(component_id, data) => {
healthy_batteries.insert(component_id, data);
unhealthy_batteries.remove(&component_id);
}
ComponentHealthStatus::Unhealthy(component_id, data) => {
unhealthy_batteries.insert(component_id, data);
healthy_batteries.remove(&component_id);
}
}
}
}
if let Err(e) = self
.status_tx
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This tracker emits a full group snapshot on every single component update, and the debounce lives one layer up in BatteryPoolTelemetryTracker. That works, but it spreads the emission policy across two layers. Consider either debouncing here, or extracting a small reusable debounce/coalesce helper so the "when do we emit?" logic lives in one place.

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.

This is true, I'll simplify in the next PR.

@shsms shsms added this pull request to the merge queue Apr 22, 2026
Merged via the queue into frequenz-floss:v0.x.x with commit 2aa9de3 Apr 22, 2026
3 checks passed
@shsms shsms deleted the pool branch April 22, 2026 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants