Sample operator HMI (CIENG_* displays, layouts, user CIENG, live-data feed) and tested findings ISS-068..075 #24

Merged
cliu merged 7 commits from feature/cieng-hmi into main 2026-10-06 11:32:18 +11:00
Showing only changes of commit 0e5a39361c - Show all commits

View file

@ -4,7 +4,8 @@ A small, invented sample project that anyone with this repo can load into a CI S
**R1.03** test system. Skills use its names in their examples, and every skill task is **R1.03** test system. Skills use its names in their examples, and every skill task is
re-tested against it so that no other project is needed. re-tested against it so that no other project is needed.
Built and tested on CI Server R1.03.00 (unlicensed test system), 2026-09-30. Built and tested on CI Server R1.03.00 (unlicensed test system), 2026-09-30; operator HMI, demo
user and live-data feed added 2026-10-06.
## Load and remove ## Load and remove
@ -21,6 +22,10 @@ cmd /c "<repo>\examples\CI-Eng-Sample\remove.cmd"
- **Restart CI Server after loading** (stop, then start the CI Service): a new storage group - **Restart CI Server after loading** (stop, then start the CI Service): a new storage group
stores no history until CI Server restarts. stores no history until CI Server restarts.
- `load.cmd` on a system that already has the project reports `Exists` and changes nothing. - `load.cmd` on a system that already has the project reports `Exists` and changes nothing.
- Before `remove.cmd`, log out every `CIENG` session (Operator Interface and web): a group
cannot be removed while a session of its user is open (`DSSP-E-NODEL` … `USER_VAL`), and a
retry in that state stopped the `DSSSDA03` process (`DUR-F-BAD_SIZE`) until CI Server was
restarted (2026-10-06).
- `remove.cmd` takes about 1½ minutes: a storage group can only be deleted after its stop time - `remove.cmd` takes about 1½ minutes: a storage group can only be deleted after its stop time
has passed, so the script sets a stop time one minute ahead and waits. Removing the group has passed, so the script sets a stop time one minute ahead and waits. Removing the group
also deletes its history. also deletes its history.
@ -43,6 +48,7 @@ cmd /c "<repo>\examples\CI-Eng-Sample\remove.cmd"
| `CI-Eng-Sample.TANK1.LEVEL.MAX` | Sub-item, Min-Max | Highest level seen | | `CI-Eng-Sample.TANK1.LEVEL.MAX` | Sub-item, Min-Max | Highest level seen |
| `CI-Eng-Sample.DEMO` | Section | Tutorial examples | | `CI-Eng-Sample.DEMO` | Section | Tutorial examples |
| `CI-Eng-Sample.DEMO.COUNTER` | Item, Integer | Counts 1…100, one step per second, written by `DEMO.INCR1` | | `CI-Eng-Sample.DEMO.COUNTER` | Item, Integer | Counts 1…100, one step per second, written by `DEMO.INCR1` |
| `CI-Eng-Sample.DEMO.FEED_ON` | Item, Boolean | 1 while the live-data feed runs in display mode (`feed\cieng_feed.ps1 -UntilFlag`); the display button *Stop* writes 0 |
| `CIENG_1S` | Trigger group | Every second | | `CIENG_1S` | Trigger group | Every second |
| `CIENG_INCR` | Class (traditional) | Increments `DEMO.COUNTER`, wraps at 100; compiled on load | | `CIENG_INCR` | Class (traditional) | Increments `DEMO.COUNTER`, wraps at 100; compiled on load |
| `CI-Eng-Sample.DEMO.INCR1` | Object | Instance of `CIENG_INCR` | | `CI-Eng-Sample.DEMO.INCR1` | Object | Instance of `CIENG_INCR` |
@ -72,7 +78,9 @@ cmd /c "<repo>\examples\CI-Eng-Sample\remove.cmd"
| `CIENG_ACK` | Acknowledgement type | Every alarm needs an acknowledgement; return to normal automatic only if the alarm was acknowledged (same matrix as `MANUAL`) | | `CIENG_ACK` | Acknowledgement type | Every alarm needs an acknowledgement; return to normal automatic only if the alarm was acknowledged (same matrix as `MANUAL`) |
| `CIENG_TANKS` | Area of interest | Label for tank items (`TANK1.LEVEL` `AOI_1`) | | `CIENG_TANKS` | Area of interest | Label for tank items (`TANK1.LEVEL` `AOI_1`) |
| `CIENG_TANK1` | Alarm selection area | `SECTION = "CI-Eng-Sample.TANK1"`, compiled on load | | `CIENG_TANK1` | Alarm selection area | `SECTION = "CI-Eng-Sample.TANK1"`, compiled on load |
| `CIENG_VIEWER` | Authorization group | Read-only: `ITEM_READ`, `SECTION_READ`, `ALARM_CURRENT_READ`, `ALARM_CHRONO_READ`. No users are created by the sample. | | `CIENG_VIEWER` | Authorization group | Read-only: `ITEM_READ`, `SECTION_READ`, `ALARM_CURRENT_READ`, `ALARM_CHRONO_READ` |
| `CIENG_OPERATOR` | Authorization group | The actions of the factory group `OPERATOR` plus `EXECUTE_GENERAL_COMMANDS` (server-side command of the live-data button) |
| `CIENG` | User | Demo user, **no password**, group `CIENG_OPERATOR`; logs on to layout `CIENG_Operator` with display `CIENG_Overview` (desktop and web). The only user the sample creates; `ADMIN` is not changed. |
| `CIENG_FILE` | Printer device + destination | FILE output to `%TLS_LST_PATH%\cieng_report.txt` (overwritten by each printed report); destination visible to operators | | `CIENG_FILE` | Printer device + destination | FILE output to `%TLS_LST_PATH%\cieng_report.txt` (overwritten by each printed report); destination visible to operators |
| `CIENG_TANK1` | Report | Values of the `TANK1` items + last-hour statistics of one item (ad-hoc parameter chosen in an item browser, default `LEVEL`); daily 06:00 local time and ad hoc; output `CIENG_FILE`; lifetime 1 week | | `CIENG_TANK1` | Report | Values of the `TANK1` items + last-hour statistics of one item (ad-hoc parameter chosen in an item browser, default `LEVEL`); daily 06:00 local time and ad hoc; output `CIENG_FILE`; lifetime 1 week |
| `CIENG_INFLOW_HI` | Report | Generated 5 s after `TANK1.INFLOW` rises above 400; output `CIENG_FILE` | | `CIENG_INFLOW_HI` | Report | Generated 5 s after `TANK1.INFLOW` rises above 400; output `CIENG_FILE` |
@ -96,7 +104,8 @@ New items start with status 13 (`NOT INIT`) until a value is written.
| `03_his_group_df.qli` | Item storage groups (`HIS_GROUP_DF`): event, scan, aggregation | | `03_his_group_df.qli` | Item storage groups (`HIS_GROUP_DF`): event, scan, aggregation |
| `04_item_his_df.qli` | Items in the storage group (`ITEM_HIS_DF`, name `<group>:<item>`) | | `04_item_his_df.qli` | Items in the storage group (`ITEM_HIS_DF`, name `<group>:<item>`) |
| `05_trigger_df.qli`, `06_class_df.qli`, `07_object_df.qli` | Trigger group; classes (source in the `METHOD` memo, `@"` … `"@`, `COMPILE` 1; Traditional and Java); objects (`ATTR_VALUE_1` = prompt answer) | | `05_trigger_df.qli`, `06_class_df.qli`, `07_object_df.qli` | Trigger group; classes (source in the `METHOD` memo, `@"` … `"@`, `COMPILE` 1; Traditional and Java); objects (`ATTR_VALUE_1` = prompt answer) |
| `08_auth_group_df.qli` | Authorization group (`AUTH_GROUP_DF`) | | `08_auth_group_df.qli` | Authorization groups (`AUTH_GROUP_DF`) |
| `08b_user_df.qli` | Demo user `CIENG` (`USER_DF`); `PASSWORD ""` given explicitly - without the field the user has no password set and every logon fails (`DSS-E-UNK_USER`) |
| `09_modbus_line_df.qli`, `10_modbus_station_df.qli`, `11_item_eqp_df.qli` | Modbus line; station, scan type, points; items connected to points | | `09_modbus_line_df.qli`, `10_modbus_station_df.qli`, `11_item_eqp_df.qli` | Modbus line; station, scan type, points; items connected to points |
| `12_opc_visible_df.qli` | OPC visible / read flags (loaded with `dssqld -m`) | | `12_opc_visible_df.qli` | OPC visible / read flags (loaded with `dssqld -m`) |
| `13_opcua_line_df.qli`, `14_opcua_station_df.qli`, `15_item_opcua_df.qli` | OPC UA client line; station, subscription, points; connected items | | `13_opcua_line_df.qli`, `14_opcua_station_df.qli`, `15_item_opcua_df.qli` | OPC UA client line; station, subscription, points; connected items |
@ -110,14 +119,13 @@ New items start with status 13 (`NOT INIT`) until a value is written.
| `equipment/eqpciengslv_start.cmd`, `_stop.cmd` | Start/stop the Modbus slave mirror (copy to `tls\com`) | | `equipment/eqpciengslv_start.cmd`, `_stop.cmd` | Start/stop the Modbus slave mirror (copy to `tls\com`) |
| `76_`…`93_remove_*.qli` | Names to delete, in reverse order (audit `79`, reports and printer `83`/`84` first, alarm definitions last, `93`) | | `76_`…`93_remove_*.qli` | Names to delete, in reverse order (audit `79`, reports and printer `83`/`84` first, alarm definitions last, `93`) |
| `load.cmd`, `remove.cmd` | Run the steps in the right order | | `load.cmd`, `remove.cmd` | Run the steps in the right order |
| `displays/CIENG_Tank.xml` | Display (HTML mode): title, number field on `TANK1.LEVEL`, `PUMP1.MODE` field with buttons *Manual (0)* / *Auto (1)* (write the item), alarm overview, trend of `TANK1.LEVEL` (padded with 49 spare pens so it also draws in the browser), button *Operator layout* |
| `19b_audit_item_df.qli` | *Audit trailing wanted* for `PUMP1.MODE` (loaded with `dssqld -m`) | | `19b_audit_item_df.qli` | *Audit trailing wanted* for `PUMP1.MODE` (loaded with `dssqld -m`) |
| `displays/CIENG_Menu.xml` | Navigation display (200 x 700): *Tank 1*, *Current Alarm* (main frame), *Tank 1 popup* (layout `popup`) | | `displays/CIENG_*.xml` | The operator HMI: 8 displays in HTML mode (desktop and web), see *Displays and layout* |
| `layouts/CIENG_Operator.xml`, `layouts/layout.ps1` | Operator layout block and the script that adds/removes it in `Layouts.xml` | | `displays/generator/` | `build.py` + `cixml.py` write the `CIENG_*.xml` files (Python 3 + Pillow); `README.md` there describes the tool |
| `displays/CIENG_TrendLab.xml` | Trend lab (1000 x 860, HTML mode): trend of `TANK1.LEVEL` (no history group, value axis) and `TANK1.INFLOW` (`CIENG_EVENT`), live, last hour, padded with 48 spare pens so it draws in the browser; Micro Trend of both items (ISS-055) | | `layouts/CIENG_Operator.xml`, `layouts/layout.ps1` | Layout block (`CIENG_Operator`, `CIENG_Popup`) and the script that adds/removes it in `Layouts.xml` |
| `displays/add_trend_spares.ps1` | Pads every trend in a display file to 50 visible pens (web workaround, ISS-041); safe to run again | | `displays/add_trend_spares.ps1` | Pads every trend in a display file to 50 visible pens (web workaround, ISS-041); safe to run again. Kept as a tool; the sample trend is not padded |
| `displays/trend_feed.ps1` | Writes sine-wave test values to `TANK1.LEVEL` / `TANK1.INFLOW` every 5 s (`-Seconds`, default 3600) |
| `displays/deploy_displays.cmd`, `remove_displays.cmd` | Copy the displays into the operator interface and export their HTML versions / delete them | | `displays/deploy_displays.cmd`, `remove_displays.cmd` | Copy the displays into the operator interface and export their HTML versions / delete them |
| `feed/cieng_feed.ps1`, `cieng_feed_start.cmd`, `install_feed.ps1` | Live-data feed (test values for the tank, pump and system items), its start wrapper for the display button, and the installer into `C:\Users\Public\CI-Eng-Sample\feed` |
| `monitoring/*.sup.txt` | Setup-file lines for the monitoring processes (not applied by `load.cmd`) | | `monitoring/*.sup.txt` | Setup-file lines for the monitoring processes (not applied by `load.cmd`) |
## Modbus slave mirror (for station CIENG_PLC) ## Modbus slave mirror (for station CIENG_PLC)
@ -162,35 +170,72 @@ priority 1). To try it on a test system: `itmval -p -n CI-Eng-Sample.TANK1.LEVEL
## Displays and layout (optional) ## Displays and layout (optional)
A dark dashboard-style operator HMI with its own layout (no AOG displays). All displays are in
HTML mode, so the same files run in the Operator Interface (desktop) and in the browser (web).
No admin rights needed. After `load.cmd`: No admin rights needed. After `load.cmd`:
1. `displays\deploy_displays.cmd` copies `CIENG_Tank`, `CIENG_Menu` and `CIENG_TrendLab` into 1. `displays\deploy_displays.cmd` copies the 8 displays into the operator interface and creates
the operator interface and creates their HTML versions. their HTML versions.
2. `powershell -ExecutionPolicy Bypass -File layouts\layout.ps1` adds the layout 2. `powershell -ExecutionPolicy Bypass -File layouts\layout.ps1` adds the layouts
`CIENG_Operator` to `Layouts.xml` (first run saves `Layouts-before-CIENG.xml`). `CIENG_Operator` and `CIENG_Popup` to `Layouts.xml` (first run saves
**Restart the Operator Interface** afterwards: it reads the layouts only at start. `Layouts-before-CIENG.xml`). **Restart the Operator Interface** afterwards: it reads the
3. Operator Interface (desktop): open `CIENG_Tank` from the display box and click layouts only at start.
**Operator layout** - a second window opens with the sample menu (File / View / Displays), 3. `powershell -ExecutionPolicy Bypass -File feed\install_feed.ps1` installs the live-data feed
toolbar, `CIENG_Menu` on the left, `CIENG_Tank` in the main frame `default` and the alarm (see *Live data*).
banner. HTML display (web): `http://localhost:8080/mobileoperator/?d=CIENG_Tank&l=CIENG_Operator` 4. Log in as **`CIENG`** (no password): Operator Interface, or the web at
(CI Server login). `http://localhost:8080/mobileoperator/`. Other users: `?l=CIENG_Operator` (web) or
`jwuipoi.cmd -layout CIENG_Operator` (desktop).
Trends: `TANK1.LEVEL` and `TANK1.INFLOW` are internal items and stay `NOT INIT` after a CI | Display | Where | Shows |
Server start, so trends stay empty. `powershell -ExecutionPolicy Bypass -File |---|---|---|
displays\trend_feed.ps1 -Seconds 3600` writes test values every 5 s. `CIENG_TrendLab` (also | `CIENG_Header` | top frame | KPIs (level coloured by its limits, inflow, volume, pump, PLC / OPC UA communication), live data *Start* / *Stop* with lamp, *Tank 1* faceplate button, last update |
in the browser: `?d=CIENG_TrendLab`) shows the trend padded to 50 pens, which the HTML display | `CIENG_Overview` | tab *Overview* | Tank 1 mimic (inflow pipe, level fill coloured by limits, limit marks, pump, outlet pipes), volume / flow / maximum / counter / run time, three ring gauges, micro trend; click the tank for the faceplate |
needs to draw (ISS-041); `CIENG_Tank`'s trend is padded the same way (1 real pen + 49 spares). | `CIENG_Control` | tab *Process control* | Slider, spinner and input field on `PLC1.SETPOINT` with Modbus readback; toggle and *Set ON / OFF* on `PLC1.CMD` with `FEEDBACK` lamp; pump mode combo box and *Manual* / *Auto* buttons (audited), run check box; level test slider and buttons LL / L / Normal / H / HH |
| `CIENG_Trends` | tab *Trends* | Trend of level and inflow (10 min, 2 pens) and micro trends for level, inflow and CPU |
| `CIENG_Alarms` | tab *Alarms* | Current alarms and alarm history of `CIENG_TANK1` |
| `CIENG_System` | tab *System* | CPU and disk gauges, communication and process lamps with status, OPC UA loopback, report component |
| `CIENG_AlarmBanner` | bottom frame | Tank 1 alarm lamp, *Alarm list* button, 4-row alarm banner |
| `CIENG_TankFaceplate` | layout `CIENG_Popup` | Level, status, limits, maximum, last update, micro trend, *Trends* / *Alarms* / *Close* |
Remove: `layouts\layout.ps1 -Remove` (restores the file exactly) and Screen sizes: designed for 1920 x 1080. The desktop opens the tabs with `stretchDisplay`, so they
`displays\remove_displays.cmd`. Close the displays in the Edit Module first. See skill fill any monitor (slightly stretched where the ratio differs); maximise the window, it opens over
the taskbar. The web client does not zoom displays: use full screen (F11) and the browser zoom
(estimates, not tested: about 100 % at 1920 x 1080, 80 % at 1536 x 864, 70 % at 1366 x 768).
Known limits (R1.03.00): the trend draws no line in the browser (a web trend needs 50 pens,
ISS-041; the 2-pen trend keeps the desktop hairline box readable); the empty part of the alarm
lists stays white; a tab opened by clicking the tab strip itself keeps its zoom until it is opened
once from the toolbar, menu or F1–F6.
Remove: `layouts\layout.ps1 -Remove` (restores the file exactly), `displays\remove_displays.cmd`
and `feed\install_feed.ps1 -Remove`. Close the displays in the Edit Module first. See skill
`graphics`. `graphics`.
## Live data
The sample items are internal: after a CI Server start they stay `NOT INIT`, so displays, trends
and alarms show nothing until values are written. `feed\cieng_feed.ps1` writes them every 5 s:
| Option | Effect |
|---|---|
| (none) | Runs `-Seconds` (default 3600): `TANK1.LEVEL` 50 ± 25 % (inside the limits), `TANK1.INFLOW` 250 ± 150 m3/h; `PUMP1.RUNNING` follows the inflow in auto mode |
| `-Alarms` | `TANK1.LEVEL` 50 ± 33 %: crosses L 20 and H 80, so alarms appear (manual acknowledgement) |
| `-System` | Also writes `SYSTEM.CPU_LOAD` / `DISK_C` / `PING_LOCALHOST` / `PROC_ALM` with this PC's values; skipped while the monitoring processes run (they write the same items) |
| `-UntilFlag` | Runs while `DEMO.FEED_ON` = 1 (display buttons *Start* / *Stop*) |
The header button *Start* runs `C:\Users\Public\CI-Eng-Sample\feed\cieng_feed_start.cmd` on the
server (as the CI Server service account; needs a group with `EXECUTE_GENERAL_COMMANDS`), which
starts the feed with `-UntilFlag -Alarms -System`. Only one copy runs at a time. Log:
`%TLS_LST_PATH%\cieng_feed.log`. Stop the feed before manual tests with `itmval` (it overwrites the
values within 5 s). After a CI Server restart the *Live data* lamp can stay green although no feed
runs: click *Start*.
## Monitoring processes (optional) ## Monitoring processes (optional)
`monitoring/` holds the lines to add to the setup files in `%TLS_ROOT_PATH%\tls\sup\` so that `monitoring/` holds the lines to add to the setup files in `%TLS_ROOT_PATH%\tls\sup\` so that
`intcpumon`, `intdskmon`, `inttcpmon`, `intmon` and `intspawn` write into the `SYSTEM` items. `intcpumon`, `intdskmon`, `inttcpmon`, `intmon` and `intspawn` write into the `SYSTEM` items.
These change the system's own setup files: back the files up first and restore them after These change the system's own setup files: back the files up first and restore them after
testing. See the `system-management` skill, task `monitoring-processes.md`. testing. While they run, the live-data feed leaves the `SYSTEM` items alone (`-System` is skipped). See the `system-management` skill, task `monitoring-processes.md`.
## Reports ## Reports
@ -215,7 +260,7 @@ Engineering Module is in the audit trail (skill `audit-trail`):
- Generate `CIENG_AUDIT` (ad hoc, like the other reports) to list the last hour of changes on - Generate `CIENG_AUDIT` (ad hoc, like the other reports) to list the last hour of changes on
`CI-Eng-Sample.*`: time, dataset, field, action, source, user, old and new value. `CI-Eng-Sample.*`: time, dataset, field, action, source, user, old and new value.
- Operator writes: with the displays deployed, click *Manual (0)* / *Auto (1)* on `CIENG_Tank`; - Operator writes: with the displays deployed, click *Manual* / *Auto* on `CIENG_Control`;
each click is stored as `ITEM.VALUE.MODIFY.OPER-INTERFACE` because `PUMP1.MODE` has *Audit each click is stored as `ITEM.VALUE.MODIFY.OPER-INTERFACE` because `PUMP1.MODE` has *Audit
trailing wanted* (`19b_audit_item_df.qli`). trailing wanted* (`19b_audit_item_df.qli`).
- Export: `dssqld -e audit.qlo -d AUDIT_TRAIL` (whole trail) or a qli with `@SELECT` (keep `NAME` - Export: `dssqld -e audit.qlo -d AUDIT_TRAIL` (whole trail) or a qli with `@SELECT` (keep `NAME`
@ -231,7 +276,7 @@ selection group.
| Phase | Adds | | Phase | Adds |
|---|---| |---|---|
| 10 | A symbol and a faceplate popup (displays and the operator layout exist) | | 10 | A symbol (the faceplate popup `CIENG_TankFaceplate` exists since 2026-10-06) |
## Rules ## Rules