Corrected in README.md, CLAUDE.md, 02-environment/README.md and 03-plc/VERSIONS.md. The @VERSION 1.03.00 header inside the .qli files is the quickload FILE FORMAT version, not the CI Server release. Left alone. This also sharpens a caveat that was previously stated wrongly. The EQP-E-DUP_ITEM rejection - an item import fails if two items share an IO_ADDRESS - was observed on 2026-08-14 on the DEVELOPMENT machine, which ran R1.03. Production runs R1.05, where it has never been tested. The design still works around it by publishing level and speed in % only, and that workaround costs nothing; but anyone wanting a second unit for a measurement should try it on R1.05 before assuming they need a second PLC register to carry it.
3.8 KiB
Software and versions
Everything below was read from the running system on 2026-09-02, not taken from documentation. Where a version matters — where a different one behaves differently — that is said explicitly.
The PLC
| Component | Version | Where it runs | How to check |
|---|---|---|---|
| OpenPLC Runtime | v4.1.10 | openplc-runtime container on yau-sls-poc-lin001 |
docker exec openplc-runtime cat /workdir/VERSION |
| Docker image | openplc-runtime-migrated:v4.1.10 |
local to the host, not in any registry | docker images |
| Base OS in container | Debian 12 (bookworm) | docker exec openplc-runtime cat /etc/os-release |
|
| Python (runtime + plugins) | 3.11.2 | docker exec openplc-runtime python3 --version |
|
| g++ | 12.2.0 | used to build the PLC program | docker exec openplc-runtime g++ --version |
| GNU Make | 4.3 | drives scripts/Makefile.strucpp |
|
| pymodbus (in the slave plugin) | 3.11.2 | docker exec openplc-runtime ./venvs/modbus_slave/bin/pip list |
Runtime plugins
/workdir/plugins.conf — the third field is enabled (1) / disabled (0):
| Plugin | Enabled | Note |
|---|---|---|
modbus_slave |
1 | This is the one that matters. It is what makes the PLC a Modbus server on 502. |
modbus_master |
0 | Correct — the PLC must not poll anyone. |
opcua |
0 | |
s7comm |
0 | |
ethercat |
1 | ⚠️ Enabled for no reason. It came from an ethercat.json the Editor project emits by default (the file is 0 bytes). Harmless so far, but it is a plugin running with nothing to do. |
The toolchain
| Component | Version | Notes |
|---|---|---|
| OpenPLC Editor | v4.2.11 (AppImage) | Needs --no-sandbox (Electron) and libfuse2t64. ⚠️ Not currently installed anywhere — see DEPLOY.md §0. |
| STruC++ | v0.6.2 | The ST → C++ compiler. Ships only inside the Editor AppImage; there is no standalone binary. This is the single reason the Editor is unavoidable. |
The SCADA
| Component | Version | Where |
|---|---|---|
| Yokogawa CI Server | R1.05 | yau-poc-cicore1 (10.0.0.21) |
Versions that actually matter
OpenPLC Runtime v3 → v4 is a breaking change, and most guidance you'll find online is for v3.
| v3 | v4 (what we run) | |
|---|---|---|
| ST compiler | MatIEC | STruC++ |
Accepts a flat .st upload |
yes | no — scripts/compile.sh explicitly rejects MatIEC files (Config0.c, glueVars.c) |
| Web UI on the runtime | yes | no — REST API only, port 8443, JWT |
| Editor project format | one file | a folder — project.json + one file per POU |
%MW Modbus mapping |
starts at HR 0 | starts at HR 1024 (%QW occupies 0–1023) |
That last row is the one that silently produces wrong data rather than an error.
See register-map.csv, which carries resolved addresses.
The Modbus buffer layout is configuration, not a constant. From
core/generated/conf/modbus_slave.json in the running container:
"holding_registers": { "qw_count": 1024, "mw_count": 1024, ... }
qw_count: 1024 is why %MW0 is holding register 1024. Change that file and
every SCADA address moves.
One CI Server behaviour is load-bearing, and it was observed on a different
release. An item import is rejected if two items share an IO_ADDRESS
(EQP-E-DUP_ITEM). The SCADA design works around it by publishing one unit per
register — level and speed in % only, not in both % and engineering units.
That rejection was seen on 2026-08-14 on the development machine, which ran
R1.03. Production yau-poc-cicore1 runs R1.05, where the constraint has
never been tested. The workaround is harmless either way, but if you need a second
unit for a measurement, try it on R1.05 before assuming you need a second PLC
register for it.