Add explicit initial grain_mass/water_mass to the Sud doc
Sud now parses top-level grain_mass/water_mass (sibling to pot_mass/ pot_material/L/Td, defaulting to 0/0) - what's actually in the pot before the brew starts, as opposed to default.step's grain_mass/water_mass, which is just inert template filler. All sude/*.json docs gain explicit values matching what their first step already resolved to. tasks/sud.py's apply_plant_params() now takes grain_mass/water_mass directly instead of a step dict: on_step_changed() still passes the active step's own (these vary as malt goes in/water boils off), but the Load handler now reads Sud.grain_mass/water_mass directly instead of parsing schedule[0]. The GUI's status-line mass preview (shown immediately on Load, before Start) does the same. Also fixes a latent bug found along the way: _continue_forecast_after_confirm()'s reconstructed sub-doc was missing L/Td/grain_mass/water_mass entirely, silently falling back to generic defaults instead of the real Sud's own values - invisible only because every current sude/*.json happens to use those same defaults. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DkkuG48uHFCGKe6dPSERFk
This commit is contained in:
+19
-12
@@ -55,17 +55,20 @@ class SudTask(ATask):
|
||||
self.forecast_confirm_marks = {}
|
||||
msg_handler.set_recv_handler(self.recv)
|
||||
|
||||
def apply_plant_params(self, step):
|
||||
def apply_plant_params(self, grain_mass, water_mass):
|
||||
"""Keeps the real plant's and the controller's internal model's
|
||||
plant params in sync with this Sud's own doc - L/Td come straight
|
||||
from it (constant for the whole brew), while M/C also fold in the
|
||||
step's grain_mass/water_mass, which vary over the brew's course
|
||||
given grain_mass/water_mass, which vary over the brew's course
|
||||
(malt going in, water boiling off) - mirrors demo_sud.py's
|
||||
apply_plant_params(). Called both on every real step transition
|
||||
(via on_step_changed()) and once immediately on Load (see recv()),
|
||||
so the controller's behavior already matches the expected plant
|
||||
as soon as a Sud is loaded, not just once a run actually starts."""
|
||||
params = self.sud.derive_plant_params(step.get('grain_mass', 0), step.get('water_mass', 0))
|
||||
(via on_step_changed(), with that step's own grain_mass/water_mass)
|
||||
and once immediately on Load (see recv(), with the doc's own
|
||||
initial Sud.grain_mass/water_mass - no need to parse the first
|
||||
step out of the schedule for that), so the controller's behavior
|
||||
already matches the expected plant as soon as a Sud is loaded,
|
||||
not just once a run actually starts."""
|
||||
params = self.sud.derive_plant_params(grain_mass, water_mass)
|
||||
self.pot.set_plant_params(params)
|
||||
if hasattr(self.tc, 'set_model_plant_params'):
|
||||
self.tc.set_model_plant_params(params)
|
||||
@@ -95,7 +98,7 @@ class SudTask(ATask):
|
||||
phase = ramp if ramping else hold
|
||||
|
||||
if step is not None:
|
||||
self.apply_plant_params(step)
|
||||
self.apply_plant_params(step.get('grain_mass', 0), step.get('water_mass', 0))
|
||||
if ramping and step['temperature'] is not None:
|
||||
self.tc.set_theta_soll(step['temperature'])
|
||||
self.tc.set_heatrate_soll(ramp['rate'])
|
||||
@@ -214,6 +217,10 @@ class SudTask(ATask):
|
||||
'Description': self.sud.description,
|
||||
'pot_mass': self.sud.pot_mass,
|
||||
'pot_material': self.sud.pot_material,
|
||||
'L': self.sud.L,
|
||||
'Td': self.sud.Td,
|
||||
'grain_mass': self.sud.grain_mass,
|
||||
'water_mass': self.sud.water_mass,
|
||||
'steps': schedule[index:],
|
||||
}
|
||||
start_theta = self.tc.get_theta_ist()
|
||||
@@ -264,12 +271,12 @@ class SudTask(ATask):
|
||||
# on_step_changed() only re-applies plant params once a
|
||||
# real step starts (Start) - apply them right away too,
|
||||
# so the controller already matches this Sud's own pot/
|
||||
# L/Td (and its first step's expected grain/water mass)
|
||||
# from the moment it's loaded, rather than whatever the
|
||||
# previously loaded Sud (or the generic startup
|
||||
# baseline - see server/brewpi.py) left behind.
|
||||
# L/Td/initial grain_mass/water_mass from the moment
|
||||
# it's loaded, rather than whatever the previously
|
||||
# loaded Sud (or the generic startup baseline - see
|
||||
# server/brewpi.py) left behind.
|
||||
if self.sud.schedule:
|
||||
self.apply_plant_params(self.sud.schedule[0])
|
||||
self.apply_plant_params(self.sud.grain_mass, self.sud.water_mass)
|
||||
await self.send_forecast(pair[1])
|
||||
else:
|
||||
# Sud.load() refuses while a run is in progress (state
|
||||
|
||||
Reference in New Issue
Block a user