posting_data.rst 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. .. _tut_posting_data:
  2. Posting data
  3. ============
  4. The platform FlexMeasures strives on the data you feed it. Let's demonstrate how you can get data into FlexMeasures using the API. This is where FlexMeasures gets connected to your system as a smart backend and helps you build smart energy services.
  5. We will show how to use the API endpoints for POSTing data.
  6. You can call these at regular intervals (through scheduled scripts in your system, for example), so that FlexMeasures always has recent data to work with.
  7. Of course, these endpoints can also be used to load historic data into FlexMeasures, so that the forecasting models have access to enough data history.
  8. .. note:: For the purposes of forecasting and scheduling, it is often advisable to use a less fine-grained resolution than most metering services keep. For example, while such services might measure every ten seconds, FlexMeasures will usually do its job no less effective if you feed it data with a resolution of five minutes. This will also make the data integration much easier. Keep in mind that many data sources like weather forecasting or markets can have data resolutions of an hour, anyway.
  9. .. contents:: Table of contents
  10. :local:
  11. :depth: 1
  12. Prerequisites
  13. --------------
  14. - FlexMeasures needs some structural meta data for data to be understood. For example, for adding weather data we need to define a weather sensor, and what kind of weather sensors there are. You also need a user account. If you host FlexMeasures yourself, you need to add this info first. Head over to :ref:`getting_started`, where these steps are covered, study our :ref:`cli` or look into plugins which do this like `flexmeasures-entsoe <https://github.com/SeitaBV/flexmeasures-entsoe>`_ or `flexmeasures-openweathermap <https://github.com/SeitaBV/flexmeasures-openweathermap>`_.
  15. - You should be familiar with where to find your API endpoints (see :ref:`api_versions`) and how to authenticate against the API (see :ref:`api_auth`).
  16. .. note:: For deeper explanations of the data and the meta fields we'll send here, You can always read the :ref:`api_introduction`, to the FlexMeasures API, e.g. :ref:`signs`, :ref:`frequency_and_resolution`, :ref:`prognoses` and :ref:`units`.
  17. .. note:: To address assets and sensors, these tutorials assume entity addresses valid in the namespace ``fm1``. See :ref:`api_introduction` for more explanations.
  18. .. _posting_sensor_data:
  19. Posting sensor data
  20. -------------------
  21. Sensor data (both observations and forecasts) can be posted to `POST /sensors/data <../api/v3_0.html#post--api-v3_0-sensors-data>`_.
  22. This endpoint represents the basic method of getting time series data into FlexMeasures via API.
  23. It is agnostic to the type of sensor and can be used to POST data for both physical and economical events that have happened in the past or will happen in the future.
  24. Some examples:
  25. - readings from electricity and gas meters
  26. - readings from temperature and pressure sensors
  27. - state of charge of a battery
  28. - estimated availability of parking spots
  29. - price forecasts
  30. The exact URL will depend on your domain name, and will look approximately like this:
  31. .. code-block:: html
  32. [POST] https://company.flexmeasures.io/api/<version>/sensors/data
  33. This example "PostSensorDataRequest" message posts prices for hourly intervals between midnight and midnight the next day
  34. for the Korean Power Exchange (KPX) day-ahead auction, registered under sensor 16.
  35. The ``prior`` indicates that the prices were published at 3pm on December 31st 2014 (i.e. the clearing time of the KPX day-ahead market, which is at 3 PM on the previous day ― see below for a deeper explanation).
  36. .. code-block:: json
  37. {
  38. "type": "PostSensorDataRequest",
  39. "sensor": "ea1.2021-01.io.flexmeasures.company:fm1.16",
  40. "values": [
  41. 52.37,
  42. 51.14,
  43. 49.09,
  44. 48.35,
  45. 48.47,
  46. 49.98,
  47. 58.7,
  48. 67.76,
  49. 69.21,
  50. 70.26,
  51. 70.46,
  52. 70,
  53. 70.7,
  54. 70.41,
  55. 70,
  56. 64.53,
  57. 65.92,
  58. 69.72,
  59. 70.51,
  60. 75.49,
  61. 70.35,
  62. 70.01,
  63. 66.98,
  64. 58.61
  65. ],
  66. "start": "2015-01-01T00:00:00+09:00",
  67. "duration": "PT24H",
  68. "prior": "2014-12-31T15:00:00+09:00",
  69. "unit": "KRW/kWh"
  70. }
  71. Note how the resolution of the data comes out at 60 minutes when you divide the duration by the number of data points.
  72. If this resolution does not match the sensor's resolution, FlexMeasures will try to upsample the data to make the match or, if that is not possible, complain.
  73. Likewise, if the data unit does not match the sensor’s unit, FlexMeasures will attempt to convert the data or, if that is not possible, complain.
  74. Being explicit when posting power data
  75. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  76. For power data, USEF specifies separate message types for observations and forecasts.
  77. Correspondingly, we allow the following message types to be used with the `POST /sensors/data <../api/v3_0.html#post--api-v3_0-sensors-data>`_ endpoint:
  78. .. code-block:: json
  79. {
  80. "type": "PostMeterDataRequest"
  81. }
  82. .. code-block:: json
  83. {
  84. "type": "PostPrognosisRequest"
  85. }
  86. For these message types, FlexMeasures validates whether the data unit is suitable for communicating power data.
  87. Additionally, we validate whether meter data lies in the past, and prognoses lie in the future.
  88. Single value, single sensor
  89. ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  90. A single average power value for a 15-minute time interval for a single sensor, posted 5 minutes after realisation.
  91. .. code-block:: json
  92. {
  93. "type": "PostSensorDataRequest",
  94. "sensor": "ea1.2021-01.io.flexmeasures.company:fm1.1",
  95. "value": 220,
  96. "start": "2015-01-01T00:00:00+00:00",
  97. "duration": "PT0H15M",
  98. "horizon": "-PT5M",
  99. "unit": "MW"
  100. }
  101. Multiple values, single sensor
  102. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  103. Multiple values (indicating a univariate timeseries) for 15-minute time intervals for a single sensor, posted 5 minutes after each realisation.
  104. .. code-block:: json
  105. {
  106. "type": "PostSensorDataRequest",
  107. "sensor": "ea1.2021-01.io.flexmeasures.company:fm1.1",
  108. "values": [
  109. 220,
  110. 210,
  111. 200
  112. ],
  113. "start": "2015-01-01T00:00:00+00:00",
  114. "duration": "PT0H45M",
  115. "horizon": "-PT5M",
  116. "unit": "MW"
  117. }
  118. ..
  119. todo: uncomment whenever the new sensor data API supports sending data for multiple sensors in one message
  120. Single identical value, multiple sensors
  121. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  122. Single identical value for a 15-minute time interval for two sensors, posted 5 minutes after realisation.
  123. Please note that both sensors consumed at 10 MW, i.e. the value does not represent the total of the two sensors.
  124. We recommend to use this notation for zero values only.
  125. .. code-block:: json
  126. {
  127. "type": "PostSensorDataRequest",
  128. "sensors": [
  129. "ea1.2021-01.io.flexmeasures.company:fm1.1",
  130. "ea1.2021-01.io.flexmeasures.company:fm1.2"
  131. ],
  132. "value": 10,
  133. "start": "2015-01-01T00:00:00+00:00",
  134. "duration": "PT0H15M",
  135. "horizon": "-PT5M",
  136. "unit": "MW"
  137. }
  138. Single different values, multiple sensors
  139. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  140. Single different values for a 15-minute time interval for two sensors, posted 5 minutes after realisation.
  141. .. code-block:: json
  142. {
  143. "type": "PostSensorDataRequest",
  144. "groups": [
  145. {
  146. "sensor": "ea1.2021-01.io.flexmeasures.company:fm1.1",
  147. "value": 220
  148. },
  149. {
  150. "sensor": "ea1.2021-01.io.flexmeasures.company:fm1.2",
  151. "value": 300
  152. }
  153. ],
  154. "start": "2015-01-01T00:00:00+00:00",
  155. "duration": "PT0H15M",
  156. "horizon": "-PT5M",
  157. "unit": "MW"
  158. }
  159. Multiple values, multiple sensors
  160. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  161. Multiple values (indicating a univariate timeseries) for 15-minute time intervals for two sensors, posted 5 minutes after each realisation.
  162. .. code-block:: json
  163. {
  164. "type": "PostSensorDataRequest",
  165. "groups": [
  166. {
  167. "sensor": "ea1.2021-01.io.flexmeasures.company:fm1.1",
  168. "values": [
  169. 220,
  170. 210,
  171. 200
  172. ]
  173. },
  174. {
  175. "sensor": "ea1.2021-01.io.flexmeasures.company:fm1.2",
  176. "values": [
  177. 300,
  178. 303,
  179. 306
  180. ]
  181. }
  182. ],
  183. "start": "2015-01-01T00:00:00+00:00",
  184. "duration": "PT0H45M",
  185. "horizon": "-PT5M",
  186. "unit": "MW"
  187. }
  188. .. _observations_vs_forecasts
  189. Observations vs forecasts: The time of knowledge
  190. -------------------------------------------------
  191. To correctly tell FlexMeasures when a meter reading or forecast was known is crucial, as it determines which data is being used to compute schedules or to make other forecasts.
  192. Usually, the time of posting is assumed to be the time when the data was known. But you can also explicitly tell FlexMeasures what these times are. This either works with one fixed time (for the whole set of data being sent) or with a horizon (which applies to each data point separately).
  193. E.g. to post a forecast rather than an observation after the fact, simply set the ``prior`` to the moment at which the forecasts were made, e.g. at "2015-01-01T16:30:00+09:00". Assuming your data starts at 5.00pm, this denotes that the data are forecasts, made half an hour before realisation.
  194. Alternatively, to indicate that each individual observation was made directly after the end of its 15-minute interval (i.e. at 3.15pm, 3.30pm and so on), set a ``horizon`` to "PT0H" instead of a ``prior``.
  195. Finally, delays in reading out sensor data can be simulated by setting the ``horizon`` field to a negative value.
  196. For example, a horizon of "-PT1H" would denote that each temperature reading was observed one hour after the fact (i.e. at 4.15pm, 4.30pm and so on).
  197. See :ref:`prognoses` for more information regarding the ``prior`` and ``horizon`` fields.
  198. A good example for the use of the ``prior`` field are markets, which have clearing times.
  199. For example, at the KPX day-ahead auction this is every day at 3pm.
  200. This point in time (i.e. when contracts are signed) determines the difference between an ex-post observation and an ex-ante forecast.
  201. Another example for the ``prior`` field is running simulations with FlexMeasures. It gives you control over the timing so that you could run a month in the past as if it happened right now.
  202. .. _posting_flex_states:
  203. Posting flexibility states
  204. -------------------------------
  205. There is one more crucial kind of data that FlexMeasures needs to know about: What are the current states of flexible devices?
  206. For example, a battery has a certain state of charge, which is relevant to describe the flexibility that the battery currently has.
  207. In our terminology, this is called the "flex model" and you can read more at :ref:`describing_flexibility`.
  208. Owners of such devices can post the flex model along with triggering the creation of a new schedule, to `[POST] /schedules/trigger <../api/v3_0.html#post--api-v3_0-sensors-(id)-schedules-trigger>`_.
  209. The URL might look like this:
  210. .. code-block:: html
  211. https://company.flexmeasures.io/api/<version>/sensors/10/schedules/trigger
  212. The following example triggers a schedule for a power sensor (with ID 10) of a battery asset, asking to take into account the battery's current state of charge.
  213. From this, FlexMeasures derives the energy flexibility this battery has in the next 48 hours and computes an optimal charging schedule.
  214. The endpoint also allows to limit the flexibility range and also to set target values.
  215. .. code-block:: json
  216. {
  217. "start": "2015-06-02T10:00:00+00:00",
  218. "flex-model": {
  219. "soc-at-start": "12.1 kWh"
  220. }
  221. }
  222. .. note:: More details on supported flex models can be found in :ref:`flex_models_and_schedulers`.
  223. .. note:: Flexibility states are persisted on sensor attributes. To record a more complete history of the state of charge, set up a separate sensor and post data to it using `[POST] /sensors/data <../api/v3_0.html#post--api-v3_0-sensors-data>`_ (see :ref:`posting_sensor_data`).
  224. In :ref:`how_queue_scheduling`, we'll cover what happens when FlexMeasures is triggered to create a new schedule, and how those schedules can be retrieved via the API, so they can be used to steer assets.