wrps-demo-kit/03-plc/VERSIONS.md
Clio Liu 55279ca78f docs(plc): as-built copy, versions, and a getting-started guide
Adds what the folder was missing for someone picking it up cold.

as-built/  the STruC++ output copied out of the live container - the C++
           the PLC is actually executing, plus program.st and the Modbus
           buffer config. The running image was made with docker commit
           and exists in no registry, so this is the only other copy of
           the compiled form.

           Verified while copying: the deployed program.st matches
           build/wrps.st generated from src/. Identical POU structure,
           ZERO differences in non-declaration lines. src/ is genuinely
           canonical and the running PLC agrees with it.

VERSIONS.md         every version read from the running system, not from
                    documentation: runtime v4.1.10, STruC++ 0.6.2, Editor
                    4.2.11, Debian 12, g++ 12.2, pymodbus 3.11.2, CI
                    Server R1.03. Plus which plugins are enabled -
                    ethercat is on for no reason - and a v3-vs-v4 table,
                    since most OpenPLC guidance online is for v3 and the
                    %MW HR1024 change silently produces wrong data.

GETTING-STARTED.md  three questions answered in a page: how to modify the
                    program, how to stand up a new PLC container from
                    scratch, how to move this one. Includes the compose
                    file, the Editor steps that are not generated and are
                    always missed, and a symptom-to-document table.
2026-09-02 16:48:30 +10:00

3.4 KiB
Raw Blame History

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.03 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 noscripts/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 folderproject.json + one file per POU
%MW Modbus mapping starts at HR 0 starts at HR 1024 (%QW occupies 01023)

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.

CI Server R1.03 vs R1.05. One R1.03 behaviour is load-bearing here: 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. If you move to R1.05, re-check that before assuming the workaround is still needed.