Skip to content

Index

frequenz.sdk.microgrid ¤

A microgrid is a local electrical grid that connects a set of electrical components together. They are often built around a passive power consumer, to supplement the electricity consumed from the public grid with on-site power generation or storage systems.

Microgrids can also function in island-mode, without a grid connection, or without a local power consumer, but they have to have at least one of the two, to be meaningful.

Frequenz SDK Microgrid Model¤

The SDK aims to provide an abstract model of the microgrid that enables high-level interactions with microgrid components, without having to worry about (or even be aware of) location-specific details such as:

  • where the meters are placed,
  • how many batteries,
  • whether there's a grid connection or a passive consumer,
  • what models the inverters are, etc.
  • whether components are having downtimes, because metrics and limits get adjusted automatically when components are having downtimes.

Users of the SDK can develop applications around this interface once and deploy anywhere, and the SDK will take care of translating the requests and instructions to correspond to the specific microgrid configurations.

flowchart LR

subgraph Left[Measurements only]
direction LR
  grid["Grid Connection"]
  consumer["Consumer"]
  pv["PV Arrays"]
  chp["CHP"]
end

junction(( ))

subgraph Right[Measurements and control]
direction LR
  bat["Batteries"]
  ev["EV Chargers"]
end

grid --- junction
consumer --- junction
pv --- junction
chp --- junction

junction --- bat
junction --- ev

Grid¤

This refers to a microgrid's connection to the external Grid. The power flowing through this connection can be streamed through grid_power.

In locations without a grid connection, this method remains accessible, and streams zero values.

Consumer¤

This is the main power consumer at the site of a microgrid, and often the load the microgrid is built to support. The power drawn by the consumer is available through consumer_power

In locations without a consumer, this method streams zero values.

Producers: PV Arrays, CHP¤

The total CHP production in a site can be streamed through chp_power. PV Power is available through the PV pool described below. And total producer power is available through microgrid.producer().power.

As is the case with the other methods, if PV Arrays or CHPs are not available in a microgrid, the corresponding methods stream zero values.

PV Arrays¤

The total PV power production is available through pv_pool's power. The PV pool by default uses all PV inverters available at a location, but PV pool instances can be created for subsets of PV inverters if necessary, by specifying the inverter ids.

The pv_pool also provides available power bounds through the power_status method.

The pv_pool also provides a control method propose_power, which accepts values in the Passive Sign Convention and supports only production.

Batteries¤

The total Battery power is available through the battery_pool's power. The battery pool by default uses all batteries available at a location, but battery pool instances can be created for subsets of batteries if necessary, by specifying the battery ids.

The battery_pool also provides soc, capacity, temperature and available power bounds through the power_status method.

The battery_pool also provides control methods propose_power (which accepts values in the Passive Sign Convention and supports both charging and discharging), or through propose_charge, or propose_discharge.

EV Chargers¤

The ev_charger_pool offers a power method that streams the total power measured for all the EV Chargers at a site.

The ev_charger_pool also provides available power bounds through the power_status method.

The ev_charger_pool also provides a control method propose_power, which accepts values in the Passive Sign Convention and supports only charging.

Component pools¤

The SDK provides a unified interface for interacting with sets of Batteries, EV chargers and PV arrays, through their corresponding Pools.

All of them provide support for streaming aggregated data and for setting the power values of the components.

Streaming component data¤

All pools have a power property, which is a FormulaEngine that can

  • provide a stream of resampled power values, which correspond to the sum of the power measured from all the components in the pool together.

  • be composed with other power streams to for composite formulas.

In addition, the battery pool has some additional properties that can be used as streams for metrics specific to batteries: soc, capacity and temperature.

Setting power¤

All pools provide a propose_power method for setting power for the pool. This would then be distributed to the individual components in the pool, using an algorithm that's suitable for the category of the components. For example, when controlling batteries, power could be distributed based on the SoC of the individual batteries, to keep the batteries in balance.

Resolving conflicting power proposals¤

When there are multiple actors trying to control the same set of batteries, a target power is calculated based on the priorities of the actors making the requests. Actors need to specify their priorities as parameters when creating the *Pool instances using the constructors mentioned above.

The algorithm used for resolving power conflicts based on actor priority can be found in the documentation for any of the propose_power methods.

Shifting the target power by an Operating Point power¤

There are cases where the target power needs to be shifted by an operating point. This can be done by designating some actors to be able to set only the operating point power.

When creating a *Pool instance using the above-mentioned constructors, an optional set_operating_point parameter can be passed to specify that this actor is special, and the target power of the regular actors will be shifted by the target power of all actors with set_operating_point together.

In a location with 2 regular actors and 1 set_operating_point actor, here's how things would play out:

  1. When only regular actors have made proposals, the power bounds available from the batteries are available to them exactly.
actor priority in op group? proposed power/bounds available bounds
3 No 1000, -4000..2500 -3000..3000
2 No 2500 -3000..2500
1 Yes None -3000..3000

Power actually distributed to the batteries: 2500W

  1. When the set_operating_point actor has made proposals, the bounds available to the regular actors gets shifted, and the final power that actually gets distributed to the batteries is also shifted.
actor priority in op group? proposed power/bounds available bounds
3 No 1000, -4000..2500 -2000..4000
2 No 2500 -2000..2500
1 Yes -1000 -3000..3000

Power actually distributed to the batteries: 1500W

Classes¤

Functions¤

frequenz.sdk.microgrid.consumer ¤

consumer() -> Consumer

Return the Consumption measuring point.

Source code in frequenz/sdk/microgrid/_data_pipeline.py
def consumer() -> Consumer:
    """Return the [`Consumption`][frequenz.sdk.timeseries.consumer.Consumer] measuring point."""
    return _get().consumer()

frequenz.sdk.microgrid.frequency ¤

frequency() -> GridFrequency

Return the grid frequency measuring point.

Source code in frequenz/sdk/microgrid/_data_pipeline.py
def frequency() -> GridFrequency:
    """Return the grid frequency measuring point."""
    return _get().frequency()

frequenz.sdk.microgrid.grid ¤

grid() -> Grid

Return the grid measuring point.

Source code in frequenz/sdk/microgrid/_data_pipeline.py
def grid() -> Grid:
    """Return the grid measuring point."""
    return _get().grid()

frequenz.sdk.microgrid.initialize async ¤

initialize(
    server_url: str,
    resampler_config: ResamplerConfig,
    *,
    api_power_request_timeout: timedelta = timedelta(
        seconds=5.0
    )
) -> None

Initialize the microgrid connection manager and the data pipeline.

PARAMETER DESCRIPTION
server_url

The location of the microgrid API server in the form of a URL. The following format is expected: grpc://hostname{:port}{?ssl=ssl}, where the port should be an int between 0 and 65535 (defaulting to 9090) and ssl should be a boolean (defaulting to false). For example: grpc://localhost:1090?ssl=true.

TYPE: str

resampler_config

Configuration for the resampling actor.

TYPE: ResamplerConfig

api_power_request_timeout

Timeout to use when making power requests to the microgrid API. When requests to components timeout, they will be marked as blocked for a short duration, during which time they will be unavailable from the corresponding component pools.

TYPE: timedelta DEFAULT: timedelta(seconds=5.0)

Source code in frequenz/sdk/microgrid/__init__.py
async def initialize(
    server_url: str,
    resampler_config: ResamplerConfig,
    *,
    api_power_request_timeout: timedelta = timedelta(seconds=5.0),
) -> None:
    """Initialize the microgrid connection manager and the data pipeline.

    Args:
        server_url: The location of the microgrid API server in the form of a URL.
            The following format is expected: `grpc://hostname{:port}{?ssl=ssl}`,
            where the port should be an int between `0` and `65535` (defaulting to
            `9090`) and ssl should be a boolean (defaulting to false). For example:
            `grpc://localhost:1090?ssl=true`.
        resampler_config: Configuration for the resampling actor.
        api_power_request_timeout: Timeout to use when making power requests to
            the microgrid API.  When requests to components timeout, they will
            be marked as blocked for a short duration, during which time they
            will be unavailable from the corresponding component pools.
    """
    await connection_manager.initialize(server_url)
    await _data_pipeline.initialize(
        resampler_config,
        api_power_request_timeout=api_power_request_timeout,
    )

frequenz.sdk.microgrid.logical_meter ¤

logical_meter() -> LogicalMeter

Return the logical meter of the microgrid.

Source code in frequenz/sdk/microgrid/_data_pipeline.py
def logical_meter() -> LogicalMeter:
    """Return the logical meter of the microgrid."""
    return _get().logical_meter()

frequenz.sdk.microgrid.new_battery_pool ¤

new_battery_pool(
    *,
    priority: int,
    component_ids: Set[int] | None = None,
    name: str | None = None,
    set_operating_point: bool = False
) -> BatteryPool

Return a new BatteryPool instance for the given parameters.

The priority value is used to resolve conflicts when multiple actors are trying to propose different power values for the same set of batteries.

Note

When specifying priority, bigger values indicate higher priority.

It is recommended to reuse the same instance of the BatteryPool within the same actor, unless they are managing different sets of batteries.

In deployments with multiple actors managing the same set of batteries, it is recommended to use different priorities to distinguish between them. If not, a random prioritization will be imposed on them to resolve conflicts, which may lead to unexpected behavior like longer duration to converge on the desired power.

PARAMETER DESCRIPTION
priority

The priority of the actor making the call.

TYPE: int

component_ids

Optional set of IDs of batteries to be managed by the BatteryPool. If not specified, all batteries available in the component graph are used.

TYPE: Set[int] | None DEFAULT: None

name

An optional name used to identify this instance of the pool or a corresponding actor in the logs.

TYPE: str | None DEFAULT: None

set_operating_point

Whether this instance sets the operating point power or the normal power for the components.

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
BatteryPool

A BatteryPool instance.

Source code in frequenz/sdk/microgrid/_data_pipeline.py
def new_battery_pool(
    *,
    priority: int,
    component_ids: abc.Set[int] | None = None,
    name: str | None = None,
    set_operating_point: bool = False,
) -> BatteryPool:
    """Return a new `BatteryPool` instance for the given parameters.

    The priority value is used to resolve conflicts when multiple actors are trying to
    propose different power values for the same set of batteries.

    !!! note
        When specifying priority, bigger values indicate higher priority.

        It is recommended to reuse the same instance of the `BatteryPool` within the
        same actor, unless they are managing different sets of batteries.

        In deployments with multiple actors managing the same set of batteries, it is
        recommended to use different priorities to distinguish between them.  If not,
        a random prioritization will be imposed on them to resolve conflicts, which may
        lead to unexpected behavior like longer duration to converge on the desired
        power.

    Args:
        priority: The priority of the actor making the call.
        component_ids: Optional set of IDs of batteries to be managed by the
            `BatteryPool`.  If not specified, all batteries available in the component
            graph are used.
        name: An optional name used to identify this instance of the pool or a
            corresponding actor in the logs.
        set_operating_point: Whether this instance sets the operating point power or the
            normal power for the components.

    Returns:
        A `BatteryPool` instance.
    """
    return _get().new_battery_pool(
        priority=priority,
        component_ids=component_ids,
        name=name,
        set_operating_point=set_operating_point,
    )

frequenz.sdk.microgrid.new_ev_charger_pool ¤

new_ev_charger_pool(
    *,
    priority: int,
    component_ids: Set[int] | None = None,
    name: str | None = None,
    set_operating_point: bool = False
) -> EVChargerPool

Return a new EVChargerPool instance for the given parameters.

The priority value is used to resolve conflicts when multiple actors are trying to propose different power values for the same set of EV chargers.

Note

When specifying priority, bigger values indicate higher priority.

It is recommended to reuse the same instance of the EVChargerPool within the same actor, unless they are managing different sets of EV chargers.

In deployments with multiple actors managing the same set of EV chargers, it is recommended to use different priorities to distinguish between them. If not, a random prioritization will be imposed on them to resolve conflicts, which may lead to unexpected behavior like longer duration to converge on the desired power.

PARAMETER DESCRIPTION
priority

The priority of the actor making the call.

TYPE: int

component_ids

Optional set of IDs of EV Chargers to be managed by the EVChargerPool. If not specified, all EV Chargers available in the component graph are used.

TYPE: Set[int] | None DEFAULT: None

name

An optional name used to identify this instance of the pool or a corresponding actor in the logs.

TYPE: str | None DEFAULT: None

set_operating_point

Whether this instance sets the operating point power or the normal power for the components.

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
EVChargerPool

An EVChargerPool instance.

Source code in frequenz/sdk/microgrid/_data_pipeline.py
def new_ev_charger_pool(
    *,
    priority: int,
    component_ids: abc.Set[int] | None = None,
    name: str | None = None,
    set_operating_point: bool = False,
) -> EVChargerPool:
    """Return a new `EVChargerPool` instance for the given parameters.

    The priority value is used to resolve conflicts when multiple actors are trying to
    propose different power values for the same set of EV chargers.

    !!! note
        When specifying priority, bigger values indicate higher priority.

        It is recommended to reuse the same instance of the `EVChargerPool` within the
        same actor, unless they are managing different sets of EV chargers.

        In deployments with multiple actors managing the same set of EV chargers, it is
        recommended to use different priorities to distinguish between them.  If not,
        a random prioritization will be imposed on them to resolve conflicts, which may
        lead to unexpected behavior like longer duration to converge on the desired
        power.

    Args:
        priority: The priority of the actor making the call.
        component_ids: Optional set of IDs of EV Chargers to be managed by the
            EVChargerPool.  If not specified, all EV Chargers available in the
            component graph are used.
        name: An optional name used to identify this instance of the pool or a
            corresponding actor in the logs.
        set_operating_point: Whether this instance sets the operating point power or the
            normal power for the components.

    Returns:
        An `EVChargerPool` instance.
    """
    return _get().new_ev_charger_pool(
        priority=priority,
        component_ids=component_ids,
        name=name,
        set_operating_point=set_operating_point,
    )

frequenz.sdk.microgrid.new_pv_pool ¤

new_pv_pool(
    *,
    priority: int,
    component_ids: Set[int] | None = None,
    name: str | None = None,
    set_operating_point: bool = False
) -> PVPool

Return a new PVPool instance for the given parameters.

The priority value is used to resolve conflicts when multiple actors are trying to propose different power values for the same set of PV inverters.

Note

When specifying priority, bigger values indicate higher priority.

It is recommended to reuse the same instance of the PVPool within the same actor, unless they are managing different sets of PV inverters.

In deployments with multiple actors managing the same set of PV inverters, it is recommended to use different priorities to distinguish between them. If not, a random prioritization will be imposed on them to resolve conflicts, which may lead to unexpected behavior like longer duration to converge on the desired power.

PARAMETER DESCRIPTION
priority

The priority of the actor making the call.

TYPE: int

component_ids

Optional set of IDs of PV inverters to be managed by the PVPool. If not specified, all PV inverters available in the component graph are used.

TYPE: Set[int] | None DEFAULT: None

name

An optional name used to identify this instance of the pool or a corresponding actor in the logs.

TYPE: str | None DEFAULT: None

set_operating_point

Whether this instance sets the operating point power or the normal power for the components.

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
PVPool

A PVPool instance.

Source code in frequenz/sdk/microgrid/_data_pipeline.py
def new_pv_pool(
    *,
    priority: int,
    component_ids: abc.Set[int] | None = None,
    name: str | None = None,
    set_operating_point: bool = False,
) -> PVPool:
    """Return a new `PVPool` instance for the given parameters.

    The priority value is used to resolve conflicts when multiple actors are trying to
    propose different power values for the same set of PV inverters.

    !!! note
        When specifying priority, bigger values indicate higher priority.

        It is recommended to reuse the same instance of the `PVPool` within the same
        actor, unless they are managing different sets of PV inverters.

        In deployments with multiple actors managing the same set of PV inverters, it is
        recommended to use different priorities to distinguish between them.  If not,
        a random prioritization will be imposed on them to resolve conflicts, which may
        lead to unexpected behavior like longer duration to converge on the desired
        power.

    Args:
        priority: The priority of the actor making the call.
        component_ids: Optional set of IDs of PV inverters to be managed by the
            `PVPool`. If not specified, all PV inverters available in the component
            graph are used.
        name: An optional name used to identify this instance of the pool or a
            corresponding actor in the logs.
        set_operating_point: Whether this instance sets the operating point power or the
            normal power for the components.

    Returns:
        A `PVPool` instance.
    """
    return _get().new_pv_pool(
        priority=priority,
        component_ids=component_ids,
        name=name,
        set_operating_point=set_operating_point,
    )

frequenz.sdk.microgrid.producer ¤

producer() -> Producer

Return the Production measuring point.

Source code in frequenz/sdk/microgrid/_data_pipeline.py
def producer() -> Producer:
    """Return the [`Production`][frequenz.sdk.timeseries.producer.Producer] measuring point."""
    return _get().producer()

frequenz.sdk.microgrid.voltage_per_phase ¤

voltage_per_phase() -> VoltageStreamer

Return the per-phase voltage measuring point.

Source code in frequenz/sdk/microgrid/_data_pipeline.py
def voltage_per_phase() -> VoltageStreamer:
    """Return the per-phase voltage measuring point."""
    return _get().voltage_per_phase()