Restructure into brewpi/client/ws packages and add README

Splits the server, GUI client, and websocket layer into their own
packages with dedicated requirements.txt files, and adds a README
documenting the project's architecture and usage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-18 20:05:08 +02:00
co-authored by Claude Sonnet 4.6
parent 4955fb073e
commit df23840f6a
15 changed files with 129 additions and 0 deletions
View File
+83
View File
@@ -0,0 +1,83 @@
#!/usr/bin/env python3
import asyncio
import json
from utils import ChangedFloat
from ws.message import MessageDispatcher
from ws.server.ws_server_multi_user import WsServerMultiUser
from components.sensor import TempSensorFactory
from components.pid import PidFactory
from components.plant import Pot
from components.actor import HeaterFactory, StirrerFactory
from tasks import TaskManager, TempSensorTask, HeaterTask, PotTask, TcTask, StirrerTask, TracerTask
from tracer import Tracer
if __name__ == '__main__':
config = json.load(open("config.json"))
dispatcher = MessageDispatcher()
server = WsServerMultiUser(listener=dispatcher)
taskmgr = TaskManager()
DT = config['Controller']['dt']
DT_TASK = 1.0 / config['Controller']['sim_warp_factor']
DT_TASK_TRACER = DT_TASK / DT
# Sensor
sensor = TempSensorFactory.create(config['Controller']['sensor_name'], temp_offset=-0.15)
sensor_task = TempSensorTask(sensor, DT_TASK, dispatcher.msgio_get("Sensor"))
taskmgr.add(sensor_task)
# Plant
pot_params = config['Plant']
pot = Pot(DT, pot_params, 20)
taskmgr.add(PotTask(pot, DT_TASK, dispatcher.msgio_get("Pot")))
# Heater
heater = HeaterFactory.create(config['Controller']['heater_name'], config['Heater'])
heater.set_on_changed("power_eff", ChangedFloat(pot.set_power, prec=0).set)
heater_task = HeaterTask(heater, DT_TASK, dispatcher.msgio_get("Heater"))
taskmgr.add(heater_task)
# Temperature Controller
tc = PidFactory.create(config['Controller']['pid_type'], DT, config['TempCtrl'], config['Model'])
tc_task = TcTask(tc, DT_TASK, dispatcher.msgio_get("TempCtrl"))
taskmgr.add(tc_task)
tc_trace_vars = [
{'variable': 'theta_ist_plant', 'name': 'theta_ist_plant', 'unit': ''},
{'variable': 'dtheta_ist_plant', 'name': 'dtheta_ist_plant', 'unit': ''},
{'variable': 'theta_ist_model', 'name': 'theta_ist_model', 'unit': ''},
{'variable': 'dtheta_ist_model', 'name': 'dtheta_ist_model', 'unit': ''},
{'variable': 'theta_ist_model_delay', 'name': 'theta_ist_model_delay', 'unit': ''},
{'variable': 'dtheta_ist_model_delay', 'name': 'dtheta_ist_model_delay', 'unit': ''}
]
trace_tc = Tracer(tc, tc_trace_vars, name='tc_trace')
# Stirrer
stirrer = StirrerFactory.create(config['Controller']['stirrer_name'], DT, config['Stirrer'])
stirrer_task = StirrerTask(stirrer, DT_TASK, dispatcher.msgio_get("Stirrer"))
taskmgr.add(stirrer_task)
# Tracer
taskmgr.add(TracerTask(sensor, heater, tc, trace_tc, DT_TASK_TRACER, dispatcher.msgio_get("Tracer")))
# Assign data flow
# Assign tc control value to heater
tc.set_on_changed("y", heater_task.actor)
# Assign temp. sensor readings to tc
sensor_task.set_on_changed("temp", ChangedFloat(tc.set_theta_ist, prec=2).set)
# Assign heater power set to tc model
heater.set_on_changed("power_set", tc.set_model_power)
# For simulation
if "sim" in config['Controller']['sensor_name']:
pot.set_on_changed("temp", ChangedFloat(sensor.set_fake_temp, prec=3).set)
sensor.set_fake_temp(pot.temp)
# Message dispatcher
h_dispatcher = taskmgr.start()
h_server = server.listen("0.0.0.0", 8765)
asyncio.gather(h_dispatcher, h_server)
server.run_forever()
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
source $WORKON_HOME/brewpi/bin/activate
$BREWPI_HOME/brewpi.py
View File