# 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.
