Build the heater/pot/sensor rig as one unit, picked by plant_name alone
heater_name/sensor_name/plant_name were three independent config keys, each picked via its own factory - in practice sim and real hardware are never actually mixed and matched, so this could (nonsensically) disagree, e.g. a real heater paired with a simulated sensor. Add PlantFactory (components/plant/plant_factory.py): plant_name alone now builds the whole rig together. "sim" gets HeaterSim/Pot (the modeled plant, as before)/TempSensorSim. Anything else gets HeaterHendi/PotReal/TempSensor_max31865 - PotReal is a new, deliberately unmodeled Pot for the real, physical kettle (components/plant/pot_real.py): the real temperature comes straight from the real sensor, not from a model, so it just accepts and ignores set_plant_params()/ set_ambient_temperature()/initial() and reports no temperature of its own, satisfying PotTask/SudTask's interface with nothing to actually simulate. heater_name/sensor_name are gone from config.json.templ; server/brewpi.py delegates to HeaterFactory/TempSensorFactory lazily from inside PlantFactory, same as before, so real hardware's spidev/pyserial deps still aren't needed just to import the module.
This commit is contained in:
@@ -92,22 +92,26 @@ sude/ Mash schedules ("Sud" = brew/wort), each a
|
||||
for user confirmation.
|
||||
|
||||
config.json.templ Configuration template - the "sim" component
|
||||
names (sensor/heater/stirrer/plant) already
|
||||
default to simulation; point Heater/Stirrer
|
||||
at real serial ports to switch to hardware.
|
||||
names (stirrer/plant) already default to
|
||||
simulation; point Stirrer/Heater at real
|
||||
serial ports and plant_name at a real
|
||||
backend to switch to hardware.
|
||||
```
|
||||
|
||||
### Data flow
|
||||
|
||||
The server (`server/brewpi.py`) loads `config.json`, builds the configured
|
||||
sensor/heater/stirrer/controller via factories (`*Factory.create(name, ...)`)
|
||||
based on the `Controller` section (`sensor_name`, `heater_name`,
|
||||
`stirrer_name`, `pid_type`, or `"sim"` for any of them), and connects their
|
||||
outputs to each other's inputs via `set_on_changed` callbacks, e.g.:
|
||||
stirrer/controller via factories (`*Factory.create(name, ...)`), and the
|
||||
heater/pot/sensor trio together as one consistent rig via `PlantFactory`
|
||||
(`components/plant/plant_factory.py`) - based on the `Controller` section
|
||||
(`stirrer_name`, `pid_type`, `plant_name`, or `"sim"` for any of them) -
|
||||
and connects their outputs to each other's inputs via `set_on_changed`
|
||||
callbacks, e.g.:
|
||||
|
||||
- sensor temperature → temperature controller's `theta_ist`
|
||||
- temperature controller output `y` → heater power
|
||||
- heater effective power → pot model power (simulation only)
|
||||
- heater effective power → pot model power (simulation only - PotReal, the
|
||||
real, unmodeled kettle, has no model to feed)
|
||||
|
||||
Each component runs inside its own `ATask` at a configurable interval
|
||||
(`Controller.dt`, scaled by `sim_warp_factor`) and pushes state changes onto a
|
||||
@@ -172,9 +176,11 @@ pip install -r client/requirements.txt
|
||||
|
||||
1. Copy `config.json.templ` to `config.json` next to `brewpi.py` - it
|
||||
already runs entirely in simulation (no hardware needed) as-is; switch
|
||||
any of the `sensor_name`/`heater_name`/`stirrer_name`/`plant_name`
|
||||
`"sim"` values to a real backend, and set the corresponding serial
|
||||
port, to use real hardware.
|
||||
`stirrer_name`/`plant_name`'s `"sim"` value(s) to a real backend, and
|
||||
set the corresponding serial port, to use real hardware. `plant_name`
|
||||
alone picks the heater/pot/sensor trio together (see `PlantFactory`) -
|
||||
`"sim"` gets `HeaterSim`/`Pot`/`TempSensorSim`, anything else gets
|
||||
`HeaterHendi`/`PotReal`/`TempSensor_max31865`.
|
||||
2. Start the server:
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user