scada-points.csv led with a scada_tag column of PS_* names derived from
the PLC register map - PS_STN_WET_WELL_LEVEL and the like. CI Server never
adopted them. They named nothing that exists, nothing in this repo read
them, and read as if authoritative they have already caused a real defect
in a downstream project.
Replaced with ci-server-points.csv, the as-built delivery from the CI
Server side (copied from yau-plant-assistant, not re-derived). It is keyed
on the CI Server item, with the station and point name beside it:
ci_item,ci_station,ci_point,description,poll_group,...
gen_scada_points.py now reproduces that file byte-identically, taking the
names from the LEAF table in gen_ciserver_qli.py so the CSV and the .qli
cannot disagree. tag_for() is gone. Verified: the CSV and all three .qli
regenerate unchanged, and all six displays still build.
The four poll groups keep their PS_ names - PS_STATUS_BITS, PS_PUBLISHED,
PS_SETPOINTS, PS_SIM_CONTROL. Those are live configuration, and are the
only legitimate PS_ names.
modbus_points/README.md gains a 'four namespaces' section - instrument tag,
PLC address, CI Server point, CI Server item - since confusing them is what
produced the placeholder column in the first place.
Also settles the historian drift left open in the previous commit. The
live export is the authority: the server runs WRPS_ONE_SEC at 5 SECONDS,
not 1, and WRPS_THIRTY_SEC at 30 seconds rather than a 60 second
WRPS_ONE_MIN. Code assuming 60 s was wrong by twelvefold. Recorded in
historian/README.md with a caution never to hardcode a sample interval.
Every .qli in the delivery was byte-identical to ours - only the CSV
differed.
|
||
|---|---|---|
| .. | ||
| build_display.py | ||
| build_tagtest.py | ||
| check_layout.py | ||
| component-kit.md | ||
| DEPLOY.md | ||
| item-ids.csv | ||
| item-ids.meta.json | ||
| point_format.py | ||
| README.md | ||
| render_preview.py | ||
hmi — what CI Server can draw, and the kit we build with
Study of the live CI Server deployment copied to
99-reference/ciserver-hmi-deployment/: 53 components, 3130
symbols (177 of them the AOG standard set), 74 displays, 2 layouts.
C:\Users\Public\Yokogawa\tlsis reference only. Never edit it. Everything is authored in this repo and handed over for the user to deploy.
1. Components — the primitives a display is made of
| Group | Components |
|---|---|
| Drawing | Rectangle Ellipse Arc Line Polygon Spline Text Icon |
| Structure | Display GraphicSet Symbol SymbolInstance VisibilityGroup VisualizationLayer VisualizationParameter Link |
| Data display | Number DataBar CircularScale RectangularScale Radial MicroTrend Chart DtsChart |
| Input | JButton JToggleButton JCheckBox JRadioButton JComboBox JSlider JSpinner JFormattedNumberField JFormattedTextField JTextArea JDateTimeField JList JNavigationTree |
| System | AlarmOverview ShelvedOverview BlockedItems AlarmSound Playback Reporting MapViewer PDFViewer DatasetTable DatasetForm ScriptedFunction |
So the earlier claim that CI View was "rectangles and text only" was wrong — that was an artefact of the Straddle screens, which happen to use little else. Ellipses, lines, polygons, trends, gauges and real input widgets are all available.
2. AOG — the standard symbol library
symbols/AOG_*.xml is Yokogawa's Advanced Operating Graphics set: a
high-performance HMI standard in the ISA-101 tradition. Relevant here:
| Purpose | Symbol |
|---|---|
| Analog value | AOG_ProcessIndicator, AOG_NumberIndicator |
| Typed instrument | AOG_IndicatorLevel AOG_IndicatorFlow AOG_IndicatorPressure AOG_IndicatorTemperature |
| Bar / needle | AOG_VerticalBarIndicator AOG_HorizontalBarIndicator AOG_*NeedleIndicator AOG_RadialNeedleIndicator |
| Digital state | AOG_OnOffIndicator AOG_AlarmIndicator AOG_TextIndicator AOG_ManualIndicator |
| Equipment | AOG_Pump AOG_PumpSimple AOG_PumpWithOutlet AOG_Motor AOG_Tank AOG_Vessel AOG_AtmosphericTank |
| Valves | AOG_CheckValve AOG_Horizontal2WayValve AOG_VerticalOnOffValve AOG_ButterflyValve AOG_BlockValveStation |
| Instrument bubble | AOG_Instrument AOG_Transmitter |
| Faceplate | AOG_Faceplate AOG_FP_Frame AOG_FP_PVValue AOG_FP_SVValue AOG_FP_Mode AOG_FP_Status AOG_FP_BarIndicator |
| Trend | AOG_Trend AOG_TrendIndicator |
| Screen furniture | AOG_DisplayTitle AOG_SelectionBox AOG_NavigationSelectionBox AOG_TagNameComponent |
An AOG_O* variant exists for most (AOG_OPump, AOG_ONumberIndicator …).
The parameter contract — this is what standardisation means here
Every dynamic AOG symbol takes the same external parameters:
item the SCADA item to display (AID.WRPS.STN.LEVEL)
setPointItem optional companion item
tagName label, with alwaysShowTagName / neverShowTagName
format numeric format
showBackground draw the indicator box
showAlarmIndicator built-in alarm annunciation
selectable can the operator click it
displayToActivate display opened on click <- this is how faceplates work
Two consequences worth stating plainly:
- Analog values are consistent by construction. Every one is an
AOG_ProcessIndicator; nothing is hand-drawn, so nothing can drift. - Faceplates are separate displays, not overlays. A symbol names one in
displayToActivate.AOG_ItemFaceplateandAOG_ObjectFacePlatealready exist and can be used as-is, or copied and specialised for a pump.
Ready-made displays
displays/AOG_displays/ includes AOG_DisplayTemplate (start a new display from
it), AOG_Style (the colour tokens), AOG_ItemFaceplate, AOG_ItemTuningPanel,
AOG_AlarmBanner, AOG_AlarmCurrent, AOG_MenuMain, AOG_SetNumberPV/SV/SH/SL
(the standard numeric-entry popups — use these for setpoint writes rather than
building an entry field).
3. Two styles exist on this system — pick one
| AOG standard | Site style (Straddle screens) | |
|---|---|---|
| Ground | #E3E3E3 light grey |
#171B22 near-black |
| Panels | #F0F0F0 / #F2F2F2 |
#262D38 / #333B47 |
| Text | #404040 / #6D6D6D |
#C8D0DA |
| Accent | none — colour is reserved | #5FB8D0 cyan |
| Alarm | #FF0000 #FFA500 #FFFF00 |
#D65B5B |
| Built from | AOG symbols | hand-drawn rectangles + text |
The AOG palette follows the high-performance HMI convention: a grey plant, and
colour only where something is abnormal. The site's own Straddle screens are a
custom dark theme that does not use the AOG library at all — no display in the
deployment instantiates a single AOG_* symbol.
Recommendation: AOG. It is the product standard, it brings the faceplate machinery and alarm annunciation for free, and its parameter contract is what keeps every indicator identical. The cost is that the demo will not match the Straddle screens an operator may already know.
4. Decision: our own kit, AOG as reference only
Settled 2026-08-14 with the user:
- Build our own components, not AOG instances — only what this project needs. AOG's parameter contract is the thing worth copying, not its artwork.
- Light theme, but not AOG's. The customer reads AOG as dated; the cause is the bevelled 3D symbols and mid-grey ground, so the kit is flat, square, hairline bordered, white on cool neutral.
- 16:9, and operators may write setpoint, command and simulation items.
The kit is specified in component-kit.md. The table below is superseded by it
and kept only to show which AOG symbol each of our components was modelled on.
5. AOG reference for each component we built
What each element of the display is built from, so the same thing always looks the same:
| Element | Component | Bound to |
|---|---|---|
| Title bar | AOG_DisplayTitle |
— |
| Wet well | AOG_Tank + AOG_VerticalBarIndicator |
STN.LEVEL |
| Level, flows, pressures, speed | AOG_ProcessIndicator |
STN.*, PU30x.* |
| Level switches, run/avail/trip | AOG_OnOffIndicator |
PU30x.*, STN.* |
| Pumps | AOG_Pump, displayToActivate = pump faceplate |
PU30x.RUNNING |
| Check / isolation valves | AOG_CheckValve, AOG_Horizontal2WayValve |
static |
| Instrument bubbles | AOG_Instrument |
tag text |
| Setpoint entry | AOG_SetNumberSV popup |
SP.* |
| Pump faceplate | copy of AOG_ItemFaceplate |
PU30x.* |
| Buttons (mode, commands, simulation) | AOG_SelectionBox / JButton |
SP.MODE, SP.CMD_WORD, SIM.* |
Scripts in this directory
| Command | What it does |
|---|---|
python build_display.py |
Builds the three displays into out/. Refuses to build if the item ids cannot be proven current. |
python build_display.py --harvest <saved.xml> |
Re-calibrates the item ids from a display CI View saved, and records provenance |
python build_display.py --verify <saved.xml> |
Compares CI Server's own ids against what the build emits; exit 1 on any mismatch |
python build_tagtest.py |
Builds the diagnostic display that lists every item |
python check_layout.py |
Reports text that collides with other text; exit 1 on any collision |
The two -- modes exist because of the failure that keeps recurring: an item
id that no longer matches CI Server binds silently to nothing, and the screen
looks fine. DEPLOY.md has the ritual.
Status
Study complete; nothing built yet. The layout is under review as a mockup — see
the preview link in the conversation, and 04-scada/hmi/ will hold the display
XML once the style question above is settled.