refactor: move pot hardware params and pid_type out of per-brew docs
Pot hardware constants (mass, material, L, Td) moved from sude/*.json to config.json's Pot section; Sud/SudForecastEstimator accept pot_config as baseline, per-brew pot sections may still override. Controller key removed; pid_type moved into TempCtrl. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+20
-10
@@ -82,28 +82,38 @@ EMPTY_SUD = {
|
||||
|
||||
|
||||
class Sud(AttributeChange):
|
||||
def __init__(self):
|
||||
def __init__(self, pot_config=None):
|
||||
"""Starts out with no schedule loaded - one of potentially several
|
||||
sude/*.json files on disk is brought in later via load(), kept
|
||||
purely in memory (see load()) until replaced or the server
|
||||
restarts."""
|
||||
restarts.
|
||||
|
||||
pot_config provides hardware baseline values (mass, material, L, Td)
|
||||
from config.json's Pot section - a loaded sud.json may override any
|
||||
of them per-brew, but config is the source of truth for the physical
|
||||
kettle."""
|
||||
AttributeChange.__init__(self)
|
||||
self._pot_config = pot_config or {}
|
||||
self._data = EMPTY_SUD
|
||||
|
||||
(self.name, self.description, self.schedule, self.pot_mass,
|
||||
self.pot_material, self.L, self.Td, self.grain_mass,
|
||||
self.water_mass) = self._parse_data(self._data)
|
||||
self.water_mass) = self._parse_data(self._data, self._pot_config)
|
||||
|
||||
self._paused_from = None
|
||||
self._reset_run_state()
|
||||
|
||||
@staticmethod
|
||||
def _parse_data(data):
|
||||
def _parse_data(data, pot_config=None):
|
||||
"""Parses a sud.json document into the (name, description, schedule,
|
||||
pot_mass, pot_material, L, Td, grain_mass, water_mass) tuple Sud
|
||||
needs. Computed up front rather than assigned straight onto self,
|
||||
so a malformed load() can't leave a half-applied schedule in
|
||||
place."""
|
||||
place.
|
||||
|
||||
pot_config (from config.json's Pot section) provides hardware baseline
|
||||
values; a sud.json's own pot section overrides any of them per-brew."""
|
||||
pot_config = pot_config or {}
|
||||
name = data.get('Name', '')
|
||||
description = data.get('Description', '')
|
||||
|
||||
@@ -111,10 +121,10 @@ class Sud(AttributeChange):
|
||||
schedule = [_build_step(i + 1, step_defaults, raw) for i, raw in enumerate(data['steps'])]
|
||||
|
||||
pot_data = data.get('pot', {})
|
||||
pot_mass = pot_data.get('mass', 0)
|
||||
pot_material = pot_data.get('material')
|
||||
L = pot_data.get('L', EMPTY_SUD['pot']['L'])
|
||||
Td = pot_data.get('Td', EMPTY_SUD['pot']['Td'])
|
||||
pot_mass = pot_data.get('mass', pot_config.get('mass', 0))
|
||||
pot_material = pot_data.get('material', pot_config.get('material'))
|
||||
L = pot_data.get('L', pot_config.get('L', EMPTY_SUD['pot']['L']))
|
||||
Td = pot_data.get('Td', pot_config.get('Td', EMPTY_SUD['pot']['Td']))
|
||||
grain_mass = pot_data.get('grain_mass', EMPTY_SUD['pot']['grain_mass'])
|
||||
water_mass = pot_data.get('water_mass', EMPTY_SUD['pot']['water_mass'])
|
||||
|
||||
@@ -147,7 +157,7 @@ class Sud(AttributeChange):
|
||||
if self.state not in (SudState.IDLE, SudState.DONE):
|
||||
return False
|
||||
try:
|
||||
parsed = self._parse_data(data)
|
||||
parsed = self._parse_data(data, self._pot_config)
|
||||
except (KeyError, TypeError):
|
||||
return False
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ class SudForecastEstimator:
|
||||
real run actually is (the discrete steps end up duty-cycling it back
|
||||
down to something close to the commanded average)."""
|
||||
|
||||
def __init__(self, dt, theta_amb, pid_type, tempctrl_params, heater_powers, sim_warp_factor):
|
||||
def __init__(self, dt, theta_amb, pid_type, tempctrl_params, heater_powers, sim_warp_factor, pot_config=None):
|
||||
self.dt = dt
|
||||
self.theta_amb = theta_amb
|
||||
self.pid_type = pid_type
|
||||
@@ -61,6 +61,7 @@ class SudForecastEstimator:
|
||||
# pair straddling the commanded power.
|
||||
self.heater_powers = heater_powers
|
||||
self.sim_warp_factor = sim_warp_factor
|
||||
self.pot_config = pot_config or {}
|
||||
|
||||
def set_ambient_temperature(self, theta_amb):
|
||||
self.theta_amb = theta_amb
|
||||
@@ -93,7 +94,7 @@ class SudForecastEstimator:
|
||||
if start_theta is None:
|
||||
start_theta = self.theta_amb
|
||||
|
||||
sud = Sud()
|
||||
sud = Sud(self.pot_config)
|
||||
if not sud.load(doc) or not sud.schedule:
|
||||
return [0.0], [start_theta], SudState.DONE, {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user