Skip to content

Commit

Permalink
various review comments
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas Höning <nicolas@seita.nl>
  • Loading branch information
nhoening committed Oct 29, 2022
1 parent c2b2787 commit c0400ae
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 18 deletions.
8 changes: 6 additions & 2 deletions documentation/plugin/customisation.rst
Expand Up @@ -33,9 +33,13 @@ The following minimal example gives you an idea of the inputs and outputs:
*args,
**kwargs
):
"""Just a dummy scheduler, advising to do nothing"""
"""
Just a dummy scheduler that always plans to consume at maximum capacity.
(Schedulers return positive values for consumption, and negative values for production)
"""
return pd.Series(
0, index=pd.date_range(start, end, freq=resolution, closed="left")
sensor.get_attribute("capacity_in_mw"),
index=pd.date_range(start, end, freq=resolution, closed="left"),
)
Expand Down
13 changes: 7 additions & 6 deletions flexmeasures/api/v3_0/sensors.py
Expand Up @@ -256,20 +256,21 @@ def trigger_schedule( # noqa: C901
.. :quickref: Schedule; Trigger scheduling job
Trigger FlexMeasures to create a schedule for this sensor.
The assumption is that this sensor is the energy sensor on a flexible asset.
The assumption is that this sensor is the power sensor on a flexible asset.
In this request, you can describe:
- the schedule (start, unit, prior)
- the flexibility model for the sensor (see below, only storage models are supported at the moment)
- the EMS the sensor operates in (inflexible device sensors, sensors which put a price on consumption and/or production)
- the EMS the sensor operates in (inflexible device sensors, and sensors that put a price on consumption and/or production)
Note: This endpoint does not support an EMS with multiple flexible sensors. This will happen in another endpoint.
See https://github.com/FlexMeasures/flexmeasures/issues/485
Note: This endpoint does not support to schedule an EMS with multiple flexible sensors at once. This will happen in another endpoint.
See https://github.com/FlexMeasures/flexmeasures/issues/485. Until then, it is possible to call this endpoint for one flexible endpoint at a time
(considering already scheduled sensors as inflexible).
Flexibility models apply to the sensor's asset type:
1) For storage sensors (e.g. battery, charging stations), the schedule deals with the state of charge (SOC).
1) For storage sensors (e.g. battery, charge points), the schedule deals with the state of charge (SOC).
The possible flexibility parameters are:
- soc-at-start (defaults to 0)
Expand Down Expand Up @@ -365,7 +366,7 @@ def trigger_schedule( # noqa: C901
if unit == "kWh":
start_value = start_value / 1000.0

# Convert round-trip efficiency to dimensionless (to the [0,1] range)
# Convert round-trip efficiency to dimensionless (to the (0,1] range)
if roundtrip_efficiency is not None:
roundtrip_efficiency = roundtrip_efficiency.to(
ur.Quantity("dimensionless")
Expand Down
31 changes: 25 additions & 6 deletions flexmeasures/data/models/planning/utils.py
Expand Up @@ -17,9 +17,15 @@


def initialize_df(
columns: List[str], start: datetime, end: datetime, resolution: timedelta
columns: List[str],
start: datetime,
end: datetime,
resolution: timedelta,
inclusive: str,
) -> pd.DataFrame:
df = pd.DataFrame(index=initialize_index(start, end, resolution), columns=columns)
df = pd.DataFrame(
index=initialize_index(start, end, resolution, inclusive), columns=columns
)
return df


Expand All @@ -28,16 +34,25 @@ def initialize_series(
start: datetime,
end: datetime,
resolution: timedelta,
inclusive: str,
) -> pd.Series:
s = pd.Series(index=initialize_index(start, end, resolution), data=data)
s = pd.Series(index=initialize_index(start, end, resolution, inclusive), data=data)
return s


def initialize_index(
start: Union[date, datetime], end: Union[date, datetime], resolution: timedelta
start: Union[date, datetime],
end: Union[date, datetime],
resolution: timedelta,
inclusive: str = "left",
) -> pd.DatetimeIndex:
assert inclusive == "left" or inclusive == "right"
i = pd.date_range(
start=start, end=end, freq=to_offset(resolution), closed="left", name="datetime"
start=start,
end=end,
freq=to_offset(resolution),
closed=inclusive,
name="datetime",
)
return i

Expand Down Expand Up @@ -101,7 +116,7 @@ def ensure_sensor_is_set(sensor) -> Sensor:
# Check for min and max SOC, or get default from sensor
if "soc_min" not in specs or specs["soc_min"] is None:
sensor = ensure_sensor_is_set(sensor)
# Can't drain the EV battery by more than it contains
# Can't drain the storage by more than it contains
specs["soc_min"] = sensor.get_attribute("min_soc_in_mwh", 0)
if "soc_max" not in specs or specs["soc_max"] is None:
sensor = ensure_sensor_is_set(sensor)
Expand Down Expand Up @@ -234,6 +249,10 @@ def get_power_values(
raise UnknownForecastException(
f"Forecasts unknown for planning window. (sensor {sensor.id})"
)
if sensor.get_attribute(
"consumption_is_positive", False
): # FlexMeasures default is to store consumption as negative power values
return df.values
return -df.values


Expand Down
4 changes: 2 additions & 2 deletions flexmeasures/data/services/scheduling.py
Expand Up @@ -109,7 +109,7 @@ def make_schedule(
- Choose which scheduling function can be used
- Compute schedule
- Turn schedukled values into beliefs and save them to db
- Turn scheduled values into beliefs and save them to db
"""
# https://docs.sqlalchemy.org/en/13/faq/connections.html#how-do-i-use-engines-connections-sessions-with-python-multiprocessing-or-os-fork
db.engine.dispose()
Expand Down Expand Up @@ -202,7 +202,7 @@ def load_custom_scheduler(scheduler_specs: dict) -> Tuple[Callable, str]:
assert "function" in scheduler_specs, "scheduler specs have no 'function'"

source_name = scheduler_specs.get(
"source", f"Custom scheduler - {scheduler_specs['function']}"
"source", f"custom scheduler - {scheduler_specs['function']}"
)
scheduler_name = scheduler_specs["function"]

Expand Down
7 changes: 5 additions & 2 deletions flexmeasures/data/tests/dummy_scheduler.py
Expand Up @@ -12,10 +12,13 @@ def compute_a_schedule(
*args,
**kwargs
):
"""Just a dummy scheduler."""
"""
Just a dummy scheduler that always plans to consume at maximum capacity.
(Schedulers return positive values for consumption, and negative values for production)
"""
return initialize_series( # simply creates a Pandas Series repeating one value
data=sensor.get_attribute("capacity_in_mw"),
start=start,
end=end,
resolution=resolution,
)
)

0 comments on commit c0400ae

Please sign in to comment.