Commissioning
A project goes onto a plant in steps, each one changing one thing: first the engine checks what it would connect to, then it reads the plant and writes nothing, then it writes. No step needs another binary or another project format; a bundle may carry one project file per step (Applications as packages).
flowchart LR
A["check<br/>nothing contacted"] --> B["check --live<br/>every item verified"]
B --> C["run, writes = dry-run<br/>reads, logs writes"]
C --> D["check --live --write<br/>writability"]
D --> E["run --write<br/>or writes = on"]
1. Offline
taktwerk check project.toml
Loads every model, binds every dimension, resolves every signal and checks every connector’s
settings and map against the plan; contacts nothing. A project whose opcua-client or rest
map writes and that does not say writes = "on" or "dry-run" is refused here, so no project
starts writing to a plant, or stops, without saying so.
Run the project as a simulation first: the plant connectors replaced by a plant model in the
image, or the project with --no-connectors and a scenario.
2. The endpoints
taktwerk check project.toml --live
Runs the verification every opcua-client session runs at its start against the live server,
for every connector: each mapped node exists, has the signal’s type and shape, is readable,
and is writable where the connector writes with writes on. It writes nothing. The report has a
row per node and the connector’s own problems (an unreachable endpoint, a missing writes);
--json gives the same as one object. A from-server dimension is resolved only here.
3. Reading, not writing
With writes = "dry-run" in the connector:
taktwerk run project.toml
Inputs and plain tunables are read as usual, the models step on plant data, the write gate is evaluated, and at most once a second the connector logs what it would write:
dry run, not written: plant.u (ns=4;s=Plant.u) = 0.25, …
Compare the logged values with what the plant runs today. Synced tunables stay idle in a dry run. Watch the engine meanwhile:
taktwerk engine status --url 127.0.0.1:8480 --expect 'taktwerk.overruns == 0' \
--expect 'est.status & 255 == 0'
taktwerk engine read 'plant.*' --for 300 # mean, sd, min, max per signal over 5 min
(--http 127.0.0.1:8480 on the run, or an http connector; on a device the bundle’s unit
has one, see Operating a running engine.)
A rest connector takes the same writes: a dry run reads, evaluates the gate and sends
nothing, the heartbeat included, logging what it would send.
4. Writing
taktwerk check project.toml --live --write plc # writability, as that run would write
taktwerk run project.toml --write plc # writes on for this run
--write <id> turns a dry-run connector’s writes on for one run and is recorded in
run.json’s invocation; it is refused while CI is set. Once the loop is accepted, set
writes = "on" in the project (or deploy the bundle’s next project file).
A set point written to the engine and read back with its event:
taktwerk engine set ctl.sp 1.2 # the plan, with the current value
taktwerk engine set ctl.sp 1.2 --yes # write, wait for the tick, read back
Records of commissioning
Each step’s run is a run record when the project has a recorder:
the project’s hash, every override, --write, the tunables’ values at every cycle and every
gate change. @io records exactly what the engine exchanged with the plant.