Skip to main content
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=1,
    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 a schedule can take some time. On FlexMeasures v0.33.0 and newer, the convenience method waits on the generic job-status endpoint before retrieving the schedule values. It falls back to result-endpoint polling on older servers.

Trigger and retrieve a schedule for multiple devices:

schedules = await client.trigger_and_get_schedule(
    asset_id=3,
    start="2026-09-05T08:00+02:00",
    duration="PT12H",  # ISO duration
    flex_context={
        "consumption-price": {"sensor": 7},
    },
    flex_model=[
        # Example flex-model for an electric truck at a regular Charge Point
        {
            "sensor": 8,
            "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": "2026-09-05T18:00+02:00"},
            ],
        },
        # Example flex-model for curtailable solar panels
        {
            "sensor": 9,
            "power-capacity": "20 kVA",
            "consumption-capacity": "0 kW",
            "production-capacity": {"sensor": 9},
        },
    ],
)

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 client.trigger_and_get_schedule(
    sensor_id=8,
    start="2026-09-05T08:00+02:00",
    duration="PT12H",  # ISO duration
    flex_context={
        "consumption-price": {"sensor": 7},
    },
    flex_model={
        "soc-at-start": "50 kWh",
        "soc-max": "400 kWh",
        "soc-min": "20 kWh",
        "soc-targets": [
            {"value": "100 kWh", "datetime": "2026-09-05T18: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 client.trigger_schedule(
    **kwargs,  # same kwargs as previous example
)

The trigger_schedule method returns a schedule_uuid. On FlexMeasures v0.33.0 and newer, wait for the job once before retrieving one or more sensor results:

await client.wait_for_job(schedule_uuid)

schedule = await client.get_schedule(
    sensor_id=8,
    schedule_id=schedule_uuid,
    duration="PT45M",  # ISO duration
)

For the complete scheduling API, including multi-device results, job timeouts, and compatibility with older servers, see scheduling.

Forecasting

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

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

On FlexMeasures v0.33.0 and newer, the client polls the generic job endpoint until the forecasting job is complete, then retrieves its values. 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.

Metadata

Release files for flexmeasures-client 0.9.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for flexmeasures-client 0.9.6
File Size Uploaded
flexmeasures_client-0.9.6.tar.gz 525.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for flexmeasures-client 0.9.6
File Interpreter ABI Platform
flexmeasures_client-0.9.6-py3-none-any.whl Python 3 none any Details

Total release size: 584.0 kB

Release files / flexmeasures_client-0.9.6.tar.gz

Download URL flexmeasures_client-0.9.6.tar.gz
Size 525.2 kB
Tags Source
SHA-256 checksum
How to use checksums
966e656b6dd765611d82d17982b56686f10bd60bafe98f3d3ac9b9b53c444ec6
BLAKE2b-256 checksum
How to use checksums
e43e1b5272f9a5e244c699a181f2ab101e7a80c946183b0bd9094a18e30d7a5e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / flexmeasures_client-0.9.6-py3-none-any.whl

Download URL flexmeasures_client-0.9.6-py3-none-any.whl
Size 58.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b707fbb11b8badce93beb8a620f92dc76ca7db69d7da25ecd860106ab1099f28
BLAKE2b-256 checksum
How to use checksums
02fdef3e6a804fd255f14f0c61a947fcbbacda6c0841204821a77d71ea7b1e71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.9.6 This release

2 release files

0.9.5

2 release files

0.9.4

2 release files

0.9.3

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.6

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page