feat(fusion_iot): add setpoint/optimum + deviation to sensor schema

Sensors previously only tracked alarm thresholds (alert_min/alert_max).
Missing the third piece of standard process control: the SETPOINT —
what the heater/chiller controls toward and what dashboards compare
against. Without it an operator can't tell whether 89°C is "on target"
or "barely still in spec".

Schema changes:

**fusion.plating.bath.parameter** (shop-wide default)
- New `target_value` field — the default setpoint for this parameter
  across the shop (e.g. 87°C for ENP bath). Parallel to existing
  target_min / target_max.

**fp.tank.sensor** (per-sensor override)
- New `target_value_override` — per-sensor override, zero = inherit
  from parameter. Matches the existing override pattern for alert
  thresholds so users can fine-tune per-tank without touching the
  shop-wide spec.
- New `effective_target` / `effective_target_unit` computed — resolves
  override → parameter default, converts to company-preferred unit.
- New `_get_setpoint()` helper for internal use.

**fp.tank.reading**
- New `deviation_from_target` — signed Δ from the sensor's effective
  setpoint, in the company's preferred unit. Positive = above, negative
  = below, zero if no setpoint defined.
- New `deviation_band` (selection: on/near/far/out/none) — coarse band
  for fast visual scanning. `on` = within ±1° of target, `near` = ±3°,
  `far` = beyond, `out` = actually out of the alarm band.

**Views**
- Sensor form: split the alerting panel into two groups — "Target
  (setpoint)" on the left, "Alarm band" on the right. Makes the
  distinction between "where we want to be" and "where we'd panic"
  visually obvious.
- Reading list: new Δ + band columns, with decoration classes
  (success/info/warning/danger) so the list reads at a glance.
- Tank form Sensors tab: inline setpoint + unit column.

Seeded: parameter "Bath Temperature (Hot Process)" now carries
target_value=87°C as a realistic ENP shop default. Sensors inherit
unless they set their own override.

Design decisions kept simple:
- Did NOT add a warning band (warn_min/warn_max). Two-tier model
  (setpoint + alarm band) is enough for the pilot. Can add soft
  warnings later as a separate commit if ops wants them.
- Did NOT auto-control heaters. Setpoint is stored as metadata only;
  actual heater actuation via IoT is a future phase C project.

Verified: setpoint 87°C stored → displays 188.60°F on the live pilot
sensor (company pref = F). Each incoming reading correctly computes
signed deviation; bands colour the reading list appropriately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-20 16:36:58 -04:00
parent 089cda71fe
commit 118f96dad4
8 changed files with 146 additions and 10 deletions

View File

@@ -10,15 +10,22 @@
<field name="model">fp.tank.reading</field>
<field name="arch" type="xml">
<list string="Sensor Readings"
decoration-danger="not in_spec" default_order="reading_at desc">
default_order="reading_at desc"
decoration-danger="deviation_band == 'out'"
decoration-warning="deviation_band == 'far'"
decoration-info="deviation_band == 'near'"
decoration-success="deviation_band == 'on'"
decoration-muted="deviation_band == 'none'">
<field name="reading_at"/>
<field name="sensor_id"/>
<field name="tank_id" optional="show"/>
<field name="parameter_id" optional="hide"/>
<field name="display_value"/>
<field name="display_unit"/>
<field name="deviation_from_target"/>
<field name="deviation_band" widget="badge"/>
<field name="value" optional="hide" string="Value (°C raw)"/>
<field name="in_spec" widget="boolean_toggle"/>
<field name="in_spec" widget="boolean_toggle" optional="show"/>
<field name="source" optional="hide"/>
<field name="hold_id" optional="show"/>
</list>

View File

@@ -69,13 +69,19 @@
<field name="parameter_id" options="{'no_create': True}"/>
</group>
</group>
<group string="Alerting">
<group>
<group string="Setpoint &amp; Alerting">
<group string="Target (setpoint)">
<field name="target_value_override"
help="Leave 0 to inherit from bath parameter's Default Setpoint. This is the IDEAL operating value — not an alarm threshold."/>
<field name="effective_target" readonly="1"/>
<field name="effective_target_unit" readonly="1"/>
</group>
<group string="Alarm band">
<field name="alert_on_out_of_spec"/>
<field name="alert_min_override"
help="Leave 0 to inherit from the bath parameter's target_min."/>
help="Leave 0 to inherit from the bath parameter's target_min. Readings below this fire a quality hold."/>
<field name="alert_max_override"
help="Leave 0 to inherit from the bath parameter's target_max."/>
help="Leave 0 to inherit from the bath parameter's target_max. Readings above this fire a quality hold."/>
</group>
<group string="Most Recent Reading">
<field name="last_reading_display" readonly="1"/>

View File

@@ -24,6 +24,8 @@
<field name="device_kind"/>
<field name="device_serial"/>
<field name="parameter_id"/>
<field name="effective_target" readonly="1"/>
<field name="effective_target_unit" readonly="1"/>
<field name="last_reading_display"/>
<field name="last_reading_display_unit"/>
<field name="last_reading_at" readonly="1"/>