For technical leaders

Architecture

How ForgeIEC is built: which processes run on the controller, how they exchange data, how faults are reported — and why it is built this way.

ForgeIEC keeps three jobs apart: programming at the workstation, running on the controller and connecting the field devices. Each job runs in its own processes, which exchange data over a shared-memory bus. If one bus connection fails, the rest keeps running.

Overview

The system at a glance

The Studio on the workstation talks gRPC to the Anvil server (anvild) on the controller. There, the PLC program, the bus connections and the operator interface run as separate processes; they exchange data over the Anvil bus, a publish/subscribe bus on shared memory (iceoryx2).

System overview: Studio, Anvil server, PLC cycle, Anvil bus, Tongs, field devices, Hearth and RivetForgeIEC Studioworkstation: ST editor, compiler, diagnosisgRPCproject, monitor, parametersCONTROLLER · industrial PCAnvil server (anvild)builds the program, starts and supervisesstartsforgeiec_plcPLC cycle, own processAnvil busiceoryx2 memory · process data · status · diagnosisTongs-Buscontrol plane on the Anvil bus · anvild is the only mastertongs-modbusTCP / RTUtongs-lorawanin progresstongs-…one process per segmentHearthHMI, previewwebField devicesModbus · LoRaWAN sensors · EtherCAT, PROFIBUS, EtherNet/IPBrowserpanel, tabletREMOTE ACCESS · Rivetin developmentPhoneWireGuard appRivet serverfixed IP, brokerssees no contentoutgoingonlyRivet gatewayin the LAN next tothe controller
Processes and connections. Solid arrows: data; coloured: the control plane (Tongs-Bus), on which only anvild writes into a Tongs.
Text description of the diagramTop left, ForgeIEC Studio on the workstation. It is connected over gRPC to the Anvil server (anvild) on the controller. anvild starts the PLC cycle forgeiec_plc as a process of its own. Both are attached to the Anvil bus (iceoryx2, shared memory), which carries process data, status and diagnosis. On the same bus runs the Tongs-Bus, the control plane whose only master is anvild. Below, one Tongs process per bus segment (Modbus TCP/RTU, LoRaWAN in progress, others) and Hearth, the operator interface, as a preview. The Tongs talk to the field devices; Hearth delivers screens to a browser on a panel or tablet. On the right, the remote access Rivet (in development): a gateway in the controller’s LAN builds only outgoing connections to a central server, through which a phone with the WireGuard app reaches the released controller.
  • ForgeIEC Studio translates the IEC program (Structured Text) into C++ source and transfers it to the controller.
  • anvild builds the program forgeiec_plc from it with make and g++ and starts it as a process of its own. It also starts and supervises one Tongs per bus segment (German Zange, tongs): a bridge between the PLC and the field devices.
  • The Anvil bus connects all processes on the controller without copying the data.
  • The Tongs-Bus is the backplane of anvild: addresses, heartbeat, parameters and commands for the Tongs. Hearth (and the resting gateway bellowsd) read along and instruct anvild when they want something changed.
  • Hearth reads the process data directly from the Anvil bus; anvild publishes the HMI groups from the PLC program’s monitor stream. Hearth produces no values, it shows them.
  • Rivet brings the controller’s screen safely to a phone, without port forwarding — more on the Rivet page.

Layers

Building blocks and repositories

Every layer has its own repository. The Tongs and tongs-core are submodules of the anvil repository and build only inside that tree; every participant on the bus builds against the same iceoryx2 version as anvild.

Workstation

Studio

The engineering tool (C++, Qt 6): ST editor, own compiler core, bus configuration, diagnosis. Talks to the controller over gRPC only.

Controller

anvil

The Anvil server anvild, the transport shared/anvil (iceoryx2 with a stable C interface for the PLC runtime) and the contract crates. Holds all Tongs as submodules.

Common base

tongs-core

What all Tongs share: fault model, status format, runtime frame, Tongs-Bus protocol, parameter and diagnosis model. A new Tongs contains only its protocol.

Bus connection

The Tongs

One repository per protocol: tongs-modbustcp, tongs-modbusrtu, tongs-ethercat, tongs-ethernetip, tongs-profibus, plus tongs-lorawan in progress.

Contracts

crate-contract and shared

One source of truth for what several processes speak: the codec for IEC types on the wire, the reader of the variable description, the command handshake. shared is the Anvil transport itself.

Operation

hearth

Hearth Server (Rust) shows screens in the browser and reads the Anvil topics for them; Hearth Studio is its editor. Runs as a preview today.

For developers

The crate tree of tongs-core

Three of the five crates have no access to processes, memory or network. They run in unit tests without shared memory — which keeps the heart of every bus connection fast and fully testable.

Crate dependency tree of tongs-corefeature bustongs-<protocol>the Tongs, own repositoriesanvildmaster of the Tongs-Bustongs-runtimeprocesses, shared memorytongs-corefault model, status formatforgeiec-tongs-busbus protocol, sans-IOanviltransport with C ABIforge-device-diagdiagnosis modelforge-tongs-paramsparameter modeliceoryx2 =0.9.2shared memoryno I/O: testable without shared memory or networkonly with Cargo feature "bus"arrow: "uses"
Arrows point from a crate to what it uses. A Tongs depends only on tongs-core and tongs-runtime; tongs-core re-exports the types of the model crates.
Text description of the diagramAt the top, the Tongs programs (own repositories) and anvild. A Tongs uses tongs-runtime and tongs-core. tongs-runtime uses tongs-core and anvil, the transport with a C interface, which in turn uses iceoryx2 version 0.9.2. tongs-core uses the diagnosis model forge-device-diag and the parameter model forge-tongs-params; forge-device-diag also uses forge-tongs-params. Only with the Cargo feature “bus” does tongs-core also use the bus protocol forgeiec-tongs-bus and anvil. anvild uses forgeiec-tongs-bus, anvil and tongs-core. forge-device-diag, forge-tongs-params and forgeiec-tongs-bus do no input or output.
  • tongs-core: the fault state machine, status format, backoff, clocks; with feature bus the Tongs as a participant on the Tongs-Bus.
  • tongs-runtime: command line, signals, configuration, Anvil binding, status publisher, supervisor. A Tongs implements exactly one trait, Protocol.
  • forgeiec-tongs-bus: the Tongs-Bus protocol, sans-IO.
  • forge-tongs-params and forge-device-diag: parameter and diagnosis model; the C header for the Studio is generated from the diagnosis model, and a test keeps both equal.

Data

Four data planes on one bus

Process values, state, diagnosis and control commands travel on separate topics. The Tongs-Bus carries addresses, heartbeat, parameters and commands, never process values — so administration never disturbs the cycle.

The planes on the Anvil bus: process data, status, diagnosis, controlPLC programforgeiec_plcReadersanvild, Hearth, Studioanvildthe only masterTongsone process per segmentAnvil/<GROUP>process data: outputs, cyclicAnvil/<GROUP>/bridgeprocess data: inputsAnvil/status/<segment>state of every device, at least once a secondAnvil/diag/<segment>diagnostic values from the device description (FDD)Anvil/tongsbuscontrol: addresses, heartbeat, parameters, commands — never process values
The topics on the Anvil bus and their direction. The status arrives at least once a second even when a segment has no devices.
Text description of the diagramOn the left the PLC program forgeiec_plc, the readers (anvild, Hearth, Studio) and anvild as the master; on the right the Tongs, one process per segment. First, the PLC program sends its outputs cyclically on Anvil/GROUP to the Tongs. Second, the inputs come back from the Tongs on Anvil/GROUP/bridge. Third, the Tongs publishes the state of every device on Anvil/status/segment, at least once a second. Fourth, it publishes the diagnostic values from the device description on Anvil/diag/segment. Fifth, in both directions between anvild and the Tongs: the Tongs-Bus on Anvil/tongsbus for addresses, heartbeat, parameters and commands, never for process values.

The status record is binary and of fixed size (5152 bytes for up to 64 devices per segment). A reader judges freshness by its own clock: a record older than three seconds means a dead Tongs, and its devices count as offline.

In the Studio, a view per protocol with diagnosis and bus traffic is being built for this. in progress

Reliability

The fault model

Every bus connection reports faults with the same ten states — whether Modbus, LoRaWAN or EtherCAT. A PLC program therefore sees one diagnosis interface for every protocol: xOnline, xFault and xWarning per device, plus error code and counters. Only in the states Online and Degraded can values be trusted; Degraded means online, but with a failing variable. The generated PLC code, the Studio display, Hearth and anvild all use the same classification.

Every device has its own connection state, its own status and its own backoff; an unreachable device does not delay another, and device tasks share no blocking lock. State changes go through a single function that refuses transitions the model does not have. After a failure, the Tongs waits exponentially (1, 2, 4, 8, 16, then 30 s). If a Tongs crashes, anvild restarts it with a backoff (at most 30 s); the state held by anvild stays untouched.

Fault model: ten states and the allowed transitionsreloadnext attempt: 1, 2, 4, 8, 16, then 30 sUnknownDisabledConnectingConfigErrorOnlineDegradedTimeoutUnreachableBackoffEvery state except Shutdownleads to Shutdown (the end).values can be trusted
The allowed transitions (tongs_core::can_transition). A device that never answered is Unreachable, not Timeout.
Text description of the diagramThe start is Unknown. From Unknown to Connecting or Disabled; from Disabled to Connecting once the device is enabled. Connecting leads to Online, Unreachable or ConfigError; ConfigError leads back to Connecting only after the configuration is reloaded. Online and Degraded change into each other and both lead to Timeout or Unreachable. Timeout and Unreachable lead to Backoff, and Backoff after a wait of 1, 2, 4, 8, 16, then 30 seconds back to Connecting. Every state except Shutdown leads to Shutdown, the end.

Settings

The parameter model

A setting is checked first, then made effective, then saved — and every side checks it with the same code. Parameters exist on two levels: device parameters come from the manufacturer’s device description (FDD); a Tongs does not invent any. Segment parameters are what no FDD can know — where a radio service listens, say, or a cycle time; the Tongs describes them itself and prints the description even without a running process (--describe). The Studio renders both without knowing the protocol.

Values are binary, encoded as IEC types and addressed by number. A write lands in a draft first; APPLY makes it effective or refuses it with reasons, SAVE stores it atomically, DISCARD drops it. anvild checks every value before the bus exactly as the Tongs will and names every refused one. Secret values are never read back, only whether they are set and a fingerprint; anvild does not write them over the bus today because its encryption is not built yet — they come from the project.

Why this way

Decisions and their reasons

Process per bus segment

One Tongs per segment instead of one big daemon

A hanging or crashing protocol takes down neither the PLC nor other buses. anvild restarts the Tongs; each one reloads on its own (SIGHUP) and ends in order (SIGTERM, within five seconds).

Control plane

Typed binary records instead of JSON

Every register has a fixed layout of IEC types; no JSON, no XML. The master needs no parser, telegrams fit into 512-byte frames, and a malformed write is refused at once. The gRPC interface to the Studio carries typed messages as well.

Testability

A protocol core without input and output

The bus protocol is sans-IO: frames and time go in, frames and events come out. So it runs in tests on a simulated line, a lossy one included — without shared memory, without a network.

Clear authority

One master per machine

Only anvild writes into a Tongs; any other write is refused. A Tongs therefore needs no rights list. If a master hears a second one at start-up, it leaves the bus and anvild ends.

Lifetime

The bridges end with the master

PLC program and Tongs end with anvild; without a heartbeat (default 3 s) a Tongs must end. The field devices go to their safe state through their own supervision. The rule applies to Tongs on the Tongs-Bus; the existing protocol Tongs do not use it yet (as of 22.10.2026).

Sampling

At most half the system cycle

To sample a signal without aliasing, the poll period may be at most 0.5 × the system cycle. The achieved period is measured, not assumed: anvild computes mean, jitter and overruns per device and reports violations.

On security on the machine: the Anvil transport admits only processes of anvild’s user group. That is the outer fence, not an authorisation; authentication of privileged writes on the Tongs-Bus is specified but not built yet. ForgeIEC does not replace a safety PLC (no SIL/PL).

Honest status

What runs today

Building blockDetailsStatus
ST editor, compiler core, anvild, forgeiec_plcPreview version 0.2, in pilot use at the SoLaWi Ackervielfaltin use
Modbus TCP / RTUbridges for both variantsavailable
LoRaWANthe focus for the SoLaWisin progress
EtherCAT, PROFIBUS, EtherNet/IPskeleton with fault model and binding, protocol part to followin progress
Hearth (operation)over the Anvil bus, as a previewpreview
Rivet (remote access)in development, pilot with SoLaWisin progress
bellowsd (HMI/OPC UA gateway)not in development at presentresting

Source code under AGPL-3.0-or-later; access on request. The developer documentation (the tongs-core wiki with architecture, dependency tree and “where do I change what”) is not public yet — access on request as well, at blacksmith@forgeiec.io.