Skip to content

Commit

Permalink
feature/migrate to official s2 library (#76)
Browse files Browse the repository at this point in the history
* refactor(client): Add static typing

Signed-off-by: GustaafL <guus@seita.nl>

* refactor(client): Add error checking for wrong content type

Signed-off-by: GustaafL <guus@seita.nl>

* refactor(client): type client.py

Signed-off-by: GustaafL <guus@seita.nl>

* refactor(cem): type as much some of the code

Signed-off-by: GustaafL <guus@seita.nl>

* feat(mypy): add mypy to pre-commit checks

Signed-off-by: GustaafL <guus@seita.nl>

* refactor(typing): add types for constraints and async parts

Signed-off-by: GustaafL <guus@seita.nl>

* Update ci.yml

Signed-off-by: Guus Linzel <41048720+GustaafL@users.noreply.github.com>

* add new dependencies

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* migrate to the official s2 library

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* remove old s2 message validation module

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* feature/add support for more message types (#77)

* add dummy methods to return `Ok`Status code for the message types Timer and Transition

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Timer and Transition are not message types, the message type that we want to support is FRBCTimerStatus

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

---------

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

---------

Signed-off-by: GustaafL <guus@seita.nl>
Signed-off-by: Guus Linzel <41048720+GustaafL@users.noreply.github.com>
Signed-off-by: Victor Garcia Reolid <victor@seita.nl>
Co-authored-by: GustaafL <guus@seita.nl>
Co-authored-by: Guus Linzel <41048720+GustaafL@users.noreply.github.com>
  • Loading branch information
3 people committed Mar 4, 2024
1 parent 66f7756 commit 7be2645
Show file tree
Hide file tree
Showing 15 changed files with 62 additions and 1,077 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
strategy:
matrix:
python:
- "3.9"
- "3.10"
# - "3.7" # oldest Python supported by PSF
- "3.11" # newest Python that is stable
platform:
Expand Down
5 changes: 3 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ install_requires =
aiohttp
pandas
pydantic>=1.10.8,<2.0
async-timeout

s2-python
async_timeout

[options.packages.find]
where = src
Expand All @@ -74,6 +74,7 @@ testing =
pytest-mock
aioresponses


[options.entry_points]
# Add here console scripts like:
# console_scripts =
Expand Down
20 changes: 7 additions & 13 deletions src/flexmeasures_client/s2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@
from typing import Callable, Coroutine, Dict, Type

import pydantic
from s2python.common import ReceptionStatus, ReceptionStatusValues, RevokeObject

from flexmeasures_client.s2.python_s2_protocol.common.messages import (
ReceptionStatus,
ReceptionStatusValues,
RevokeObject,
)
from flexmeasures_client.s2.utils import (
SizeLimitOrderedDict,
get_message_id,
Expand Down Expand Up @@ -58,7 +54,7 @@ def wrap(*args, **kwargs):

except pydantic.ValidationError as e:
return ReceptionStatus(
subject_message_id=incoming_message.message_id,
subject_message_id=str(incoming_message.message_id),
diagnostic_label=get_validation_error_summary(e),
status=ReceptionStatusValues.INVALID_DATA,
) # TODO: Discuss status
Expand Down Expand Up @@ -201,9 +197,7 @@ def handle_response_status(self, message: ReceptionStatus):

# save acknowledgement status code
# TODO: implement function __hash__ in ID that returns the value of __root__
self.outgoing_messages_status[
message.subject_message_id.__root__
] = message.status
self.outgoing_messages_status[str(message.subject_message_id)] = message.status

# choose which callback to call, depending on the ReceptionStatus value
if message.status == ReceptionStatusValues.OK:
Expand All @@ -212,21 +206,21 @@ def handle_response_status(self, message: ReceptionStatus):
callback_store = self.failure_callbacks

# pop callback from callback_store and run it, if there exists one
if callback := callback_store.pop(message.subject_message_id.__root__, None):
if callback := callback_store.pop(str(message.subject_message_id), None):
callback()

# delete success callback related to this message
if callback is None and (message.status != ReceptionStatusValues.OK):
self.success_callbacks.pop(message.subject_message_id.__root__, None)
self.success_callbacks.pop(str(message.subject_message_id), None)

@register(RevokeObject)
def handle_revoke_object(self, message: RevokeObject):
"""
Stores the revoked object ID into the objects_revoked list
"""

self.objects_revoked.append(message.object_id.__root__)
self.objects_revoked.append(message.object_id)

return ReceptionStatus(
subject_message_id=message.message_id, status=ReceptionStatusValues.OK
subject_message_id=str(message.message_id), status=ReceptionStatusValues.OK
)
12 changes: 6 additions & 6 deletions src/flexmeasures_client/s2/cem.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@
from typing import Dict, Optional

import pydantic

from flexmeasures_client.client import FlexMeasuresClient
from flexmeasures_client.s2 import Handler, register
from flexmeasures_client.s2.control_types import ControlTypeHandler
from flexmeasures_client.s2.python_s2_protocol.common.messages import (
from s2python.common import (
ControlType,
Handshake,
HandshakeResponse,
PowerMeasurement,
Expand All @@ -21,7 +18,10 @@
RevokeObject,
SelectControlType,
)
from flexmeasures_client.s2.python_s2_protocol.common.schemas import ControlType

from flexmeasures_client.client import FlexMeasuresClient
from flexmeasures_client.s2 import Handler, register
from flexmeasures_client.s2.control_types import ControlTypeHandler
from flexmeasures_client.s2.utils import get_reception_status, get_unique_id


Expand Down
27 changes: 14 additions & 13 deletions src/flexmeasures_client/s2/control_types/FRBC/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import asyncio

import pydantic

from flexmeasures_client.s2 import SizeLimitOrderedDict, register
from flexmeasures_client.s2.control_types import ControlTypeHandler
from flexmeasures_client.s2.python_s2_protocol.common.messages import (
ReceptionStatusValues,
)
from flexmeasures_client.s2.python_s2_protocol.common.schemas import ControlType
from flexmeasures_client.s2.python_s2_protocol.FRBC.messages import (
from s2python.common import ControlType, ReceptionStatusValues
from s2python.frbc import (
FRBCActuatorStatus,
FRBCFillLevelTargetProfile,
FRBCInstruction,
Expand All @@ -18,6 +12,9 @@
FRBCTimerStatus,
FRBCUsageForecast,
)

from flexmeasures_client.s2 import SizeLimitOrderedDict, register
from flexmeasures_client.s2.control_types import ControlTypeHandler
from flexmeasures_client.s2.utils import get_reception_status, get_unique_id


Expand Down Expand Up @@ -59,7 +56,7 @@ def __init__(self, max_size: int = 100) -> None:
def handle_system_description(
self, message: FRBCSystemDescription
) -> pydantic.BaseModel:
system_description_id = message.message_id.__root__
system_description_id = str(message.message_id)

# store system_description message for later
self._system_description_history[system_description_id] = message
Expand All @@ -77,7 +74,7 @@ async def send_actuator_status(self, status: FRBCActuatorStatus):

@register(FRBCStorageStatus)
def handle_storage_status(self, message: FRBCStorageStatus) -> pydantic.BaseModel:
message_id = message.message_id.__root__
message_id = str(message.message_id)

self._storage_status_history[message_id] = message

Expand All @@ -87,7 +84,7 @@ def handle_storage_status(self, message: FRBCStorageStatus) -> pydantic.BaseMode

@register(FRBCActuatorStatus)
def handle_actuator_status(self, message: FRBCActuatorStatus) -> pydantic.BaseModel:
message_id = message.message_id.__root__
message_id = str(message.message_id)

self._actuator_status_history[message_id] = message

Expand All @@ -110,6 +107,10 @@ def handle_usage_forecast(self, message: FRBCUsageForecast) -> pydantic.BaseMode
async def trigger_schedule(self, system_description_id: str):
raise NotImplementedError()

@register(FRBCTimerStatus)
def handle_frbc_timer_status(self, message: FRBCTimerStatus) -> pydantic.BaseModel:
return get_reception_status(message, status=ReceptionStatusValues.OK)


class FRBCTest(FRBC):
"""Dummy class to simulate the triggering of a schedule."""
Expand All @@ -129,8 +130,8 @@ async def trigger_schedule(self, system_description_id: str):
instruction = FRBCInstruction(
message_id=get_unique_id(),
id=get_unique_id(),
actuator_id=actuator.id.__root__,
operation_mode=actuator.operation_modes[0].id.__root__,
actuator_id=actuator.id,
operation_mode=actuator.operation_modes[0].id,
operation_mode_factor=0.5,
execution_time=system_description.valid_from,
abnormal_condition=False,
Expand Down
6 changes: 1 addition & 5 deletions src/flexmeasures_client/s2/control_types/FRBC/frbc_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@
from datetime import datetime, timedelta

import pytz
from s2python.frbc import FRBCActuatorStatus, FRBCStorageStatus, FRBCSystemDescription

from flexmeasures_client.s2.control_types.FRBC import FRBC
from flexmeasures_client.s2.control_types.FRBC.utils import fm_schedule_to_instructions
from flexmeasures_client.s2.python_s2_protocol.FRBC.messages import (
FRBCActuatorStatus,
FRBCStorageStatus,
FRBCSystemDescription,
)


class FRBCSimple(FRBC):
Expand Down
10 changes: 3 additions & 7 deletions src/flexmeasures_client/s2/control_types/FRBC/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@
from typing import List

import pandas as pd
from s2python.frbc import FRBCInstruction, FRBCOperationMode, FRBCSystemDescription

from flexmeasures_client.s2.python_s2_protocol.FRBC.messages import (
FRBCInstruction,
FRBCSystemDescription,
)
from flexmeasures_client.s2.python_s2_protocol.FRBC.schemas import FRBCOperationMode
from flexmeasures_client.s2.utils import get_unique_id


Expand Down Expand Up @@ -94,8 +90,8 @@ def fm_schedule_to_instructions(
instruction = FRBCInstruction(
message_id=get_unique_id(),
id=get_unique_id(),
actuator_id=actuator.id.__root__,
operation_mode=operation_mode.id.__root__,
actuator_id=actuator.id,
operation_mode=operation_mode.id,
operation_mode_factor=operation_mode_factor,
execution_time=start,
abnormal_condition=False,
Expand Down
14 changes: 6 additions & 8 deletions src/flexmeasures_client/s2/control_types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@
from typing import cast

from pydantic import BaseModel

from flexmeasures_client.client import FlexMeasuresClient
from flexmeasures_client.s2 import Handler, register
from flexmeasures_client.s2.python_s2_protocol.common.messages import (
from s2python.common import (
ControlType,
InstructionStatus,
InstructionStatusUpdate,
)
from flexmeasures_client.s2.python_s2_protocol.common.schemas import (
ControlType,
ReceptionStatusValues,
)

from flexmeasures_client.client import FlexMeasuresClient
from flexmeasures_client.s2 import Handler, register
from flexmeasures_client.s2.utils import SizeLimitOrderedDict, get_reception_status


Expand All @@ -33,7 +31,7 @@ def __init__(self, max_size: int = 100) -> None:

@register(InstructionStatusUpdate)
def handle_instruction_status_update(self, message: InstructionStatusUpdate):
instruction_id: str = cast(str, message.instruction_id.__root__)
instruction_id: str = cast(str, message.instruction_id)

self._instruction_status_history[instruction_id] = message.status_type

Expand Down
Loading

0 comments on commit 7be2645

Please sign in to comment.