flexmeasures.api.v3_0.sensors
Classes
- class flexmeasures.api.v3_0.sensors.SensorAPI
- delete(id: int, sensor: Sensor)
Delete a sensor given its identifier.
This endpoint deletes an existing sensor, as well as all measurements recorded for it.
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 204:
DELETED
- Status 400:
INVALID_REQUEST, REQUIRED_INFO_MISSING, UNEXPECTED_PARAMS
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 422:
UNPROCESSABLE_ENTITY
- delete_data(id: int, sensor: Sensor)
Delete all data for a sensor.
This endpoint deletes all data for a sensor.
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 204:
DELETED
- Status 400:
INVALID_REQUEST, REQUIRED_INFO_MISSING, UNEXPECTED_PARAMS
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 422:
UNPROCESSABLE_ENTITY
- fetch_one(id, sensor)
Fetch a given sensor.
This endpoint gets a sensor.
Example response
{ "name": "some gas sensor", "unit": "m³/h", "entity_address": "ea1.2023-08.localhost:fm1.1", "event_resolution": "PT10M", "generic_asset_id": 4, "timezone": "UTC", "id": 2 }
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 200:
PROCESSED
- Status 400:
INVALID_REQUEST, REQUIRED_INFO_MISSING, UNEXPECTED_PARAMS
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 422:
UNPROCESSABLE_ENTITY
- get_data(sensor_data_description: dict)
Get sensor data from FlexMeasures.
Example request
{ "sensor": "ea1.2021-01.io.flexmeasures:fm1.1", "start": "2021-06-07T00:00:00+02:00", "duration": "PT1H", "resolution": "PT15M", "unit": "m³/h" }
The unit has to be convertible from the sensor’s unit.
Optional fields
“resolution” (see Frequency and resolution)
“horizon” (see Tracking the recording time of beliefs)
“prior” (see Tracking the recording time of beliefs)
“source” (see Sources)
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 200:
PROCESSED
- Status 400:
INVALID_REQUEST
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 422:
UNPROCESSABLE_ENTITY
- get_schedule(sensor: Sensor, job_id: str, duration: timedelta, **kwargs)
Get a schedule from FlexMeasures.
Optional fields
“duration” (6 hours by default; can be increased to plan further into the future)
Example response
This message contains a schedule indicating to consume at various power rates from 10am UTC onwards for a duration of 45 minutes.
{ "values": [ 2.15, 3, 2 ], "start": "2015-06-02T10:00:00+00:00", "duration": "PT45M", "unit": "MW" }
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 200:
PROCESSED
- Status 400:
INVALID_TIMEZONE, INVALID_DOMAIN, INVALID_UNIT, UNKNOWN_SCHEDULE, UNRECOGNIZED_CONNECTION_GROUP
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 405:
INVALID_METHOD
- Status 422:
UNPROCESSABLE_ENTITY
- get_stats(id, sensor: Sensor, event_start_time: str, event_end_time: str, sort_keys: bool)
Fetch stats for a given sensor.
This endpoint fetches sensor stats for all the historical data.
Example response
{ "some data source": { "First event start": "2015-06-02T10:00:00+00:00", "Last event end": "2015-10-02T10:00:00+00:00", "Last recorded": "2015-10-02T10:01:12+00:00", "Min value": 0.0, "Max value": 100.0, "Mean value": 50.0, "Sum over values": 500.0, "Number of values": 10 } }
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 200:
PROCESSED
- Status 400:
INVALID_REQUEST, REQUIRED_INFO_MISSING, UNEXPECTED_PARAMS
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 422:
UNPROCESSABLE_ENTITY
- get_status(id, sensor)
Fetch the current status for a given sensor.
This endpoint fetches the current status data for the specified sensor. The status includes information about the sensor’s status, staleness and resolution.
Example response:
[ { 'staleness': None, 'stale': True, 'staleness_since': None, 'reason': 'no data recorded', 'source_type': None, 'id': 64906, 'name': 'power', 'resolution': '15 minutes', 'asset_name': 'Location 1', 'relation': 'sensor belongs to this asset' } ]
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 200:
PROCESSED
- Status 400:
INVALID_REQUEST, REQUIRED_INFO_MISSING, UNEXPECTED_PARAMS
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 404:
ASSET_NOT_FOUND
- Status 422:
UNPROCESSABLE_ENTITY
- index(account: Account | None = None, asset: GenericAsset | None = None, include_consultancy_clients: bool = False, include_public_assets: bool = False, page: int | None = None, per_page: int | None = None, filter: list[str] | None = None, unit: str | None = None)
API endpoint to list all sensors of an account.
This endpoint returns all accessible sensors. By default, “accessible sensors” means all sensors in the same account as the current user (if they have read permission to the account).
You can also specify an account (an ID parameter), if the user has read access to that account. In this case, all assets under the specified account will be retrieved, and the sensors associated with these assets will be returned.
Alternatively, you can filter by asset hierarchy by providing the asset parameter (ID). When this is set, all sensors on the specified asset and its sub-assets are retrieved, provided the user has read access to the asset.
NOTE: You can’t set both account and asset at the same time, you can only have one set. The only exception is if the asset being specified is part of the account that was set, then we allow to see sensors under that asset but then ignore the account (account = None).
Finally, you can use the include_consultancy_clients parameter to include sensors from accounts for which the current user account is a consultant. This is only possible if the user has the role of a consultant.
Only admins can use this endpoint to fetch sensors from a different account (by using the account_id query parameter).
The filter parameter allows you to search for sensors by name or account name. The unit parameter allows you to filter by unit.
For the pagination of the sensor list, you can use the page and per_page query parameters, the page parameter is used to trigger pagination, and the per_page parameter is used to specify the number of records per page. The default value for page is 1 and for per_page is 10.
Example response
An example of one sensor being returned:
{ "data" : [ { "entity_address": "ea1.2021-01.io.flexmeasures.company:fm1.42", "event_resolution": PT15M, "generic_asset_id": 1, "name": "Gas demand", "timezone": "Europe/Amsterdam", "unit": "m³/h" "id": 2 } ], "num-records" : 1, "filtered-records" : 1 }
If no pagination is requested, the response only consists of the list under the “data” key.
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 200:
PROCESSED
- Status 400:
INVALID_REQUEST
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 422:
UNPROCESSABLE_ENTITY
- patch(sensor_data: dict, id: int, sensor: Sensor)
Update a sensor given its identifier.
This endpoint updates the descriptive data of an existing sensor.
Any subset of sensor fields can be sent. However, the following fields are not allowed to be updated: - id - generic_asset_id - entity_address
Only admin users have rights to update the sensor fields. Be aware that changing unit, event resolution and knowledge horizon should currently only be done on sensors without existing belief data (to avoid a serious mismatch), or if you really know what you are doing.
Example request
{ "name": "POWER", }
Example response
The whole sensor is returned in the response:
{ "name": "some gas sensor", "unit": "m³/h", "entity_address": "ea1.2023-08.localhost:fm1.1", "event_resolution": "PT10M", "generic_asset_id": 4, "timezone": "UTC", "id": 2 }
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 200:
UPDATED
- Status 400:
INVALID_REQUEST, REQUIRED_INFO_MISSING, UNEXPECTED_PARAMS
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 422:
UNPROCESSABLE_ENTITY
- post(sensor_data: dict)
Create new sensor.
This endpoint creates a new Sensor.
Example request
{ "name": "power", "event_resolution": "PT1H", "unit": "kWh", "generic_asset_id": 1, }
Example response
The whole sensor is returned in the response:
{ "name": "power", "unit": "kWh", "entity_address": "ea1.2023-08.localhost:fm1.1", "event_resolution": "PT1H", "generic_asset_id": 1, "timezone": "UTC", "id": 2 }
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 201:
CREATED
- Status 400:
INVALID_REQUEST
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 422:
UNPROCESSABLE_ENTITY
- post_data(bdf: BeliefsDataFrame)
Post sensor data to FlexMeasures.
Example request
{ "sensor": "ea1.2021-01.io.flexmeasures:fm1.1", "values": [-11.28, -11.28, -11.28, -11.28], "start": "2021-06-07T00:00:00+02:00", "duration": "PT1H", "unit": "m³/h" }
The above request posts four values for a duration of one hour, where the first event start is at the given start time, and subsequent events start in 15 minute intervals throughout the one hour duration.
The sensor is the one with ID=1. The unit has to be convertible to the sensor’s unit. The resolution of the data has to match the sensor’s required resolution, but FlexMeasures will attempt to upsample lower resolutions. The list of values may include null values.
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 200:
PROCESSED
- Status 400:
INVALID_REQUEST
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 422:
UNPROCESSABLE_ENTITY
- trigger_schedule(sensor: Sensor, start_of_schedule: datetime, duration: timedelta, belief_time: datetime | None = None, flex_model: dict | None = None, flex_context: dict | None = None, force_new_job_creation: bool | None = False, **kwargs)
Trigger FlexMeasures to create a schedule for a single flexible device, possibly taking into account inflexible devices.
Trigger FlexMeasures to create a schedule for this sensor. The assumption is that this sensor is the power sensor on a flexible asset.
In this request, you can describe:
the schedule’s main features (when does it start, what unit should it report, prior to what time can we assume knowledge)
the flexibility model for the sensor (state and constraint variables, e.g. current state of charge of a battery, or connection capacity)
the flexibility context which the sensor operates in (other sensors under the same EMS which are relevant, e.g. prices)
For details on flexibility model and context, see Describing flexibility. Below, we’ll also list some examples.
Note
To schedule an EMS with multiple flexible sensors at once, use this endpoint instead.
The length of the schedule can be set explicitly through the ‘duration’ field. Otherwise, it is set by the config setting FLEXMEASURES_PLANNING_HORIZON, which defaults to 48 hours. If the flex-model contains targets that lie beyond the planning horizon, the length of the schedule is extended to accommodate them. Finally, the schedule length is limited by max_planning_horizon_config, which defaults to 2520 steps of the sensor’s resolution. Targets that exceed the max planning horizon are not accepted.
The appropriate algorithm is chosen by FlexMeasures (based on asset type). It’s also possible to use custom schedulers and custom flexibility models, see Plugin Customization.
If you have ideas for algorithms that should be part of FlexMeasures, let us know: https://flexmeasures.io/get-in-touch/
Example request A
This message triggers a schedule for a storage asset, starting at 10.00am, at which the state of charge (soc) is 12.1 kWh.
{ "start": "2015-06-02T10:00:00+00:00", "flex-model": { "soc-at-start": "12.1 kWh" } }
Example request B
This message triggers a 24-hour schedule for a storage asset, starting at 10.00am, at which the state of charge (soc) is 12.1 kWh, with a target state of charge of 25 kWh at 4.00pm.
The charging efficiency is constant (120%) and the discharging efficiency is determined by the contents of sensor with id 98. If just the
roundtrip-efficiency
is known, it can be described with its own field. The global minimum and maximum soc are set to 10 and 25 kWh, respectively. To guarantee a minimum SOC in the period prior, the sensor with ID 300 contains beliefs at 2.00pm and 3.00pm, for 15kWh and 20kWh, respectively. Storage efficiency is set to 99.99%, denoting the state of charge left after each time step equal to the sensor’s resolution. Aggregate consumption (of all devices within this EMS) should be priced by sensor 9, and aggregate production should be priced by sensor 10, where the aggregate power flow in the EMS is described by the sum over sensors 13, 14, 15, and the power sensor of the flexible device being optimized (referenced in the endpoint URL).The battery consumption power capacity is limited by sensor 42 and the production capacity is constant (30 kW).
Finally, the (contractual and physical) situation of the site is part of the flex-context. The site has a physical power capacity of 100 kVA, but the production capacity is limited to 80 kW, while the consumption capacity is limited by a dynamic capacity contract whose values are recorded under sensor 32. Breaching either capacity is penalized heavily in the optimization problem, with a price of 1000 EUR/kW. Finally, peaks over 50 kW in either direction are penalized with a price of 260 EUR/MW. These penalties can be used to steer the schedule into a certain behaviour (e.g. avoiding breaches and peaks), even if no direct financial impacts are expected at the given prices in the real world. For example, site owners may be requested by their network operators to reduce stress on the grid, be it explicitly or under a social contract.
Note that, if forecasts for sensors 13, 14 and 15 are not available, a schedule cannot be computed.
{ "start": "2015-06-02T10:00:00+00:00", "duration": "PT24H", "flex-model": { "soc-at-start": "12.1 kWh", "state-of-charge" : {"sensor" : 24}, "soc-targets": [ { "value": "25 kWh", "datetime": "2015-06-02T16:00:00+00:00" }, ], "soc-minima": {"sensor" : 300}, "soc-min": "10 kWh", "soc-max": "25 kWh", "charging-efficiency": "120%", "discharging-efficiency": {"sensor": 98}, "storage-efficiency": 0.9999, "power-capacity": "25kW", "consumption-capacity" : {"sensor": 42}, "production-capacity" : "30 kW" }, "flex-context": { "consumption-price": {"sensor": 9}, "production-price": {"sensor": 10}, "inflexible-device-sensors": [13, 14, 15], "site-power-capacity": "100 kVA", "site-production-capacity": "80 kW", "site-consumption-capacity": {"sensor": 32}, "site-production-breach-price": "1000 EUR/kW", "site-consumption-breach-price": "1000 EUR/kW", "site-peak-consumption": "50 kW", "site-peak-production": "50 kW", "site-peak-consumption-price": "260 EUR/MW", "site-peak-production-price": "260 EUR/MW" } }
Example response
This message indicates that the scheduling request has been processed without any error. A scheduling job has been created with some Universally Unique Identifier (UUID), which will be picked up by a worker. The given UUID may be used to obtain the resulting schedule: see /sensors/<id>/schedules/<uuid>.
{ "status": "PROCESSED", "schedule": "364bfd06-c1fa-430b-8d25-8f5a547651fb", "message": "Request has been processed." }
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
application/json
- Resheader Content-Type:
application/json
- Status 200:
PROCESSED
- Status 400:
INVALID_DATA
- Status 401:
UNAUTHORIZED
- Status 403:
INVALID_SENDER
- Status 405:
INVALID_METHOD
- Status 422:
UNPROCESSABLE_ENTITY
- upload_data(data: list[BeliefsDataFrame], filenames: list[str], **kwargs)
Post sensor data to FlexMeasures by file upload.
** Example request **
{ "data": [ { "uploaded-files": "["file1.csv", "file2.csv"]" } ] }
The file should have columns for a timestamp (event_start) and a value (event_value). The timestamp should be in ISO 8601 format. The value should be a numeric value.
The unit has to be convertible to the sensor’s unit. The resolution of the data has to match the sensor’s required resolution, but FlexMeasures will attempt to upsample lower resolutions. The list of values may include null values.
- Reqheader Authorization:
The authentication token
- Reqheader Content-Type:
multipart/form-data
- Resheader Content-Type:
application/json
- Status 200:
PROCESSED
- Status 400:
INVALID_REQUEST