From 2566140c2b78204f9f0471b04cd3125bb834cc35 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Thu, 18 Jun 2026 20:23:38 +0200 Subject: [PATCH] Fix Python 3.10+/websockets compatibility, add CLI args and .gitignore - ws/message.py, ws/server/ws_server_multi_user.py: drop the loop= kwarg and replace asyncio.wait(coroutines) with asyncio.gather(), both of which were removed/forbidden in Python 3.10+. - brewpi/requirements.txt: pin websockets==10.4, the latest version that still supports this code's serve()/handler API. - config.json.sim: move Model to the top level and add the missing gain field so it matches the schema brewpi.py and config.json.templ expect. - brewpi/brewpi.py: add -c/-m/-s/-d CLI args for selecting config/model files, simulation mode, and debug. - .gitignore: exclude __pycache__, logs, the local config.json, and editor/venv directories. Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 6 ++++++ brewpi/brewpi.py | 11 ++++++++++- brewpi/requirements.txt | 5 +++++ config.json.sim | 20 +++++++++++--------- ws/message.py | 2 +- ws/server/ws_server_multi_user.py | 4 ++-- 6 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ec67349 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +__pycache__/ +*.pyc +.idea/ +.venv/ +logs/ +config.json diff --git a/brewpi/brewpi.py b/brewpi/brewpi.py index 831d487..f358ca9 100755 --- a/brewpi/brewpi.py +++ b/brewpi/brewpi.py @@ -11,8 +11,17 @@ from components.actor import HeaterFactory, StirrerFactory from tasks import TaskManager, TempSensorTask, HeaterTask, PotTask, TcTask, StirrerTask, TracerTask from tracer import Tracer +import argparse as ap + if __name__ == '__main__': - config = json.load(open("config.json")) + parser = ap.ArgumentParser() + parser.add_argument("-d", "--debug", action="store_true") + parser.add_argument("-c", "--config", default="config.json") + parser.add_argument("-m", "--model", default="model.json") + parser.add_argument("-s", "--sim", action="store_true") + + args = parser.parse_args() + config = json.load(open(args.config)) dispatcher = MessageDispatcher() server = WsServerMultiUser(listener=dispatcher) taskmgr = TaskManager() diff --git a/brewpi/requirements.txt b/brewpi/requirements.txt index e69de29..1432349 100644 --- a/brewpi/requirements.txt +++ b/brewpi/requirements.txt @@ -0,0 +1,5 @@ +numpy +scipy +matplotlib +websockets==10.4 +dpath diff --git a/config.json.sim b/config.json.sim index 5b6389c..6148917 100755 --- a/config.json.sim +++ b/config.json.sim @@ -9,14 +9,6 @@ "pid_type": "Smith" }, "TempCtrl": { - "Model": { - "theta": 20, - "C": 4190, - "M": 25, - "L": 0.05, - "Td": 80, - "kn": 0.2 - }, "Kalman": { "var_P" : 1.0, "var_Q" : 0.0001, @@ -35,13 +27,23 @@ "kt": 1.5 } }, + "Model": { + "theta": 20, + "C": 4190, + "M": 25, + "L": 0.05, + "Td": 80, + "kn": 0.2, + "gain": 0.8 + }, "Plant": { "theta": 20, "C": 4190, "M": 22, "L": 0.05, "Td": 80, - "kn": 0.2 + "kn": 0.2, + "gain": 0.8 }, "Heater": { "port": "/dev/ttyUSB0", diff --git a/ws/message.py b/ws/message.py index 574c767..2299a32 100644 --- a/ws/message.py +++ b/ws/message.py @@ -35,7 +35,7 @@ class MessageDispatcher(IConnection): def __init__(self, auto_subscribe=False, loop=None): self.msg_handlers: MsgIo = [] self.state = None - self.state = asyncio.Queue(loop=loop) + self.state = asyncio.Queue() self.auto_subscribe = auto_subscribe self.loop = loop diff --git a/ws/server/ws_server_multi_user.py b/ws/server/ws_server_multi_user.py index c7d5f20..09e4671 100644 --- a/ws/server/ws_server_multi_user.py +++ b/ws/server/ws_server_multi_user.py @@ -24,12 +24,12 @@ class WsServerMultiUser(WsServer): async def notify_state(self, data): if self.USERS: # asyncio.wait doesn't accept an empty list - await asyncio.wait([user.send(data) for user in self.USERS]) + await asyncio.gather(*[user.send(data) for user in self.USERS]) async def notify_users(self): if self.USERS: # asyncio.wait doesn't accept an empty list message = {"info": {"type": "users", "count": len(self.USERS)}} - await asyncio.wait([user.send(message) for user in self.USERS]) + await asyncio.gather(*[user.send(message) for user in self.USERS]) async def register(self, websocket): usr = User(websocket)