The old 05-scada/, restructured around the distinction its README never
drew: configuration is deployed with dssqld, displays are deployed by
file copy. Conflating the two is what made the folder confusing.
modbus_points/ the tag database - named for the protocol,
since CI Server configures others differently
modbus_points/historian/ 3 groups, 49 bindings - HAND-MADE, no
generator, and drifted from the server
hmi/ displays and their generator
ciserver-backup-2026-08/ outdated exports, evidence only, never import
QUICKLOAD.md dssqld export/import, the 5 classes, the import
order, and why an item import kills every display
README.md the chain end to end, and the not-updating triage
Verified during the move - the whole chain is reproducible:
scada-points.csv and all three .qli regenerate byte-identically
all six displays build clean
Removed the K offset machinery from build_display.py, item-ids.meta.json
and DEPLOY.md. K was a consistency check on measured ids, not a source of
them, and diagnosing a dead screen by arithmetic is wasted effort when
validating the display in CI Server's Editor Module fixes it outright.
The guidance now leads with that one action.
Recorded, not fixed: the repo's historian config disagrees with the
2026-08 CI Server export - WRPS_THIRTY_SEC and a FIVE_SECONDS group exist
on the server and not here. cicore1 was unreachable during this audit, so
which is correct is unknown.
Not carried across: __pycache__, out/*.xml, and the top-level
WRPS_Overview.xml that was tracked despite .gitignore declaring the
display XMLs to be build output.
119 lines
4.7 KiB
Markdown
119 lines
4.7 KiB
Markdown
# Quickload — moving configuration in and out of CI Server
|
|
|
|
`dssqld` is CI Server's quickload utility. It exports and imports **configuration
|
|
datasets** as `.qli` files: sections, items, Modbus points, historian groups.
|
|
|
|
> [!IMPORTANT]
|
|
> **Quickload is for configuration only. It is not how displays are deployed.**
|
|
> HMI displays are plain file copy/replace into the deployment's `displays`
|
|
> directory — see `hmi/DEPLOY.md`. Do not look for a `dssqld` command for them;
|
|
> there isn't one.
|
|
|
|
## The two commands
|
|
|
|
**Export** — writes every record of one class to a file:
|
|
|
|
```bash
|
|
dssqld -d MODBUS_POINT_DF -e modbus-points.qli
|
|
```
|
|
|
|
`-d` names the class, `-e` the output file.
|
|
|
|
**Import** — loads a file back in:
|
|
|
|
```bash
|
|
dssqld -i modbus-points.qli
|
|
```
|
|
|
|
The class is read from the file's own `@` header, so import takes no `-d`.
|
|
|
|
> Other classes may need different flags. These two forms are the ones proven on
|
|
> this project. **If a command fails, ask** — do not guess at flags against a live
|
|
> configuration.
|
|
|
|
## The classes this project uses
|
|
|
|
| Class | File | Holds | Generated? |
|
|
|---|---|---|---|
|
|
| `SECTION_DF` | `modbus_points/wrps_section_df.qli` | the 6 `AID.WRPS.*` sections | ✅ `gen_ciserver_qli.py` |
|
|
| `MODBUS_POINT_DF` | `modbus_points/wrps_modbus_point_df.qli` | 49 Modbus point definitions | ✅ |
|
|
| `ITEM_DF` | `modbus_points/wrps_item_df.qli` | 49 items, bound to those points | ✅ |
|
|
| `HIS_GROUP_DF` | `modbus_points/historian/his_group.qli` | 3 collection groups | ❌ hand-made |
|
|
| `ITEM_HIS_DF` | `modbus_points/historian/item_his.qli` | 49 item→group bindings | ❌ hand-made |
|
|
|
|
## Import order — it matters
|
|
|
|
```bash
|
|
dssqld -i wrps_section_df.qli # 1. sections
|
|
dssqld -i wrps_modbus_point_df.qli # 2. points
|
|
dssqld -i wrps_item_df.qli # 3. items
|
|
dssqld -i historian/his_group.qli # 4. collection groups
|
|
dssqld -i historian/item_his.qli # 5. item -> group bindings
|
|
```
|
|
|
|
Each step depends on the one before it:
|
|
|
|
- **Sections first.** CI Server derives its hierarchy from the dots in a name, and
|
|
a section must exist before an item can be created inside it.
|
|
- **Points before items**, because an item binds to a point.
|
|
- **Groups before bindings**, because `ITEM_HIS_DF` names both an item and a group
|
|
and needs both to exist.
|
|
|
|
## ⚠️ After importing items, every display goes dead
|
|
|
|
**An item import renumbers every item.** Proven on 2026-08-14: items were
|
|
re-imported to change engineering units, keeping every `NAME`, `NSID` and
|
|
`ID_NUMBER` byte-identical — and every itemId still moved. CI Server recreates
|
|
items on import rather than updating them in place.
|
|
|
|
Displays bind by **itemId** at runtime, so every value on every screen dies at
|
|
once.
|
|
|
|
**The fix is one action, and it is not a rebuild:**
|
|
|
|
> **Open each display in CI Server's Editor Module and validate it.**
|
|
|
|
Validation resolves every connection by name and rewrites the ids. Then re-harvest
|
|
so the next build ships the current ids:
|
|
|
|
```bash
|
|
python hmi/build_display.py --harvest <the saved display>.xml
|
|
```
|
|
|
|
`WRPS_TagTest` binds every project item, so harvesting that one display measures
|
|
all 49 in a single pass.
|
|
|
|
**Moving displays to a different CI Server** needs no rebuild and no re-harvest:
|
|
importing a display into the target resolves its connections by name on the way
|
|
in. **Import, then validate.** The files built for one server are the files you
|
|
ship to the next — provided the item names are identical, which means `ROOT`,
|
|
`INSTALL` and `STATION` in `gen_ciserver_qli.py` must match on both.
|
|
|
|
## Exporting, to check what the server actually holds
|
|
|
|
The repo cannot see `cicore1`, so the only way to confirm the server agrees with
|
|
this folder is to export and diff:
|
|
|
|
```bash
|
|
dssqld -d SECTION_DF -e check_section_df.qli
|
|
dssqld -d MODBUS_POINT_DF -e check_modbus_point_df.qli
|
|
dssqld -d ITEM_DF -e check_item_df.qli
|
|
dssqld -d HIS_GROUP_DF -e check_his_group.qli
|
|
dssqld -d ITEM_HIS_DF -e check_item_his_df.qli
|
|
```
|
|
|
|
An export contains **every** record of that class, not just this project's — the
|
|
2026-08 export in `ciserver-backup-2026-08/` holds 147 WRPS item records among
|
|
others. Filter on `AID.WRPS` when comparing.
|
|
|
|
**This has already caught a real drift.** The 2026-08 export shows historian
|
|
groups (`WRPS_THIRTY_SEC`, `FIVE_SECONDS`) that
|
|
`modbus_points/historian/his_group.qli` does not define. One of the two is stale
|
|
and nobody currently knows which.
|
|
|
|
## Format reference
|
|
|
|
CI Server publishes no documentation for the `.qli` format. Ten real exports are
|
|
kept in `99-reference/ciserver-qli-exports/` — every field layout and constant in
|
|
`gen_ciserver_qli.py` was copied from them. If you need a class this project does
|
|
not use, export one record of it and read the header.
|