Skip to main content

Async client to connect to the FlexMeasures API

Project description

FlexMeasures Logo License Tests PyPI Version Python 3.9+ Code style: black Coverage

FlexMeasures Client

The FlexMeasures Client provides a Python package to connect to a FlexMeasures server to manage flexible assets.

The Flexmeasures Client package provides functionality for authentication, asset and sensor management, posting sensor data, and triggering and retrieving schedules from a FlexMeasures instance through the API.

As the Flexmeasures Client is still in active development and on version 0.x it should be considered in beta.

Installation

We use uv to manage dependencies. First, install uv.

Then add it to your project:

uv add flexmeasures-client

The FlexMeasures Client can also run as an S2 CEM. To enable S2 features, you need to install extra requirements:

uv add flexmeasures-client[s2]

Initialization and authentication

To get started with the FlexMeasures Client, first an account needs to be registered with a FlexMeasures instance. To create a local instance of FlexMeasures, follow the FlexMeasures documentation. Registering to a hosted FlexMeasures instance instead can be done through Seita BV.

In these examples we show how to set up the client to connect to either http://localhost:5000 or https://ems.seita.energy. To connect to a different host, adapt the host in the initialization of the client.

from flexmeasures_client import FlexMeasuresClient

async def main():
    client = FlexMeasuresClient(host="localhost:5000", ssl=False, email="email@email.com", password="pw")
    client = FlexMeasuresClient(host="ems.seita.energy", ssl=True, email="email@email.com", password="pw")

Retrieving available info

Retrieve user and account:

user = await client.get_user()
account = await client.get_account()

The data will be returned as a dictionary.

Retrieve available assets and sensors:

assets = await client.get_assets()
sensors = await client.get_sensors()

The data will be returned as (lists of) dictionaries.

Sending data

Post a measurement from a sensor:

await client.post_sensor_data(
    sensor_id=<sensor_id>,  # integer
    start="2023-03-26T10:00+02:00",  # ISO datetime
    duration="PT6H",  # ISO duration
    values=[1, 2, 3, 4],  # list
    unit="kWh",
)

Here is a small but complete FlexMeasures Client script, which simply updates the flex context of an asset:

import asyncio

from flexmeasures_client import FlexMeasuresClient

usr = "xxxxxxxxxxxxxxxx"
pwd = "xxxxxxxxxxxxxxxx"
asset_id = 1


async def main():
    client = FlexMeasuresClient(email=usr, password=pwd)

    asset = await client.update_asset(
        asset_id=asset_id,
        updates={
            "flex_context": {
                "site-consumption-capacity": "110 kW",
                "relax-constraints": True
            }
        },
    )

    print(asset)

    await client.close()


asyncio.run(main())

For a slightly larger self-contained script, see this script for sending data. It sets up an asset and sensor (checking if they exist first), and then sends data to it using post_sensor_data().

Scheduling

With FlexMeasures a schedule can be requested to optimize at what time the flexible assets can be activated to optimize for price of energy or emissions.

The calculation of the schedule can take some time depending on the complexity of the calculations. A polling function is used to check if a schedule is available after triggering the schedule.

Trigger and retrieve a schedule for multiple devices:

schedule = await flexmeasures_client.trigger_and_get_schedule(
    asset_id=<asset_id>,  # the asset ID (int) of the asset that all relevant power sensors belong to (or live under, in case of a tree-like asset structure)
    start="2023-03-26T10:00+02:00",  # ISO datetime
    duration="PT12H",  # ISO duration
    flex_context={
        "consumption-price": {"sensor": <consumption_price_sensor_id>},  # int
    },
    flex-model=[
        # Example flex-model for an electric truck at a regular Charge Point
        {
            "sensor": <power_sensor_id>,  # int
            "power-capacity": "22 kVA",
            "production-capacity": "0 kW",
            "soc-at-start": "50 kWh",
            "soc-max": "400 kWh",
            "soc-min": "20 kWh",
            "soc-targets": [
                {"value": "100 kWh", "datetime": "2023-03-03T11:00+02:00"},
            ],
        },
        # Example flex-model for curtailable solar panels
        {
            "sensor": <another_power_sensor_id>,  # int
            "power-capacity": "20 kVA",
            "consumption-capacity": "0 kW",
            "production-capacity": {"sensor": <another_power_sensor_id>},  # int
        },
    ],
)

For triggering and retrieving a schedule for a single device, simply limit the flex-model to list a single device. Alternatively, use a single-device flex-model (no list) and move the device’s power sensor ID out of the flex-model and use it as the sensor ID in the call to trigger_and_get_schedule (and leave out the asset ID).

schedule = await flexmeasures_client.trigger_and_get_schedule(
    sensor_id=<sensor_id>,  # int
    start="2023-03-26T10:00+02:00",  # ISO datetime
    duration="PT12H",  # ISO duration
    flex_context={
        "consumption-price": {"sensor": <consumption_price_sensor_id>},  # int
    },
    flex-model={
        "soc-at-start": "50 kWh",
        "soc-max": "400 kWh",
        "soc-min": "20 kWh",
        "soc-targets": [
            {"value": "100 kWh", "datetime": "2023-03-03T11:00+02:00"},
        ],
    },
)

The trigger and get schedule function can also be separated to trigger the schedule first and later retrieve the schedule using the schedule_uuid.

Trigger a schedule:

schedule_uuid = await flexmeasures_client.trigger_schedule(
    **kwargs,  # same kwargs as previous example
)

The trigger_schedule method returns a schedule_uuid. This can be used to retrieve the schedule, using:

schedule = await flexmeasures_client.get_schedule(
    sensor_id=<sensor_id>,  # int
    schedule_id="<schedule_uuid>",  # uuid
    duration="PT45M",  # ISO duration
)

The client will re-try until the schedule is available or the MAX_POLLING_STEPS of 10 is reached.

Forecasting

Trigger a forecast for a sensor and wait for the result:

forecast = await client.trigger_and_get_forecast(
    sensor_id=<sensor_id>,  # int
    duration="PT24H",  # ISO duration – how far ahead to forecast
)
# Returns e.g. {"values": [1.2, 1.5, ...], "start": "...", "duration": "PT24H", "unit": "kW"}

The client polls until the forecasting job is complete. For more advanced options (training window, regressors, forecast frequency, etc.) see forecasting.

Development

We use uv to manage dependencies. First, install uv.

To install the package with all development and testing dependencies:

uv sync --group dev --group test

Moreover, if you need to work on S2 features, you need to install extra dependencies:

uv sync --extra s2 --group dev --group test

Making Changes & Contributing

Install the project locally (creating a virtual environment automatically):

uv sync

Running tests locally is crucial as well:

uv run poe test

For S2 features:

uv sync --extra s2 --group test
uv run poe test-s2

This project uses pre-commit, please make sure to install it before making any changes:

uv tool install pre-commit
cd flexmeasures-client
pre-commit install

It is a good idea to update the hooks to the latest version:

pre-commit autoupdate

Don’t forget to tell your contributors to also install and use pre-commit.

New releases on PyPI are made by adding a tag and pushing it:

git tag -s -a vX.Y.Z -m "Short summary"
git push --tags

(of course you need the permissions to do so)

See releases in GitHub Actions at https://github.com/FlexMeasures/flexmeasures-client/deployments/release

HEMS tutorial

The FlexMeasures Client comes with a tutorial for creating a Home Energy Management System (HEMS) See the Usage docs.

S2 CEM

The FlexMeasures Client can also be run as a local S2 Customer Energy Manager (CEM) using WebSocket communication. See here for the docs, which includes a docker-compose stack.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flexmeasures_client-0.9.1.tar.gz (420.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flexmeasures_client-0.9.1-py3-none-any.whl (52.8 kB view details)

Uploaded Python 3

File details

Details for the file flexmeasures_client-0.9.1.tar.gz.

File metadata

  • Download URL: flexmeasures_client-0.9.1.tar.gz
  • Upload date:
  • Size: 420.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for flexmeasures_client-0.9.1.tar.gz
Algorithm Hash digest
SHA256 df60753c86b41daf455d6de7759bf17f11de35e571f26afaff3120fdfa1934f6
MD5 d4ddefb4e6ec04ad3e207ec7eedcaceb
BLAKE2b-256 1e1e4b25bac133cead021ee89ea585e8d0afd0d5d675bff7149a7fb4035ab05c

See more details on using hashes here.

Provenance

The following attestation bundles were made for flexmeasures_client-0.9.1.tar.gz:

Publisher: release.yml on FlexMeasures/flexmeasures-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file flexmeasures_client-0.9.1-py3-none-any.whl.

File metadata

File hashes

Hashes for flexmeasures_client-0.9.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6e05c637d244cc44d760d47dec66adaaa773886deba2b9a0ae6694ed38ddb071
MD5 6a1581a9deab570cc914c52be76ad6f7
BLAKE2b-256 930cc4e0c8e25f99d16fbed04b046ec79993bb07a3bf5776da2403d4fa9a1a2a

See more details on using hashes here.

Provenance

The following attestation bundles were made for flexmeasures_client-0.9.1-py3-none-any.whl:

Publisher: release.yml on FlexMeasures/flexmeasures-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page