fix(scada): PS_* placeholder tags out, CI Server item names in
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.
This commit is contained in:
parent
947f632d7f
commit
0927323e13
11 changed files with 169 additions and 102 deletions
|
|
@ -30,7 +30,7 @@ Everything derives from the PLC. The PLC side leads, always.
|
||||||
03-plc/register-map.csv the contract - 69 points
|
03-plc/register-map.csv the contract - 69 points
|
||||||
│ gen_scada_points.py
|
│ gen_scada_points.py
|
||||||
▼
|
▼
|
||||||
modbus_points/scada-points.csv the SCADA view - 49 points, poll groups, units
|
modbus_points/ci-server-points.csv the SCADA view - 49 points, poll groups, units
|
||||||
│ gen_ciserver_qli.py
|
│ gen_ciserver_qli.py
|
||||||
▼
|
▼
|
||||||
modbus_points/*.qli 6 sections · 49 Modbus points · 49 items
|
modbus_points/*.qli 6 sections · 49 Modbus points · 49 items
|
||||||
|
|
@ -100,9 +100,9 @@ look.
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Points and items | **Imported and reading live PLC values** (2026-08-14), verified against a direct Modbus read |
|
| Points and items | **Imported and reading live PLC values** (2026-08-14), verified against a direct Modbus read |
|
||||||
| Generators | Verified reproducible 2026-09-02 — `scada-points.csv` and all three `.qli` regenerate byte-identically |
|
| Generators | Verified reproducible 2026-09-02 — `ci-server-points.csv` and all three `.qli` regenerate byte-identically |
|
||||||
| Displays | Six built; `build_display.py` runs clean |
|
| Displays | Six built; `build_display.py` runs clean |
|
||||||
| Historian | 3 groups, 49 bindings — **hand-made, and drifted from the server** |
|
| Historian | 3 groups, 49 bindings — **hand-made, and the live rates differ from these files.** The server runs `WRPS_ONE_SEC` at 5 s and `WRPS_THIRTY_SEC` at 30 s. See `modbus_points/historian/README.md`. |
|
||||||
| CI Server state | ⚠️ **Unverified.** No access to `cicore1` during this audit. Everything here is what the repo believes, not what the server holds. |
|
| CI Server state | ⚠️ **Unverified.** No access to `cicore1` during this audit. Everything here is what the repo believes, not what the server holds. |
|
||||||
|
|
||||||
### Two things left for you
|
### Two things left for you
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,11 @@ as opposed to what the repo believes was configured.
|
||||||
An export holds **every** record of its class, not only this project's. Filter on
|
An export holds **every** record of its class, not only this project's. Filter on
|
||||||
`AID.WRPS` when comparing.
|
`AID.WRPS` when comparing.
|
||||||
|
|
||||||
## The drift they revealed
|
## The drift they revealed — and settled
|
||||||
|
|
||||||
Comparing these against `../modbus_points/historian/` shows the two do not agree:
|
Comparing these against `../modbus_points/historian/` shows the two do not agree.
|
||||||
|
**These exports are the authority**: they record what the running server actually
|
||||||
|
did, whereas `his_group.qli` records what the source project intended.
|
||||||
|
|
||||||
| In this export | In the repo's source |
|
| In this export | In the repo's source |
|
||||||
|---|---|
|
|---|---|
|
||||||
|
|
@ -34,6 +36,11 @@ Comparing these against `../modbus_points/historian/` shows the two do not agree
|
||||||
|
|
||||||
That is the whole reason this folder exists rather than being deleted.
|
That is the whole reason this folder exists rather than being deleted.
|
||||||
|
|
||||||
|
**The rates matter more than the names.** The live `WRPS_ONE_SEC` runs at **5
|
||||||
|
seconds**, not 1, and the second group is `WRPS_THIRTY_SEC` at **30 seconds**, not
|
||||||
|
a 60 second `WRPS_ONE_MIN`. Code that assumed 60 seconds was wrong by twelvefold.
|
||||||
|
Never hardcode a sample interval — read it from the item.
|
||||||
|
|
||||||
## Replacing it
|
## Replacing it
|
||||||
|
|
||||||
When `cicore1` is reachable, re-export the five classes (`../../QUICKLOAD.md`),
|
When `cicore1` is reachable, re-export the five classes (`../../QUICKLOAD.md`),
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ of the spill weir resolves to 0.017% because the register underneath is mm, and
|
||||||
a flow in m³/h to 0.1 — so both get one decimal, and a second would be invented
|
a flow in m³/h to 0.1 — so both get one decimal, and a second would be invented
|
||||||
precision. Integer registers get none. `point_format.check()` fails the build if
|
precision. Integer registers get none. `point_format.check()` fails the build if
|
||||||
a new item has no mask, and the masks are cross-checked against `format_mask` in
|
a new item has no mask, and the masks are cross-checked against `format_mask` in
|
||||||
`04-scada/modbus_points/scada-points.csv`, which is what CI Server imports as
|
`04-scada/modbus_points/ci-server-points.csv`, which is what CI Server imports as
|
||||||
`VALUE_FORMAT`.
|
`VALUE_FORMAT`.
|
||||||
|
|
||||||
Element order matters to match what CI View saves: `<htmlId>`, `<format>`,
|
Element order matters to match what CI View saves: `<htmlId>`, `<format>`,
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ decimal is honest and two would not be; a flow in m3/h resolves to 0.1.
|
||||||
Integer registers get no decimal at all - a decimal place there would be
|
Integer registers get no decimal at all - a decimal place there would be
|
||||||
invented precision.
|
invented precision.
|
||||||
|
|
||||||
**These masks must agree with `format_mask` in `04-scada/modbus_points/scada-points.csv`,**
|
**These masks must agree with `format_mask` in `04-scada/modbus_points/ci-server-points.csv`,**
|
||||||
which is what the item export carries into CI Server as `VALUE_FORMAT`. The
|
which is what the item export carries into CI Server as `VALUE_FORMAT`. The
|
||||||
units and their gains are defined once, in `gen_scada_points.py`.
|
units and their gains are defined once, in `gen_scada_points.py`.
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ from pathlib import Path
|
||||||
|
|
||||||
HERE = Path(__file__).resolve().parent
|
HERE = Path(__file__).resolve().parent
|
||||||
OUT = HERE / "out"
|
OUT = HERE / "out"
|
||||||
POINTS = HERE.parent / "modbus_points" / "scada-points.csv"
|
POINTS = HERE.parent / "modbus_points" / "ci-server-points.csv"
|
||||||
QLI_GEN = HERE.parent / "modbus_points" / "gen_ciserver_qli.py"
|
QLI_GEN = HERE.parent / "modbus_points" / "gen_ciserver_qli.py"
|
||||||
PLC_HOST, PLC_PORT, PLC_UNIT = "192.168.153.192", 502, 1
|
PLC_HOST, PLC_PORT, PLC_UNIT = "192.168.153.192", 502, 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,20 +7,55 @@ Three kinds of file live here, and only the first two are generated:
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Generated** | `scada-points.csv` and the three `wrps_*.qli` |
|
| **Generated** | `ci-server-points.csv` and the three `wrps_*.qli` |
|
||||||
| **Generators** | `gen_scada_points.py`, `gen_ciserver_qli.py` |
|
| **Generators** | `gen_scada_points.py`, `gen_ciserver_qli.py` |
|
||||||
| **Hand-made** | `historian/` — no generator, and it has drifted. See its README. |
|
| **Hand-made** | `historian/` — no generator, and it has drifted. See its README. |
|
||||||
|
|
||||||
Deployed with `dssqld`, not by file copy — see `../QUICKLOAD.md`.
|
Deployed with `dssqld`, not by file copy — see `../QUICKLOAD.md`.
|
||||||
|
|
||||||
|
## Four namespaces, and which one is which
|
||||||
|
|
||||||
|
Getting these confused is the single most common mistake in this folder.
|
||||||
|
|
||||||
|
```
|
||||||
|
LIT-101 instrument tag the field device
|
||||||
|
%QW0 PLC symbol/address the register the PLC writes
|
||||||
|
WRPS_PLC:STN_LEVEL CI Server point Modbus station : point name
|
||||||
|
AID.WRPS.STN.LEVEL CI Server item what displays bind to, and what
|
||||||
|
the historian is keyed on
|
||||||
|
```
|
||||||
|
|
||||||
|
`ci-server-points.csv` carries all four, one row per point: `ci_item`,
|
||||||
|
`ci_station`, `ci_point`, `iec_address` and `plc_tag`.
|
||||||
|
|
||||||
|
**The historian is keyed on the item, and only the item.** Modbus carries register
|
||||||
|
numbers, not names, so the point layer and the item layer are free to differ — and
|
||||||
|
they do.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> **`PS_*` is not one of these namespaces.**
|
||||||
|
> An earlier version of this file carried a `scada_tag` column with names like
|
||||||
|
> `PS_STN_WET_WELL_LEVEL`, derived from the PLC register map. **CI Server never
|
||||||
|
> adopted them.** They named nothing that exists, and they caused a real defect
|
||||||
|
> downstream when read as if they did.
|
||||||
|
>
|
||||||
|
> The **only** legitimate `PS_` names are the four Modbus **poll groups** in the
|
||||||
|
> `poll_group` column — `PS_STATUS_BITS`, `PS_PUBLISHED`, `PS_SETPOINTS`,
|
||||||
|
> `PS_SIM_CONTROL`. Those are live configuration.
|
||||||
|
>
|
||||||
|
> `ci-server-points.csv` is the as-built delivery from the CI Server side.
|
||||||
|
> `gen_scada_points.py` reproduces it byte-identically, taking the item names from
|
||||||
|
> the `LEAF` table in `gen_ciserver_qli.py` so the CSV and the `.qli` cannot
|
||||||
|
> disagree.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python gen_scada_points.py # register-map.csv -> scada-points.csv
|
python gen_scada_points.py # register-map.csv -> ci-server-points.csv
|
||||||
python gen_ciserver_qli.py # scada-points.csv -> the two .qli files
|
python gen_ciserver_qli.py # ci-server-points.csv -> the two .qli files
|
||||||
```
|
```
|
||||||
|
|
||||||
| File | What |
|
| File | What |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `scada-points.csv` | The point list, for reading and for configuring by hand |
|
| `ci-server-points.csv` | The point list, keyed on the **CI Server item** each point feeds |
|
||||||
| `historian/` | Collection groups and 49 item bindings — **hand-made**, see its README |
|
| `historian/` | Collection groups and 49 item bindings — **hand-made**, see its README |
|
||||||
| `wrps_section_df.qli` | `@SECTION_DF` — the six `AID.WRPS.*` sections |
|
| `wrps_section_df.qli` | `@SECTION_DF` — the six `AID.WRPS.*` sections |
|
||||||
| `wrps_modbus_point_df.qli` | `@MODBUS_POINT_DF` — 49 Modbus point definitions, station `WRPS_PLC` |
|
| `wrps_modbus_point_df.qli` | `@MODBUS_POINT_DF` — 49 Modbus point definitions, station `WRPS_PLC` |
|
||||||
|
|
@ -29,7 +64,7 @@ python gen_ciserver_qli.py # scada-points.csv -> the two .qli files
|
||||||
**Import in that order.** CI Server derives its hierarchy from the dots in a name,
|
**Import in that order.** CI Server derives its hierarchy from the dots in a name,
|
||||||
and a section must exist before an item can be created inside it.
|
and a section must exist before an item can be created inside it.
|
||||||
|
|
||||||
The chain is ST sources → `03-plc/register-map.csv` → `scada-points.csv` → `.qli`,
|
The chain is ST sources → `03-plc/register-map.csv` → `ci-server-points.csv` → `.qli`,
|
||||||
so a register change propagates by re-running the scripts. **Nothing here is
|
so a register change propagates by re-running the scripts. **Nothing here is
|
||||||
hand-edited**; if CI Server needs a field the generators do not emit, it goes in
|
hand-edited**; if CI Server needs a field the generators do not emit, it goes in
|
||||||
the generator.
|
the generator.
|
||||||
|
|
@ -90,7 +125,7 @@ presentation choice, made here, as a pure gain on the raw register:
|
||||||
| `SP.MIN_SPEED` | % | 0.2 | same scale as `STN.SPEED`; **entered in %** |
|
| `SP.MIN_SPEED` | % | 0.2 | same scale as `STN.SPEED`; **entered in %** |
|
||||||
|
|
||||||
The gains live in one place — `UNITS` in `gen_scada_points.py`. Change a unit
|
The gains live in one place — `UNITS` in `gen_scada_points.py`. Change a unit
|
||||||
there and it propagates to `scada-points.csv`, to both `.qli` files and to the
|
there and it propagates to `ci-server-points.csv`, to both `.qli` files and to the
|
||||||
HMI masks.
|
HMI masks.
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
|
|
@ -128,7 +163,7 @@ unsigned; see below.
|
||||||
## The point list
|
## The point list
|
||||||
|
|
||||||
`gen_scada_points.py` reads `03-plc/register-map.csv` (the PLC-side list, itself
|
`gen_scada_points.py` reads `03-plc/register-map.csv` (the PLC-side list, itself
|
||||||
generated from the ST sources) and rewrites `scada-points.csv`. Re-run it after any
|
generated from the ST sources) and rewrites `ci-server-points.csv`. Re-run it after any
|
||||||
register change so the two sides cannot drift — that is the §3 invariant. Anything
|
register change so the two sides cannot drift — that is the §3 invariant. Anything
|
||||||
changed by hand here is lost on the next run; if CI Server needs a field the script
|
changed by hand here is lost on the next run; if CI Server needs a field the script
|
||||||
does not emit, it goes in the generator.
|
does not emit, it goes in the generator.
|
||||||
|
|
|
||||||
50
04-scada/modbus_points/ci-server-points.csv
Normal file
50
04-scada/modbus_points/ci-server-points.csv
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
ci_item,ci_station,ci_point,description,poll_group,function_code,modbus_address,data_type,access,eng_units,raw_to_eng,eng_gain,format_mask,iec_address,plc_tag,notes
|
||||||
|
AID.WRPS.PU301.RUN_CMD,WRPS_PLC,PU301_RUN_CMD,Run command,PS_STATUS_BITS,FC01,0,Boolean,Read,,value,1.0,99999,%QX0.0,PU-301,
|
||||||
|
AID.WRPS.PU302.RUN_CMD,WRPS_PLC,PU302_RUN_CMD,Run command,PS_STATUS_BITS,FC01,1,Boolean,Read,,value,1.0,99999,%QX0.1,PU-302,
|
||||||
|
AID.WRPS.PU303.RUN_CMD,WRPS_PLC,PU303_RUN_CMD,Run command,PS_STATUS_BITS,FC01,2,Boolean,Read,,value,1.0,99999,%QX0.2,PU-303,
|
||||||
|
AID.WRPS.PU301.RUNNING,WRPS_PLC,PU301_RUNNING,Running,PS_STATUS_BITS,FC01,3,Boolean,Read,,value,1.0,99999,%QX0.3,PU-301,
|
||||||
|
AID.WRPS.PU302.RUNNING,WRPS_PLC,PU302_RUNNING,Running,PS_STATUS_BITS,FC01,4,Boolean,Read,,value,1.0,99999,%QX0.4,PU-302,
|
||||||
|
AID.WRPS.PU303.RUNNING,WRPS_PLC,PU303_RUNNING,Running,PS_STATUS_BITS,FC01,5,Boolean,Read,,value,1.0,99999,%QX0.5,PU-303,
|
||||||
|
AID.WRPS.PU301.AVAILABLE,WRPS_PLC,PU301_AVAILABLE,Available,PS_STATUS_BITS,FC01,6,Boolean,Read,,value,1.0,99999,%QX0.6,PU-301,
|
||||||
|
AID.WRPS.PU302.AVAILABLE,WRPS_PLC,PU302_AVAILABLE,Available,PS_STATUS_BITS,FC01,7,Boolean,Read,,value,1.0,99999,%QX0.7,PU-302,
|
||||||
|
AID.WRPS.PU303.AVAILABLE,WRPS_PLC,PU303_AVAILABLE,Available,PS_STATUS_BITS,FC01,8,Boolean,Read,,value,1.0,99999,%QX1.0,PU-303,
|
||||||
|
AID.WRPS.STN.IN_AUTO,WRPS_PLC,STN_IN_AUTO,Station in auto,PS_STATUS_BITS,FC01,9,Boolean,Read,,value,1.0,99999,%QX1.1,STN,
|
||||||
|
AID.WRPS.STN.HIGH_LEVEL,WRPS_PLC,STN_HIGH_LEVEL,High level alarm,PS_STATUS_BITS,FC01,10,Boolean,Read,,value,1.0,99999,%QX1.2,STN,
|
||||||
|
AID.WRPS.STN.SPILL_ACTIVE,WRPS_PLC,STN_SPILL_ACTIVE,Spill active,PS_STATUS_BITS,FC01,11,Boolean,Read,,value,1.0,99999,%QX1.3,STN,
|
||||||
|
AID.WRPS.PU301.TRIPPED,WRPS_PLC,PU301_TRIPPED,Tripped,PS_STATUS_BITS,FC01,12,Boolean,Read,,value,1.0,99999,%QX1.4,PU-301,
|
||||||
|
AID.WRPS.PU302.TRIPPED,WRPS_PLC,PU302_TRIPPED,Tripped,PS_STATUS_BITS,FC01,13,Boolean,Read,,value,1.0,99999,%QX1.5,PU-302,
|
||||||
|
AID.WRPS.PU303.TRIPPED,WRPS_PLC,PU303_TRIPPED,Tripped,PS_STATUS_BITS,FC01,14,Boolean,Read,,value,1.0,99999,%QX1.6,PU-303,
|
||||||
|
AID.WRPS.STN.LEVEL,WRPS_PLC,STN_LEVEL,Wet well level,PS_PUBLISHED,FC03,0,Signed 16-bit,Read,%,value / 60,0.016666666666666666,999.9,%QW0,STN,
|
||||||
|
AID.WRPS.STN.INFLOW,WRPS_PLC,STN_INFLOW,Inflow,PS_PUBLISHED,FC03,1,Signed 16-bit,Read,m3/h,value * 0.36,0.36,9999.9,%QW1,STN,
|
||||||
|
AID.WRPS.STN.DISCHARGE,WRPS_PLC,STN_DISCHARGE,Total discharge flow,PS_PUBLISHED,FC03,2,Signed 16-bit,Read,m3/h,value * 0.36,0.36,9999.9,%QW2,STN,
|
||||||
|
AID.WRPS.STN.PUMPS_RUNNING,WRPS_PLC,STN_PUMPS_RUNNING,Pumps running,PS_PUBLISHED,FC03,3,Signed 16-bit,Read,count,value,1.0,9,%QW3,STN,
|
||||||
|
AID.WRPS.STN.SPEED,WRPS_PLC,STN_SPEED,Common drive speed,PS_PUBLISHED,FC03,4,Signed 16-bit,Read,%,value * 0.2,0.2,999.9,%QW4,STN,
|
||||||
|
AID.WRPS.STN.TIME_TO_SPILL,WRPS_PLC,STN_TIME_TO_SPILL,Time to spill weir (32767 = drawing down),PS_PUBLISHED,FC03,5,Signed 16-bit,Read,s,value,1.0,99999,%QW5,STN,
|
||||||
|
AID.WRPS.STN.TIME_TO_LSHH,WRPS_PLC,STN_TIME_TO_LSHH,Time to LSHH (32767 = drawing down),PS_PUBLISHED,FC03,6,Signed 16-bit,Read,s,value,1.0,99999,%QW6,STN,
|
||||||
|
AID.WRPS.STN.NET_ACCUM,WRPS_PLC,STN_NET_ACCUM,Net accumulation (signed),PS_PUBLISHED,FC03,7,Signed 16-bit,Read,m3/h,value * 0.36,0.36,9999.9,%QW7,STN,
|
||||||
|
AID.WRPS.PU301.RUN_HOURS,WRPS_PLC,PU301_RUN_HOURS,Run hours,PS_PUBLISHED,FC03,8,Signed 16-bit,Read,h,value,1.0,99999,%QW8,PU-301,
|
||||||
|
AID.WRPS.PU302.RUN_HOURS,WRPS_PLC,PU302_RUN_HOURS,Run hours,PS_PUBLISHED,FC03,9,Signed 16-bit,Read,h,value,1.0,99999,%QW9,PU-302,
|
||||||
|
AID.WRPS.PU303.RUN_HOURS,WRPS_PLC,PU303_RUN_HOURS,Run hours,PS_PUBLISHED,FC03,10,Signed 16-bit,Read,h,value,1.0,99999,%QW10,PU-303,
|
||||||
|
AID.WRPS.STN.VOL_TO_SPILL,WRPS_PLC,STN_VOL_TO_SPILL,Volume remaining to spill,PS_PUBLISHED,FC03,11,Signed 16-bit,Read,m3,value,1.0,9999,%QW11,STN,
|
||||||
|
AID.WRPS.STN.STATE,WRPS_PLC,STN_STATE,Station state (enum 3.1),PS_PUBLISHED,FC03,12,Signed 16-bit,Read,,value,1.0,9,%QW12,STN,
|
||||||
|
AID.WRPS.PU301.STATE,WRPS_PLC,PU301_STATE,Pump state (enum 3.2),PS_PUBLISHED,FC03,13,Signed 16-bit,Read,,value,1.0,9,%QW13,PU-301,
|
||||||
|
AID.WRPS.PU302.STATE,WRPS_PLC,PU302_STATE,Pump state (enum 3.2),PS_PUBLISHED,FC03,14,Signed 16-bit,Read,,value,1.0,9,%QW14,PU-302,
|
||||||
|
AID.WRPS.PU303.STATE,WRPS_PLC,PU303_STATE,Pump state (enum 3.2),PS_PUBLISHED,FC03,15,Signed 16-bit,Read,,value,1.0,9,%QW15,PU-303,
|
||||||
|
AID.WRPS.STN.DUTY_PUMP,WRPS_PLC,STN_DUTY_PUMP,"Current duty pump (0 = none, 1-3)",PS_PUBLISHED,FC03,16,Signed 16-bit,Read,,value,1.0,9,%QW16,STN,
|
||||||
|
AID.WRPS.STN.ALARM_WORD,WRPS_PLC,STN_ALARM_WORD,Alarm bitmask (section 6) - READ AS UNSIGNED,PS_PUBLISHED,FC03,17,Unsigned 16-bit,Read,,value,1.0,99999,%QW17,STN,
|
||||||
|
AID.WRPS.STN.CMD_ACK,WRPS_PLC,STN_CMD_ACK,Command acknowledge (echoes %MW1),PS_PUBLISHED,FC03,20,Signed 16-bit,Read,,value,1.0,99,%QW20,STN,
|
||||||
|
AID.WRPS.SP.MODE,WRPS_PLC,SP_MODE,"Station mode: 1 = auto, 2 = off",PS_SETPOINTS,FC03/FC06,1024,Signed 16-bit,Read/Write,,value,1.0,9,%MW0,STN,
|
||||||
|
AID.WRPS.SP.CMD_WORD,WRPS_PLC,SP_CMD_WORD,Command word (section 3.3),PS_SETPOINTS,FC03/FC06,1025,Signed 16-bit,Read/Write,,value,1.0,99,%MW1,STN,
|
||||||
|
AID.WRPS.SP.CMD_PARAM,WRPS_PLC,SP_CMD_PARAM,Command parameter (pump number),PS_SETPOINTS,FC03/FC06,1026,Signed 16-bit,Read/Write,,value,1.0,9,%MW2,STN,
|
||||||
|
AID.WRPS.SP.LEVEL_SP,WRPS_PLC,SP_LEVEL_SP,Level control setpoint,PS_SETPOINTS,FC03/FC06,1027,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW3,STN,
|
||||||
|
AID.WRPS.SP.START_DUTY,WRPS_PLC,SP_START_DUTY,Start duty level,PS_SETPOINTS,FC03/FC06,1028,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW4,STN,
|
||||||
|
AID.WRPS.SP.START_P2,WRPS_PLC,SP_START_P2,Start pump 2 level,PS_SETPOINTS,FC03/FC06,1029,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW5,STN,
|
||||||
|
AID.WRPS.SP.START_P3,WRPS_PLC,SP_START_P3,Start pump 3 level,PS_SETPOINTS,FC03/FC06,1030,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW6,STN,
|
||||||
|
AID.WRPS.SP.STOP_ALL,WRPS_PLC,SP_STOP_ALL,Stop all level,PS_SETPOINTS,FC03/FC06,1031,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW7,STN,
|
||||||
|
AID.WRPS.SP.HIGH_ALARM,WRPS_PLC,SP_HIGH_ALARM,High level alarm,PS_SETPOINTS,FC03/FC06,1032,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW8,STN,
|
||||||
|
AID.WRPS.SP.MIN_SPEED,WRPS_PLC,SP_MIN_SPEED,Minimum drive speed,PS_SETPOINTS,FC03/FC06,1033,Signed 16-bit,Read/Write,%,value * 0.2,0.2,999.9,%MW9,STN,
|
||||||
|
AID.WRPS.SP.SERVICE_HRS,WRPS_PLC,SP_SERVICE_HRS,Service interval,PS_SETPOINTS,FC03/FC06,1034,Signed 16-bit,Read/Write,h,value,1.0,99999,%MW10,STN,
|
||||||
|
AID.WRPS.SIM.INFLOW,WRPS_PLC,SIM_INFLOW,manual inflow (mode 0),PS_SIM_CONTROL,FC03/FC06,1044,Signed 16-bit,Read/Write,m3/h,value * 0.36,0.36,9999.9,%MW20,SIM,SIMULATION CONTROL - simulation build only
|
||||||
|
AID.WRPS.SIM.SCENARIO,WRPS_PLC,SIM_SCENARIO,scenario 0=man 1=diurnal 2=wet 3=ref,PS_SIM_CONTROL,FC03/FC06,1045,Signed 16-bit,Read/Write,,value,1.0,9,%MW21,SIM,SIMULATION CONTROL - simulation build only
|
||||||
|
AID.WRPS.SIM.RESET,WRPS_PLC,SIM_RESET,"write 1 to reset scenario, self-clearing",PS_SIM_CONTROL,FC03/FC06,1046,Signed 16-bit,Read/Write,,value,1.0,9,%MW22,SIM,SIMULATION CONTROL - simulation build only
|
||||||
|
AID.WRPS.SIM.TIME_SCALE,WRPS_PLC,SIM_TIME_SCALE,time scale 1-120,PS_SIM_CONTROL,FC03/FC06,1047,Signed 16-bit,Read/Write,x,value,1.0,999,%MW23,SIM,SIMULATION CONTROL - simulation build only
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Emit CI Server .qli imports for the WRPS points.
|
"""Emit CI Server .qli imports for the WRPS points.
|
||||||
|
|
||||||
python gen_scada_points.py # first: refresh scada-points.csv
|
python gen_scada_points.py # first: refresh ci-server-points.csv
|
||||||
python gen_ciserver_qli.py
|
python gen_ciserver_qli.py
|
||||||
|
|
||||||
Writes, alongside this script:
|
Writes, alongside this script:
|
||||||
|
|
@ -13,7 +13,7 @@ Writes, alongside this script:
|
||||||
Import them in that order: CI Server derives its hierarchy from the dots
|
Import them in that order: CI Server derives its hierarchy from the dots
|
||||||
in a name, and a section must exist before an item can be created in it.
|
in a name, and a section must exist before an item can be created in it.
|
||||||
|
|
||||||
The chain is ST sources -> 03-plc/register-map.csv -> scada-points.csv ->
|
The chain is ST sources -> 03-plc/register-map.csv -> ci-server-points.csv ->
|
||||||
these files, so a register change propagates by re-running the three
|
these files, so a register change propagates by re-running the three
|
||||||
scripts rather than by hand-editing anything.
|
scripts rather than by hand-editing anything.
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
HERE = Path(__file__).resolve().parent
|
HERE = Path(__file__).resolve().parent
|
||||||
POINTS = HERE / "scada-points.csv"
|
POINTS = HERE / "ci-server-points.csv"
|
||||||
|
|
||||||
STATION = "WRPS_PLC"
|
STATION = "WRPS_PLC"
|
||||||
ROOT = "AID.WRPS"
|
ROOT = "AID.WRPS"
|
||||||
|
|
@ -331,7 +331,7 @@ def main():
|
||||||
args = ap.parse_args()
|
args = ap.parse_args()
|
||||||
|
|
||||||
if not POINTS.is_file():
|
if not POINTS.is_file():
|
||||||
sys.exit("missing scada-points.csv - run gen_scada_points.py first")
|
sys.exit("missing ci-server-points.csv - run gen_scada_points.py first")
|
||||||
|
|
||||||
pinned = {}
|
pinned = {}
|
||||||
for spec in args.section_nsid:
|
for spec in args.section_nsid:
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
python gen_scada_points.py
|
python gen_scada_points.py
|
||||||
|
|
||||||
Reads ../../03-plc/register-map.csv (PLC side, generated by build.py)
|
Reads ../../03-plc/register-map.csv (PLC side, generated by build.py)
|
||||||
Writes ./scada-points.csv (SCADA side, for CI Server config)
|
Writes ./ci-server-points.csv (SCADA side, for CI Server config)
|
||||||
|
|
||||||
CLAUDE.md section 3: the two sides are two views of the same points, and
|
CLAUDE.md section 3: the two sides are two views of the same points, and
|
||||||
the PLC side leads. This script makes the SCADA view reproducible
|
the PLC side leads. This script makes the SCADA view reproducible
|
||||||
|
|
@ -48,7 +48,7 @@ from pathlib import Path
|
||||||
|
|
||||||
ROOT = Path(__file__).resolve().parents[2]
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
SRC_MAP = ROOT / "03-plc" / "register-map.csv"
|
SRC_MAP = ROOT / "03-plc" / "register-map.csv"
|
||||||
OUT = Path(__file__).resolve().parent / "scada-points.csv"
|
OUT = Path(__file__).resolve().parent / "ci-server-points.csv"
|
||||||
|
|
||||||
# Modbus object -> (function code, poll group name)
|
# Modbus object -> (function code, poll group name)
|
||||||
#
|
#
|
||||||
|
|
@ -165,17 +165,31 @@ def gain_expr(gain):
|
||||||
return "value * %g" % gain
|
return "value * %g" % gain
|
||||||
|
|
||||||
|
|
||||||
def tag_for(row, description):
|
# The CI Server naming, imported from the .qli generator so the two files
|
||||||
"""Tag name per CLAUDE.md section 8: PS_<EQUIP><NN>_<MEAS>.
|
# cannot disagree. LEAF is keyed on IEC address and is the single place
|
||||||
|
# section/leaf names are defined.
|
||||||
|
#
|
||||||
|
# An earlier version of this script emitted a `scada_tag` column holding
|
||||||
|
# names like PS_STN_WET_WELL_LEVEL, derived from the PLC register map.
|
||||||
|
# **CI Server never adopted them.** They named nothing that exists, and
|
||||||
|
# they caused a real defect downstream when read as if they did. The only
|
||||||
|
# legitimate PS_ names are the four Modbus POLL GROUPS below, which are
|
||||||
|
# live configuration.
|
||||||
|
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||||
|
from gen_ciserver_qli import LEAF, ROOT, STATION
|
||||||
|
|
||||||
Built from the cleaned description, so the "SIM ONLY:" marker does
|
|
||||||
not end up inside the tag name.
|
def ci_names(iec):
|
||||||
|
"""(item, station, point) - the three CI Server namespaces.
|
||||||
|
|
||||||
|
AID.WRPS.STN.LEVEL item what the historian is keyed on
|
||||||
|
WRPS_PLC station the Modbus station
|
||||||
|
STN_LEVEL point the Modbus point on that station
|
||||||
"""
|
"""
|
||||||
equip = row["tag"].replace("-", "")
|
if iec not in LEAF:
|
||||||
meas = description.split("(")[0].split(",")[0].strip()
|
sys.exit(f"no leaf name defined for {iec} - add it to LEAF in gen_ciserver_qli.py")
|
||||||
meas = "".join(ch if ch.isalnum() else "_" for ch in meas)
|
section, leaf = LEAF[iec]
|
||||||
meas = "_".join(p for p in meas.split("_") if p)[:28].upper()
|
return (f"{ROOT}.{section}.{leaf}", STATION, ("%s_%s" % (section, leaf))[:24])
|
||||||
return f"PS_{equip}_{meas}".upper()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
@ -225,7 +239,9 @@ def main():
|
||||||
|
|
||||||
out_rows.append(
|
out_rows.append(
|
||||||
{
|
{
|
||||||
"scada_tag": tag_for(r, description),
|
"ci_item": ci_names(iec)[0],
|
||||||
|
"ci_station": ci_names(iec)[1],
|
||||||
|
"ci_point": ci_names(iec)[2],
|
||||||
"description": description,
|
"description": description,
|
||||||
"poll_group": group,
|
"poll_group": group,
|
||||||
"function_code": fc,
|
"function_code": fc,
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,30 @@ not, and that is the reason they have drifted from the server.
|
||||||
| `his_group.qli` | `@HIS_GROUP_DF` | 3 collection groups |
|
| `his_group.qli` | `@HIS_GROUP_DF` | 3 collection groups |
|
||||||
| `item_his.qli` | `@ITEM_HIS_DF` | 49 item → group bindings |
|
| `item_his.qli` | `@ITEM_HIS_DF` | 49 item → group bindings |
|
||||||
|
|
||||||
## The three groups
|
## ⚠️ These files are the INTENDED rates. The server runs different ones.
|
||||||
|
|
||||||
| Group | Items | Collection |
|
> **Resolved 2026-09-02.** The question of which was correct is now answered:
|
||||||
|
> `../../ciserver-backup-2026-08/export_his_group.qli`, taken from the running
|
||||||
|
> server, is what the historian actually did. **The live export wins.**
|
||||||
|
|
||||||
|
| | `his_group.qli` says | The running server does |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `WRPS_ONE_SEC` | 5 | 1 s scan — the fast analogues: level, inflow, discharge |
|
| Fast group | `WRPS_ONE_SEC` at **1 second** | `WRPS_ONE_SEC` at **5 seconds** |
|
||||||
| `WRPS_ONE_MIN` | 4 | 1 min scan — slower trends |
|
| Second group | `WRPS_ONE_MIN` at **60 seconds** | `WRPS_THIRTY_SEC` at **30 seconds** |
|
||||||
|
| Event group | `WRPS_EVENT`, on change | `WRPS_EVENT`, on change ✅ |
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> **Never hardcode a sample interval from these files.** Anything assuming
|
||||||
|
> `WRPS_ONE_MIN` at 60 seconds is wrong by **twelvefold** against a group that is
|
||||||
|
> actually running at 5 seconds. This has already produced a real defect in a
|
||||||
|
> downstream project. Read the interval from the item's own configuration.
|
||||||
|
|
||||||
|
## The three groups as written here (intended, not live)
|
||||||
|
|
||||||
|
| Group | Items | Intended collection |
|
||||||
|
|---|---|---|
|
||||||
|
| `WRPS_ONE_SEC` | 5 | 1 s — the fast analogues: level, inflow, discharge |
|
||||||
|
| `WRPS_ONE_MIN` | 4 | 1 min — slower trends |
|
||||||
| `WRPS_EVENT` | 40 | on change — states, commands, alarms, trips |
|
| `WRPS_EVENT` | 40 | on change — states, commands, alarms, trips |
|
||||||
|
|
||||||
Written 2026-08-21.
|
Written 2026-08-21.
|
||||||
|
|
@ -31,25 +49,16 @@ and headroom — works from live values alone. The push-back that earns trust do
|
||||||
not. **Without these two files there is no historian, and the demo loses the layer
|
not. **Without these two files there is no historian, and the demo loses the layer
|
||||||
it was designed around.**
|
it was designed around.**
|
||||||
|
|
||||||
## ⚠️ These files disagree with the server
|
## Why they disagree
|
||||||
|
|
||||||
`ciserver-backup-2026-08/export_his_group.qli`, exported from CI Server around
|
These files are the *source project's* intent. The server was tuned afterwards and
|
||||||
2026-08-20, contains groups that `his_group.qli` does not define:
|
nobody brought the change back. That is the predictable cost of the one link in
|
||||||
|
this chain with no generator: the points and items cannot drift because they are
|
||||||
|
regenerated; the historian can, and did.
|
||||||
|
|
||||||
| In the CI Server export | In `his_group.qli` |
|
Before importing these onto a working server, **export what is there first**
|
||||||
|---|---|
|
(`../../QUICKLOAD.md`) and compare. Importing blind may remove a group something
|
||||||
| `WRPS_EVENT` | ✅ |
|
depends on.
|
||||||
| `WRPS_ONE_SEC` | ✅ |
|
|
||||||
| `WRPS_THIRTY_SEC` | ❌ not defined here |
|
|
||||||
| `WRPS_ONE_MIN` | — not in the export |
|
|
||||||
| `FIVE_SECONDS` (binding `STN.LEVEL`, `STN.INFLOW`) | ❌ not a WRPS group at all |
|
|
||||||
|
|
||||||
**Nobody currently knows which is right.** The export is dated a day before these
|
|
||||||
files, but contains groups they do not. Resolve it by exporting from `cicore1` and
|
|
||||||
comparing — see `../../QUICKLOAD.md`.
|
|
||||||
|
|
||||||
Until then: **do not import these files onto a working server** without checking
|
|
||||||
what is already there. You may remove a group something depends on.
|
|
||||||
|
|
||||||
## Worth doing: generate these too
|
## Worth doing: generate these too
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
scada_tag,description,poll_group,function_code,modbus_address,data_type,access,eng_units,raw_to_eng,eng_gain,format_mask,iec_address,plc_tag,notes
|
|
||||||
PS_PU301_RUN_COMMAND,Run command,PS_STATUS_BITS,FC01,0,Boolean,Read,,value,1.0,99999,%QX0.0,PU-301,
|
|
||||||
PS_PU302_RUN_COMMAND,Run command,PS_STATUS_BITS,FC01,1,Boolean,Read,,value,1.0,99999,%QX0.1,PU-302,
|
|
||||||
PS_PU303_RUN_COMMAND,Run command,PS_STATUS_BITS,FC01,2,Boolean,Read,,value,1.0,99999,%QX0.2,PU-303,
|
|
||||||
PS_PU301_RUNNING,Running,PS_STATUS_BITS,FC01,3,Boolean,Read,,value,1.0,99999,%QX0.3,PU-301,
|
|
||||||
PS_PU302_RUNNING,Running,PS_STATUS_BITS,FC01,4,Boolean,Read,,value,1.0,99999,%QX0.4,PU-302,
|
|
||||||
PS_PU303_RUNNING,Running,PS_STATUS_BITS,FC01,5,Boolean,Read,,value,1.0,99999,%QX0.5,PU-303,
|
|
||||||
PS_PU301_AVAILABLE,Available,PS_STATUS_BITS,FC01,6,Boolean,Read,,value,1.0,99999,%QX0.6,PU-301,
|
|
||||||
PS_PU302_AVAILABLE,Available,PS_STATUS_BITS,FC01,7,Boolean,Read,,value,1.0,99999,%QX0.7,PU-302,
|
|
||||||
PS_PU303_AVAILABLE,Available,PS_STATUS_BITS,FC01,8,Boolean,Read,,value,1.0,99999,%QX1.0,PU-303,
|
|
||||||
PS_STN_STATION_IN_AUTO,Station in auto,PS_STATUS_BITS,FC01,9,Boolean,Read,,value,1.0,99999,%QX1.1,STN,
|
|
||||||
PS_STN_HIGH_LEVEL_ALARM,High level alarm,PS_STATUS_BITS,FC01,10,Boolean,Read,,value,1.0,99999,%QX1.2,STN,
|
|
||||||
PS_STN_SPILL_ACTIVE,Spill active,PS_STATUS_BITS,FC01,11,Boolean,Read,,value,1.0,99999,%QX1.3,STN,
|
|
||||||
PS_PU301_TRIPPED,Tripped,PS_STATUS_BITS,FC01,12,Boolean,Read,,value,1.0,99999,%QX1.4,PU-301,
|
|
||||||
PS_PU302_TRIPPED,Tripped,PS_STATUS_BITS,FC01,13,Boolean,Read,,value,1.0,99999,%QX1.5,PU-302,
|
|
||||||
PS_PU303_TRIPPED,Tripped,PS_STATUS_BITS,FC01,14,Boolean,Read,,value,1.0,99999,%QX1.6,PU-303,
|
|
||||||
PS_STN_WET_WELL_LEVEL,Wet well level,PS_PUBLISHED,FC03,0,Signed 16-bit,Read,%,value / 60,0.016666666666666666,999.9,%QW0,STN,
|
|
||||||
PS_STN_INFLOW,Inflow,PS_PUBLISHED,FC03,1,Signed 16-bit,Read,m3/h,value * 0.36,0.36,9999.9,%QW1,STN,
|
|
||||||
PS_STN_TOTAL_DISCHARGE_FLOW,Total discharge flow,PS_PUBLISHED,FC03,2,Signed 16-bit,Read,m3/h,value * 0.36,0.36,9999.9,%QW2,STN,
|
|
||||||
PS_STN_PUMPS_RUNNING,Pumps running,PS_PUBLISHED,FC03,3,Signed 16-bit,Read,count,value,1.0,9,%QW3,STN,
|
|
||||||
PS_STN_COMMON_DRIVE_SPEED,Common drive speed,PS_PUBLISHED,FC03,4,Signed 16-bit,Read,%,value * 0.2,0.2,999.9,%QW4,STN,
|
|
||||||
PS_STN_TIME_TO_SPILL_WEIR,Time to spill weir (32767 = drawing down),PS_PUBLISHED,FC03,5,Signed 16-bit,Read,s,value,1.0,99999,%QW5,STN,
|
|
||||||
PS_STN_TIME_TO_LSHH,Time to LSHH (32767 = drawing down),PS_PUBLISHED,FC03,6,Signed 16-bit,Read,s,value,1.0,99999,%QW6,STN,
|
|
||||||
PS_STN_NET_ACCUMULATION,Net accumulation (signed),PS_PUBLISHED,FC03,7,Signed 16-bit,Read,m3/h,value * 0.36,0.36,9999.9,%QW7,STN,
|
|
||||||
PS_PU301_RUN_HOURS,Run hours,PS_PUBLISHED,FC03,8,Signed 16-bit,Read,h,value,1.0,99999,%QW8,PU-301,
|
|
||||||
PS_PU302_RUN_HOURS,Run hours,PS_PUBLISHED,FC03,9,Signed 16-bit,Read,h,value,1.0,99999,%QW9,PU-302,
|
|
||||||
PS_PU303_RUN_HOURS,Run hours,PS_PUBLISHED,FC03,10,Signed 16-bit,Read,h,value,1.0,99999,%QW10,PU-303,
|
|
||||||
PS_STN_VOLUME_REMAINING_TO_SPILL,Volume remaining to spill,PS_PUBLISHED,FC03,11,Signed 16-bit,Read,m3,value,1.0,9999,%QW11,STN,
|
|
||||||
PS_STN_STATION_STATE,Station state (enum 3.1),PS_PUBLISHED,FC03,12,Signed 16-bit,Read,,value,1.0,9,%QW12,STN,
|
|
||||||
PS_PU301_PUMP_STATE,Pump state (enum 3.2),PS_PUBLISHED,FC03,13,Signed 16-bit,Read,,value,1.0,9,%QW13,PU-301,
|
|
||||||
PS_PU302_PUMP_STATE,Pump state (enum 3.2),PS_PUBLISHED,FC03,14,Signed 16-bit,Read,,value,1.0,9,%QW14,PU-302,
|
|
||||||
PS_PU303_PUMP_STATE,Pump state (enum 3.2),PS_PUBLISHED,FC03,15,Signed 16-bit,Read,,value,1.0,9,%QW15,PU-303,
|
|
||||||
PS_STN_CURRENT_DUTY_PUMP,"Current duty pump (0 = none, 1-3)",PS_PUBLISHED,FC03,16,Signed 16-bit,Read,,value,1.0,9,%QW16,STN,
|
|
||||||
PS_STN_ALARM_BITMASK,Alarm bitmask (section 6) - READ AS UNSIGNED,PS_PUBLISHED,FC03,17,Unsigned 16-bit,Read,,value,1.0,99999,%QW17,STN,
|
|
||||||
PS_STN_COMMAND_ACKNOWLEDGE,Command acknowledge (echoes %MW1),PS_PUBLISHED,FC03,20,Signed 16-bit,Read,,value,1.0,99,%QW20,STN,
|
|
||||||
PS_STN_STATION_MODE_1_AUTO,"Station mode: 1 = auto, 2 = off",PS_SETPOINTS,FC03/FC06,1024,Signed 16-bit,Read/Write,,value,1.0,9,%MW0,STN,
|
|
||||||
PS_STN_COMMAND_WORD,Command word (section 3.3),PS_SETPOINTS,FC03/FC06,1025,Signed 16-bit,Read/Write,,value,1.0,99,%MW1,STN,
|
|
||||||
PS_STN_COMMAND_PARAMETER,Command parameter (pump number),PS_SETPOINTS,FC03/FC06,1026,Signed 16-bit,Read/Write,,value,1.0,9,%MW2,STN,
|
|
||||||
PS_STN_LEVEL_CONTROL_SETPOINT,Level control setpoint,PS_SETPOINTS,FC03/FC06,1027,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW3,STN,
|
|
||||||
PS_STN_START_DUTY_LEVEL,Start duty level,PS_SETPOINTS,FC03/FC06,1028,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW4,STN,
|
|
||||||
PS_STN_START_PUMP_2_LEVEL,Start pump 2 level,PS_SETPOINTS,FC03/FC06,1029,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW5,STN,
|
|
||||||
PS_STN_START_PUMP_3_LEVEL,Start pump 3 level,PS_SETPOINTS,FC03/FC06,1030,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW6,STN,
|
|
||||||
PS_STN_STOP_ALL_LEVEL,Stop all level,PS_SETPOINTS,FC03/FC06,1031,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW7,STN,
|
|
||||||
PS_STN_HIGH_LEVEL_ALARM,High level alarm,PS_SETPOINTS,FC03/FC06,1032,Signed 16-bit,Read/Write,%,value / 60,0.016666666666666666,999.9,%MW8,STN,
|
|
||||||
PS_STN_MINIMUM_DRIVE_SPEED,Minimum drive speed,PS_SETPOINTS,FC03/FC06,1033,Signed 16-bit,Read/Write,%,value * 0.2,0.2,999.9,%MW9,STN,
|
|
||||||
PS_STN_SERVICE_INTERVAL,Service interval,PS_SETPOINTS,FC03/FC06,1034,Signed 16-bit,Read/Write,h,value,1.0,99999,%MW10,STN,
|
|
||||||
PS_SIM_MANUAL_INFLOW,manual inflow (mode 0),PS_SIM_CONTROL,FC03/FC06,1044,Signed 16-bit,Read/Write,m3/h,value * 0.36,0.36,9999.9,%MW20,SIM,SIMULATION CONTROL - simulation build only
|
|
||||||
PS_SIM_SCENARIO_0_MAN_1_DIURNAL_2_W,scenario 0=man 1=diurnal 2=wet 3=ref,PS_SIM_CONTROL,FC03/FC06,1045,Signed 16-bit,Read/Write,,value,1.0,9,%MW21,SIM,SIMULATION CONTROL - simulation build only
|
|
||||||
PS_SIM_WRITE_1_TO_RESET_SCENARIO,"write 1 to reset scenario, self-clearing",PS_SIM_CONTROL,FC03/FC06,1046,Signed 16-bit,Read/Write,,value,1.0,9,%MW22,SIM,SIMULATION CONTROL - simulation build only
|
|
||||||
PS_SIM_TIME_SCALE_1_120,time scale 1-120,PS_SIM_CONTROL,FC03/FC06,1047,Signed 16-bit,Read/Write,x,value,1.0,999,%MW23,SIM,SIMULATION CONTROL - simulation build only
|
|
||||||
|
Loading…
Add table
Reference in a new issue