From 4461a2aa7822b2f3cf696c29ba7bde0dafd935de Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Thu, 19 Feb 2026 17:32:14 +0100 Subject: [PATCH 1/9] feat: let CEM logger use the logging level set in the docker-compose.yaml Signed-off-by: F.N. Claessen --- .../s2/script/websockets_server.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/flexmeasures_client/s2/script/websockets_server.py b/src/flexmeasures_client/s2/script/websockets_server.py index 6318918c..858ca617 100644 --- a/src/flexmeasures_client/s2/script/websockets_server.py +++ b/src/flexmeasures_client/s2/script/websockets_server.py @@ -1,5 +1,7 @@ import asyncio import json +import logging +import os import aiohttp from aiohttp import web @@ -9,6 +11,13 @@ from flexmeasures_client.s2.cem import CEM from flexmeasures_client.s2.control_types.FRBC.frbc_simple import FRBCSimple +log_level = os.getenv("LOGGING_LEVEL", "WARNING").upper() +logging.basicConfig( + level=log_level, + format="[CEM][%(asctime)s] %(levelname)s: %(name)s | %(message)s", +) +LOGGER = logging.getLogger(__name__) + async def rm_details_watchdog(ws, cem: CEM): """This function will define a service in Home Assistant, or could @@ -78,7 +87,11 @@ async def websocket_handler(request): site_name, fm_client ) - cem = CEM(sensor_id=power_sensor["id"], fm_client=fm_client) + cem = CEM( + sensor_id=power_sensor["id"], + fm_client=fm_client, + logger=LOGGER, + ) frbc = FRBCSimple( power_sensor_id=power_sensor["id"], price_sensor_id=price_sensor["id"], From a0e9cab275918ea4705084fcff0023321ed273e5 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Thu, 19 Feb 2026 17:38:10 +0100 Subject: [PATCH 2/9] feat: make DEBUG log statements out of print statements in websockets_server.py Signed-off-by: F.N. Claessen --- .../s2/script/websockets_server.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/flexmeasures_client/s2/script/websockets_server.py b/src/flexmeasures_client/s2/script/websockets_server.py index 858ca617..30f62b04 100644 --- a/src/flexmeasures_client/s2/script/websockets_server.py +++ b/src/flexmeasures_client/s2/script/websockets_server.py @@ -35,43 +35,43 @@ async def rm_details_watchdog(ws, cem: CEM): # check/wait that the control type is set properly while cem._control_type != ControlType.FILL_RATE_BASED_CONTROL: - print("waiting for the activation of the control type...") + cem._logger.debug("waiting for the activation of the control type...") await asyncio.sleep(1) - print("CONTROL TYPE: ", cem._control_type) + cem._logger.debug(f"CONTROL TYPE: {cem._control_type}") # after this, schedule will be triggered on reception of a new system description async def websocket_producer(ws, cem: CEM): - print("start websocket message producer") - print("IS CLOSED? ", cem.is_closed()) + cem._logger.debug("start websocket message producer") + cem._logger.debug(f"IS CLOSED? {cem.is_closed()}") while not cem.is_closed(): message = await cem.get_message() - print("sending message") + cem._logger.debug("sending message") await ws.send_json(message) - print("cem closed") + cem._logger.debug("cem closed") async def websocket_consumer(ws, cem: CEM): async for msg in ws: - print("RECEIVED: ", json.loads(msg.json())) + cem._logger.debug(f"RECEIVED: {json.loads(msg.json())}") if msg.type == aiohttp.WSMsgType.TEXT: if msg.data == "close": # TODO: save cem state? - print("close...") + cem._logger.debug("close...") cem.close() await ws.close() else: await cem.handle_message(json.loads(msg.json())) elif msg.type == aiohttp.WSMsgType.ERROR: - print("close...") + cem._logger.debug("close...") cem.close() - print("ws connection closed with exception %s" % ws.exception()) + cem._logger.debug(f"ws connection closed with exception {ws.exception()}") # TODO: save cem state? - print("websocket connection closed") + cem._logger.debug("websocket connection closed") async def websocket_handler(request): From 7017a9b5050a84b4d5742d693689590fac589e78 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Thu, 19 Feb 2026 17:47:29 +0100 Subject: [PATCH 3/9] feat: log an error when closing the WS connection with an exception Signed-off-by: F.N. Claessen --- src/flexmeasures_client/s2/script/websockets_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flexmeasures_client/s2/script/websockets_server.py b/src/flexmeasures_client/s2/script/websockets_server.py index 30f62b04..07789f84 100644 --- a/src/flexmeasures_client/s2/script/websockets_server.py +++ b/src/flexmeasures_client/s2/script/websockets_server.py @@ -68,7 +68,7 @@ async def websocket_consumer(ws, cem: CEM): elif msg.type == aiohttp.WSMsgType.ERROR: cem._logger.debug("close...") cem.close() - cem._logger.debug(f"ws connection closed with exception {ws.exception()}") + cem._logger.error(f"ws connection closed with exception {ws.exception()}") # TODO: save cem state? cem._logger.debug("websocket connection closed") From 196419adb0279b49efe3e6bfd3ba030d6c13cb3d Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Thu, 19 Feb 2026 17:49:10 +0100 Subject: [PATCH 4/9] fix: avoid crashing on a log statement Signed-off-by: F.N. Claessen --- src/flexmeasures_client/s2/script/websockets_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flexmeasures_client/s2/script/websockets_server.py b/src/flexmeasures_client/s2/script/websockets_server.py index 07789f84..652653da 100644 --- a/src/flexmeasures_client/s2/script/websockets_server.py +++ b/src/flexmeasures_client/s2/script/websockets_server.py @@ -55,7 +55,7 @@ async def websocket_producer(ws, cem: CEM): async def websocket_consumer(ws, cem: CEM): async for msg in ws: - cem._logger.debug(f"RECEIVED: {json.loads(msg.json())}") + cem._logger.debug(f"RECEIVED: {msg}") if msg.type == aiohttp.WSMsgType.TEXT: if msg.data == "close": # TODO: save cem state? From 54d6f6eef4e0853066cc758109d0b85a6272c8c2 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Thu, 19 Feb 2026 17:49:36 +0100 Subject: [PATCH 5/9] feat: use INFO level logging for received message Signed-off-by: F.N. Claessen --- src/flexmeasures_client/s2/script/websockets_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flexmeasures_client/s2/script/websockets_server.py b/src/flexmeasures_client/s2/script/websockets_server.py index 652653da..befd941c 100644 --- a/src/flexmeasures_client/s2/script/websockets_server.py +++ b/src/flexmeasures_client/s2/script/websockets_server.py @@ -55,7 +55,7 @@ async def websocket_producer(ws, cem: CEM): async def websocket_consumer(ws, cem: CEM): async for msg in ws: - cem._logger.debug(f"RECEIVED: {msg}") + cem._logger.info(f"RECEIVED: {msg}") if msg.type == aiohttp.WSMsgType.TEXT: if msg.data == "close": # TODO: save cem state? From df6019de00d96769e6cd113f9fd36b03a02e3991 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Thu, 19 Feb 2026 17:52:41 +0100 Subject: [PATCH 6/9] fix: forgive JSON vs dict message data Signed-off-by: F.N. Claessen --- src/flexmeasures_client/s2/script/websockets_server.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/flexmeasures_client/s2/script/websockets_server.py b/src/flexmeasures_client/s2/script/websockets_server.py index befd941c..8db1b8f1 100644 --- a/src/flexmeasures_client/s2/script/websockets_server.py +++ b/src/flexmeasures_client/s2/script/websockets_server.py @@ -63,7 +63,10 @@ async def websocket_consumer(ws, cem: CEM): cem.close() await ws.close() else: - await cem.handle_message(json.loads(msg.json())) + try: + await cem.handle_message(json.loads(msg.json())) + except: + await cem.handle_message(msg.json()) elif msg.type == aiohttp.WSMsgType.ERROR: cem._logger.debug("close...") From 28d2f9a766a97580d482d45e305cbdd3633f2c03 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Thu, 19 Feb 2026 17:55:03 +0100 Subject: [PATCH 7/9] docs: restructure docstring Signed-off-by: F.N. Claessen --- src/flexmeasures_client/s2/cem.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/flexmeasures_client/s2/cem.py b/src/flexmeasures_client/s2/cem.py index b13f85af..296e418c 100644 --- a/src/flexmeasures_client/s2/cem.py +++ b/src/flexmeasures_client/s2/cem.py @@ -172,11 +172,9 @@ def register_control_type(self, control_type_handler: ControlTypeHandler): async def handle_message(self, message: Dict | pydantic.BaseModel | str): """ - This method handles the incoming messages to the CEM - and routes them to their custom handler. If certain - control type is active and there's a handler defined in both - the control type handler as well as in the CEM, it prevails the - on of the the control type. + This method handles the incoming messages to the CEM and routes them to their custom handler. + If a certain control type is active and there's a handler defined in both + the control type handler and in the CEM, then the one defined in the control type prevails. """ response = None From 76ea32a0dc16cbfaa4acdb929b9a9cc6bce9ae57 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Thu, 19 Feb 2026 20:12:20 +0100 Subject: [PATCH 8/9] docs: fix typo Signed-off-by: F.N. Claessen --- src/flexmeasures_client/s2/control_types/FRBC/frbc_simple.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flexmeasures_client/s2/control_types/FRBC/frbc_simple.py b/src/flexmeasures_client/s2/control_types/FRBC/frbc_simple.py index 2187fb5d..6e81f291 100644 --- a/src/flexmeasures_client/s2/control_types/FRBC/frbc_simple.py +++ b/src/flexmeasures_client/s2/control_types/FRBC/frbc_simple.py @@ -55,7 +55,7 @@ def __init__( self._timezone = pytz.timezone(timezone) # delay the start of the schedule from the time `valid_from` - # of the FRBC.SystemDescritption. + # of the FRBC.SystemDescription. self._valid_from_shift = valid_from_shift def now(self): From 5b8aa7cf6ea070f5fdee6f639e3c8b2b034f7b1c Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Thu, 19 Feb 2026 20:21:01 +0100 Subject: [PATCH 9/9] style: flake8 Signed-off-by: F.N. Claessen --- src/flexmeasures_client/s2/script/websockets_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flexmeasures_client/s2/script/websockets_server.py b/src/flexmeasures_client/s2/script/websockets_server.py index 8db1b8f1..afceeb56 100644 --- a/src/flexmeasures_client/s2/script/websockets_server.py +++ b/src/flexmeasures_client/s2/script/websockets_server.py @@ -65,7 +65,7 @@ async def websocket_consumer(ws, cem: CEM): else: try: await cem.handle_message(json.loads(msg.json())) - except: + except TypeError: await cem.handle_message(msg.json()) elif msg.type == aiohttp.WSMsgType.ERROR: