TwinForge is a specification-driven, vendor-neutral industrial automation toolkit. It currently imports Rockwell L5X projects into a lossless domain model and exports tested PLCopen XML and AutomationML representations.
The primary fixture is:
tests/data/basic/BoosterCompressor_20260128.L5X
Current results:
- the full automated test suite passes locally and in CI;
- all 134 RLL rungs and 474 instruction occurrences in the fixture convert;
- generated CODESYS PLCopen XML imports and precompiles with zero errors;
- standard PLCopen XML validates against the PLCopen 2.01 XSD;
- generated AutomationML loads in AutomationML Editor;
- AutomationML validates against the CAEX 3.0 XSD; and
- local and external AutomationML class, link and document references resolve; and
- Pyright reports zero errors and warnings for the maintained package, tests and examples.
These results establish the tested boundary for this fixture. They are not a claim of universal L5X or IEC 61131-3 compatibility.
See the complete architecture diagrams and the maintained PlantUML source.
Unknown L5X attributes and elements are preserved as source extensions. Exporters consume the model and never parse L5X directly.
- Controller, module and electronic-key identity
- Chassis, slots, module connections and parent relationships
- Datatypes, controller/program tags and scalar exported values
- Add-On Instructions, parameters, typed defaults and Structured Text source
- Programs, routines, RLL rungs, tasks and scheduled-program references
- Module engineering units and configured analogue ranges
- Nominal, configured, assigned, unavailable and spare I/O evidence
- Project-specific RLL conversion coverage analysis
- PLCopen XML 2.01 and CODESYS-targeted output
- AutomationML 2.1 / CAEX 3.0 hierarchy, semantic libraries and links
- Vendor-neutral and Rockwell catalog SystemUnitClasses
- Model-driven controller, tag, datatype, module, task and program reports
- Vendor-neutral device parameter and setpoint reports in Markdown and CSV
TwinForge is a deterministic engineering toolkit. AI has assisted its development and can help explain unfamiliar source logic, but AI is not a runtime dependency and must not decide PLC semantics during conversion.
Today, users can inspect an L5X file and generate supported outputs through the maintained scripts documented below. A typical script-based workflow is:
uv run python examples\parse_l5x.py project.L5X
uv run python examples\export_reports.py `
project.L5X reports\project
uv run python examples\export_plcopen.py `
project.L5X build\project.xml `
--profile codesysThese commands parse the source into the same lossless model used by the test suite and exporters. Unsupported target semantics must be reported rather than silently discarded or guessed.
TwinForge installs a twinforge command. Its first stable command group manages
versioned discovery lifecycle and promotion state without performing live
network discovery:
twinforge state init inventory\discovery.json
twinforge state validate inventory\discovery.json
twinforge state inspect inventory\discovery.json
twinforge state inspect inventory\discovery.json --format json
twinforge inspect project.L5X
twinforge inspect project.L5X --format json
twinforge report project.L5X --output reports
twinforge export project.L5X --target plcopen --output project.xml
twinforge export project.L5X --target plcopen --output project.xml `
--xsd reference\PLCopenXML\standard\tc6_xml_v201.xsd
twinforge export project.L5X --target codesys --output codesys.xml
twinforge export project.L5X --target openplc --output build\openplc `
--compile-only
twinforge export project.L5X --target openplc --output build\openplc `
--config openplc-export.json
twinforge export project.L5X --target automationml --output plant.aml `
--base-library reference\AutomationML\AutomationML2.10BaseLibraries.aml
twinforge export project.L5X --target plcopen --output project.xml --dry-runstate init refuses to overwrite an existing path. Validation and inspection
are read-only, return non-zero status for invalid state, and do not require AI
or network access. The same interface is available through
python -m twinforge.
inspect accepts controller, standalone module, program, and Add-On Instruction
L5X exports. It reports a deterministic model summary and all conversion
diagnostics without modifying the source. Missing, malformed, and unsupported
documents return a non-zero status.
report accepts a Controller L5X export and writes the seven supported
engineering reports: controller, tags, datatypes, Add-On Instructions, modules,
tasks, and programs. Existing files with those deterministic names are replaced;
unrelated files in the destination are left untouched.
export --target plcopen writes target-neutral PLCopen XML 2.01 without
CODESYS extensions. Supplying --xsd validates the complete document before
the destination is written and requires the optional validation dependencies.
export --target codesys writes the separately adapted CODESYS PLCopen XML
dialect, including its application and project-structure extensions. The
standard PLCopen 2.01 XSD does not apply to this target.
export --target openplc writes the runtime-evidenced native OpenPLC project
directory. It currently admits one scheduled program with one RLL routine and
the tested Boolean, timer, and counter subset; unsupported semantics fail before
project files are written. --compile-only sets that device configuration mode.
Advanced located-variable and telemetry mappings remain available through the
Python API and a strict, versioned JSON configuration supplied with --config.
See examples/OpenPLC/openplc-export.example.json. Explicit
--compile-only or --no-compile-only options override the configured value.
export --target automationml writes AutomationML 2.1 / CAEX 3.0 and requires
the official AutomationML base-library file. An optional --plcopen-reference
links the controller to an existing PLCopen document, while --xsd performs
CAEX validation. File references are made relative to the output document and
are semantically resolved before anything is written.
Add --dry-run to any export target to execute parsing, target planning,
configuration validation, XSD or semantic validation, and diagnostic reporting
without writing the requested output. Native OpenPLC planning is performed
entirely in memory rather than through a disposable project directory.
The example scripts remain useful as focused developer demonstrations of the same parser, analysis, and exporter APIs.
The CLI is expected to provide conversion-readiness results before export, clear unsupported-instruction diagnostics, deterministic output, meaningful process exit codes, and optional machine-readable diagnostics. Target choices such as OpenPLC located variables or CODESYS deployment settings will come from validated configuration files or explicit command options.
AI may remain useful for explaining diagnostics, reviewing AOIs, suggesting manually approved mappings, or drafting engineering prose. Every supported parse, analysis, validation, and export operation must remain usable without AI or a network service.
Install development dependencies:
uv sync --extra validationParse the reference L5X:
uv run python examples\parse_l5x.py `
tests\data\basic\BoosterCompressor_20260128.L5XRun tests:
uv run pytestRun static type checking:
uv run pyrightPyright uses standard mode for src/twinforge, tests, and maintained
examples. The legacy examples/build_twin.py live-discovery sketch is excluded
until its underlying API is implemented.
Generate PLCopen XML:
uv run python examples\export_plcopen.py `
tests\data\basic\BoosterCompressor_20260128.L5X `
examples\PLCOpenXML\BoosterCompressor_codesys.xml `
--profile codesysGenerate human-readable engineering reports:
uv run python examples\export_reports.py `
tests\data\basic\BoosterCompressor_20260128.L5X `
reports\BoosterCompressorThe report exporter consumes the vendor-neutral model rather than parsing L5X directly. Reports therefore include promoted scalar values, engineering units, ranges, resolved task/program relationships and preserved RLL source text. AOI reports include parameters, typed defaults and numbered Structured Text source lines.
Assess captured AOIs before selecting an IEC 61131-3 conversion strategy:
uv run python examples\analyze_aoi_portability.py `
tests\data\aoi\Str_Capacity_AOI.L5X `
--output reports\Str_Capacity_AOI\aoi_portability.txt `
--puml reports\Str_Capacity_AOI\aoi_portability.pumlThe analyzer recommends a function or function block and classifies each AOI as a portable candidate, adapter required, or manual review. Its conclusions are conservative and evidence-based: they identify retained state, lifecycle hooks, dependencies, referenced data types, Structured Text calls and known Rockwell services. A portable-candidate result is not proof of semantic equivalence on another runtime.
Measure lossless Structured Text syntax coverage:
uv run python examples\analyze_structured_text.py `
tests\data\aoi\Str_Capacity_AOI.L5X `
--output reports\Str_Capacity_AOI\structured_text_analysis.txtExport a supported Structured Text AOI through executable IR to a CODESYS PLCopen XML function block:
uv run python examples\export_aoi_codesys.py `
tests\data\aoi\Str_Capacity_AOI.L5X `
examples\PLCOpenXML\Str_Capacity_codesys.xmlThis path applies the explicit promote_written_inputs normalization policy
and reports both its audit diagnostics and any unresolved target requirement.
The current evidence-backed target mappings cover CODESYS variable-length
VAR_IN_OUT arrays and Rockwell SIZE array-dimension semantics. The example
also emits an explicit ten-element test binding, PLC_PRG, its function-block
call, and a 20 ms cyclic MainTask.
Generate and validate AutomationML:
uv run python examples\export_automationml.py `
tests\data\basic\BoosterCompressor_20260128.L5X `
examples\AutomationML\BoosterCompressor.aml `
--plcopen ..\PLCOpenXML\BoosterCompressor_codesys.xml `
--base-library `
..\..\reference\AutomationML\AutomationML2.10BaseLibraries.aml `
--xsd reference\AutomationML\CAEX_ClassModel_V.3.0.xsdThe reference/ directory is intentionally ignored. Standards documents and
schemas must be obtained from their official publishers and supplied locally.
- Architecture
- Architecture and refactoring roadmap
- Domain model
- Roadmap
- Parameter and setpoint reports
- PLCopen capability matrix
- AOI portability and runtime contracts
- Structured Text front end
- Executable intermediate representation
- AutomationML capability and validation
- PLCopen reference handling
- AutomationML reference handling