Skip to main content

Controls — HMI bindings

FieldDetail
Primary artifact(s)controls/water/hmi/bindings.md
SpecRO-SPEC-001 §5.4 ; WIRE-001

Summary

Widget→tag map for CM5 E-HMI export. Each row documents widget/group, plc_tag, datatype (from tags.csv), fmt, and alarms / colours. Organized by screen to match screens.md.

Screen / groupBinding countRepresentative widgets
HomeMain32HomePressGrid.*, HomeCondStrip.CT103, StartSafeMomentary, ANN_ALM_* banners
RecipeSelect6 (+ indexed)RecipeIdxSpin, RCP_{n}_* NV mirror
RecipeEditDelta8PpmDeltaMg/Ca/Na, DeltaCyclesRemain, CALC_TDSDEV_ABS
AlarmActive20ANN_ALM_WORD0, AlarmRow.b0–b14, HMI_ACK_ALARMS
TrendsMulti4TrendBufferCT103, TrendBufferTT200, PT104 / TT101 traces
CoolingDetail9RTD_TT200_ENCLOSURE, FAN relays, enclosure SPs
UVDisinfectWizard9HMI_DISINFECT_CHK01, SEQ_DISINFECT_LOCKOUT_ACTIVE
DiagnosticsForces24All DO_* force rows, AI/RTD inject

Colour / severity legend: critical → red; safety → amber lock; warn → amber; info → blue-gray; relay ON → green. Alarm row copy in hmi-alarms (alarm-strings.csv).

Test

CM5 offline simulator — tag browser diff vs tags.csv: every plc_tag in bindings.md (excluding {n} patterns and commission placeholders) must resolve.

Offline parity check (from repo root):

python3 - <<'PY'
import csv, re
from pathlib import Path

tags = {r["tag_name"]: r["data_type"] for r in csv.DictReader(open("controls/water/tags/tags.csv"))}
text = Path("controls/water/hmi/bindings.md").read_text(encoding="utf-8")
bound = set(re.findall(r"`([A-Z][A-Z0-9_]+)`", text))
# Drop widget IDs, SP cross-refs already in CSV, and pattern placeholders
skip = {"ON", "OFF", "REAL", "UINT", "INT", "WORD", "BOOL", "Commission"}
bound = {t for t in bound if not t.startswith(("Home", "Recipe", "Trend", "Cool", "Uv", "Diag", "Alarm", "Annunciator", "Ack", "Delta", "Start", "Stop", "Ppm"))}
commission = {"RCP_APPLY_TRIG"}
missing = sorted(t for t in bound if t not in tags and t not in commission and "{" not in t and t not in skip)
assert not missing, f"bindings reference tags missing from CSV: {missing}"
print("OK:", len(bound), "tag refs checked against tags.csv")
PY

Walk each screen in hmi-screens and confirm widget IDs resolve to the same plc_tag.

Changelog

  • 2026-05-24 — Expanded bindings from partial HomeMain subset to full eight-screen map. Added columns: widget/group, datatype, fmt, alarms/colours. Synchronized all plc_tag names with current tags.csv (140 rows). Documented recipe indexed RCP_{n}_* pattern and RCP_APPLY_TRIG commission placeholder.

Open items

  • Add RCP_APPLY_TRIG to tags.csv when RecipeEditDelta Apply button is wired
  • FT101 / FT103 derived gpm display tags (HomeMain flow strip placeholders)
  • Spanish toggle for alarm colour legend (future)

Reviewer sign-off

  • Bindings reviewed against RO-SPEC-001 §5.4 and CM5 tag browser import — _______________