Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
fc02695
feat: add stubs for tests and initial code structure
Flix6x Jan 20, 2025
8548047
Joule profile for target profile and original data
VladIftime Jan 20, 2025
c9468dc
Added the device state as ported from Java
VladIftime Jan 21, 2025
e0694ca
Added serialised JSON for FRBC device state
VladIftime Jan 22, 2025
20ef8c8
Added the target joule profile
VladIftime Jan 24, 2025
05bd40e
Created the first version of the python version
VladIftime Jan 31, 2025
85c98f9
Added the congestion point and root planner and a Device Planner class
VladIftime Feb 5, 2025
b95a3a9
Chore: type hints for easier debugging; removed profile insight, add …
VladIftime Feb 7, 2025
82900f2
Created pytest for FRBC
VladIftime Feb 7, 2025
10c28e5
Adding unit test
VladIftime Feb 7, 2025
108c0a8
Profile_metadata
VladIftime Feb 10, 2025
de03441
Profile_metadata
VladIftime Feb 10, 2025
e29b40d
Fixed all errors
VladIftime Feb 11, 2025
4731690
test returns null joule profile but it returns
VladIftime Feb 12, 2025
f305431
Created more robust testing. Still fails.
VladIftime Feb 14, 2025
b59e50e
Need to discuss the change to the s2-python FRBC library
VladIftime Feb 14, 2025
5f17892
Need to discuss FRBC change in s2-python
VladIftime Feb 14, 2025
7f5c99c
Need to discuss FRBC change in s2-python
VladIftime Feb 14, 2025
4d593f9
Problems at the final generation step
VladIftime Feb 19, 2025
6b2dbd4
The algorithm works with slight deviations probably due to rounding e…
VladIftime Feb 22, 2025
a0ada05
The algorithm works
VladIftime Feb 24, 2025
4d2eedb
Chore:removed prints and files used for debuggin
VladIftime Feb 24, 2025
a0915b9
Created planning service implementation that takes a device state and…
VladIftime Mar 14, 2025
2fbda15
Plan is being created
VladIftime Mar 14, 2025
d335f6a
Planning service provides initial plan
VladIftime Mar 14, 2025
047e796
Added cluster plan and global target
VladIftime Mar 19, 2025
db6728a
Root and cluster point produce a improved plan close to the target.
VladIftime Apr 2, 2025
102a239
The Planning schedule works right now. The profiling resutls are also…
VladIftime May 19, 2025
dad9e94
Scheduling 10 EVs
VladIftime Jun 2, 2025
f0e31b4
Scheduling 10 EVs
VladIftime Jun 2, 2025
7345e28
Revert "Scheduling 10 EVs"
Flix6x Jun 2, 2025
f36a85f
Dev/various planner code suggestions (#11)
Flix6x Jun 2, 2025
f8739c3
Removed simple getters that get lost
VladIftime Jun 3, 2025
c063972
Removed simple getters that get lost
VladIftime Jun 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions .idea/flexmeasures-s2.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ or:
Try it:

pre-commit run --all-files --show-diff-on-failure

For profiling, use:

pyinstrument -o profiling_results.html test_frbc_device.py
2 changes: 1 addition & 1 deletion flexmeasures_s2/api/somedata.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from flask_security import auth_token_required
from flask_json import as_json
from flask_security import auth_token_required

from .. import flexmeasures_s2_api_bp

Expand Down
58 changes: 47 additions & 11 deletions flexmeasures_s2/api/tests/test_api.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,52 @@
from flask import url_for
from flask_security import decorators as fs_decorators
from rq.job import Job

from flexmeasures.api.tests.test_auth_token import patched_check_token
from flexmeasures.api.tests.utils import UserContext
from flexmeasures.data.services.scheduling import (
handle_scheduling_exception,
get_data_source_for_job,
)
from flexmeasures.data.tests.utils import work_on_rq

def test_get_somedata_needs_authtoken(client):
response = client.get(
url_for("flexmeasures-s2 API.somedata"),
headers={"content-type": "application/json"},
follow_redirects=True,
)
assert response.status_code == 401 # HTTP error code 401 Unauthorized.
assert "application/json" in response.content_type
assert "not be properly authenticated" in response.json["message"]

def test_s2_frbc_api(monkeypatch, app, setup_frbc_asset):
sensor = setup_frbc_asset.sensors[0]

# TODO: The somedata endpoint requires authentication to be testes successfully.
# We'll need to add a user in conftest, which also requires us to add a db to testing
with UserContext("test_admin_user@seita.nl") as admin:
auth_token = admin.get_auth_token()

monkeypatch.setattr(fs_decorators, "_check_token", patched_check_token)
with app.test_client() as client:
trigger_schedule_response = client.post(
url_for("SensorAPI:trigger_schedule", id=sensor.id),
json={
"flex-context": {
"target-profile": {}, # add target profile
}
},
headers={"Authorization": auth_token},
)
print("Server responded with:\n%s" % trigger_schedule_response.json)
assert trigger_schedule_response.status_code == 200
job_id = trigger_schedule_response.json["schedule"]

# Now that our scheduling job was accepted, we process the scheduling queue
work_on_rq(app.queues["scheduling"], exc_handler=handle_scheduling_exception)
job = Job.fetch(job_id, connection=app.queues["scheduling"].connection).is_finished
assert job.is_finished is True

# First, make sure the expected scheduler data source is now there
job.refresh() # catch meta info that was added on this very instance
scheduler_source = get_data_source_for_job(job)
assert scheduler_source.model == "S2Scheduler"

# try to retrieve the schedule through the /sensors/<id>/schedules/<job_id> [GET] api endpoint
# todo: to be discussed: the response from the S2Scheduler might get a different format than the FM default
# get_schedule_response = client.get(
# url_for("SensorAPI:get_schedule", id=sensor.id, uuid=job_id),
# query_string={"duration": "PT48H"},
# )
# print("Server responded with:\n%s" % get_schedule_response.json)
# assert get_schedule_response.status_code == 200
50 changes: 48 additions & 2 deletions flexmeasures_s2/conftest.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import pytest

from flask_sqlalchemy import SQLAlchemy

from flexmeasures import Asset, AssetType, Sensor, Account
from flexmeasures.app import create as create_flexmeasures_app
from flexmeasures.auth.policy import ADMIN_ROLE
from flexmeasures.conftest import ( # noqa F401
db,
fresh_db,
) # Use these fixtures to rely on the FlexMeasures database.
) # Use these fixtures to rely on the FlexMeasures database. There might be others in flexmeasures/conftest you want to also re-use
from flexmeasures.data.services.users import create_user

# There might be others in flexmeasures/conftest you want to also re-use
from flexmeasures_s2 import S2_SCHEDULER_SPECS
from flexmeasures_s2.models.const import FRBC_TYPE


@pytest.fixture(scope="session")
Expand All @@ -25,3 +31,43 @@ def app():
ctx.pop()

print("DONE WITH APP FIXTURE")


@pytest.fixture(scope="module")
def setup_admin(db: SQLAlchemy): # noqa: F811
account = Account(name="Some FlexMeasures host")
db.session.add(account)
create_user(
username="Test Admin User",
email="test_admin_user@seita.nl",
account_name=account.name,
password="testtest",
user_roles=dict(name=ADMIN_ROLE, description="A user who can do everything."),
)
yield account


@pytest.fixture(scope="module")
def setup_frbc_asset(db: SQLAlchemy, setup_admin): # noqa: F811
asset_type = AssetType(name=FRBC_TYPE)
asset = Asset(
name="Test FRBC asset",
generic_asset_type=asset_type,
owner=setup_admin,
)
asset.attributes = {
"custom-scheduler": S2_SCHEDULER_SPECS,
"flex-model": {
"S2-FRBC-device-state": None, # ?todo: add serialized state
},
}
db.session.add(asset)
sensor = Sensor(
name="power",
unit="kW",
event_resolution="PT5M",
generic_asset=asset,
)
db.session.add(sensor)
db.session.flush() # assign (asset and sensor) IDs
yield asset
Empty file.
2 changes: 2 additions & 0 deletions flexmeasures_s2/models/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
NAMESPACE = "fm-s2"
FRBC_TYPE = f"{NAMESPACE}.FRBC"
Empty file.
Loading
Loading