utils.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. from sqlalchemy import select
  2. from flexmeasures import Sensor
  3. from flexmeasures.data import db
  4. def make_sensor_data_request_for_gas_sensor(
  5. num_values: int = 6,
  6. duration: str = "PT1H",
  7. unit: str = "m³",
  8. include_a_null: bool = False,
  9. sensor_name: str = "some gas sensor",
  10. ) -> dict:
  11. """Creates request to post sensor data for a gas sensor.
  12. This particular gas sensor measures units of m³/h with a 10-minute resolution.
  13. """
  14. sensor = db.session.execute(
  15. select(Sensor).filter_by(name=sensor_name)
  16. ).scalar_one_or_none()
  17. values = num_values * [-11.28]
  18. if include_a_null:
  19. values[0] = None
  20. message: dict = {
  21. "type": "PostSensorDataRequest",
  22. "sensor": f"ea1.2021-01.io.flexmeasures:fm1.{sensor.id}",
  23. "values": values,
  24. "start": "2021-06-07T00:00:00+02:00",
  25. "duration": duration,
  26. "horizon": "PT0H",
  27. "unit": unit,
  28. }
  29. if num_values == 1:
  30. # flatten [<float>] to <float>
  31. message["values"] = message["values"][0]
  32. return message
  33. def get_asset_post_data(account_id: int = 1, asset_type_id: int = 1) -> dict:
  34. post_data = {
  35. "name": "Test battery 2",
  36. "latitude": 30.1,
  37. "longitude": 100.42,
  38. "generic_asset_type_id": asset_type_id,
  39. "account_id": account_id,
  40. }
  41. return post_data
  42. def get_sensor_post_data(generic_asset_id: int = 2) -> dict:
  43. post_data = {
  44. "name": "power",
  45. "event_resolution": "PT1H",
  46. "unit": "kWh",
  47. "generic_asset_id": generic_asset_id,
  48. "attributes": '{"capacity_in_mw": 0.0074, "max_soc_in_mwh": 0.04, "min_soc_in_mwh": 0.008}',
  49. }
  50. return post_data
  51. def message_for_trigger_schedule(
  52. unknown_prices: bool = False,
  53. with_targets: bool = False,
  54. realistic_targets: bool = True,
  55. too_far_into_the_future_targets: bool = False,
  56. use_time_window: bool = False,
  57. use_perfect_efficiencies: bool = False,
  58. ) -> dict:
  59. message = {
  60. "start": "2015-01-01T00:00:00+01:00",
  61. "duration": "PT24H", # Will be extended in case of targets that would otherwise lie beyond the schedule's end
  62. }
  63. if unknown_prices:
  64. message["start"] = (
  65. "2040-01-01T00:00:00+01:00" # We have no beliefs in our test database about 2040 prices
  66. )
  67. message["flex-model"] = {
  68. "soc-at-start": 12.1, # in kWh, according to soc-unit
  69. "soc-min": 0, # in kWh, according to soc-unit
  70. "soc-max": 40, # in kWh, according to soc-unit
  71. "soc-unit": "kWh",
  72. "roundtrip-efficiency": "98%" if not use_perfect_efficiencies else "100%",
  73. "storage-efficiency": "99.99%" if not use_perfect_efficiencies else 1,
  74. "power-capacity": "2 MW", # same as site-power-capacity of test battery and test charging station
  75. }
  76. if with_targets:
  77. if realistic_targets:
  78. # this target (in kWh, according to soc-unit) is well below the soc_max_in_mwh on the battery's sensor attributes
  79. target_value = 25
  80. else:
  81. # this target (in kWh, according to soc-unit) is actually higher than soc_max_in_mwh on the battery's sensor attributes
  82. target_value = 25000
  83. if too_far_into_the_future_targets:
  84. # this target exceeds FlexMeasures' default max planning horizon
  85. target_datetime = "2015-02-02T23:00:00+01:00"
  86. else:
  87. target_datetime = "2015-01-02T23:00:00+01:00"
  88. if use_time_window:
  89. target_time_window = {
  90. "start": "2015-01-02T22:45:00+01:00",
  91. "end": target_datetime,
  92. }
  93. else:
  94. target_time_window = {"datetime": target_datetime}
  95. message["flex-model"]["soc-targets"] = [
  96. {"value": target_value, **target_time_window}
  97. ]
  98. # Also create some minima and maxima constraints to test correct deserialization using the soc-unit
  99. message["flex-model"]["soc-minima"] = [
  100. {"value": target_value - 1, **target_time_window}
  101. ]
  102. message["flex-model"]["soc-maxima"] = [
  103. {"value": target_value + 1, **target_time_window}
  104. ]
  105. return message