Skip to content

Export and import device-tree sibling devices#27

Closed
gsokoll wants to merge 3 commits into
backport/ws1-bugfixesfrom
backport/ws3-device-tree
Closed

Export and import device-tree sibling devices#27
gsokoll wants to merge 3 commits into
backport/ws1-bugfixesfrom
backport/ws3-device-tree

Conversation

@gsokoll

@gsokoll gsokoll commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Part of #24.

Credit: reimplemented from ipfedor/codescribe commit 6e08a99.

What this adds

codescribe currently tracks two things per device: the Application branch and the IFM-style Communication node. On standard CODESYS hardware there is a second layout: Ethernet, Modbus and fieldbus devices sit in the device tree as direct DEVICE children of the PLC device, siblings of Plc Logic. These were not tracked at all.

New module src/device_tree_import_export.py:

  • Export: each qualifying sibling is written as <device>/devices/<name>.xml via native recursive export. Children that contain an Application anywhere in their subtree are excluded, since they are already exported through their own device entrypoint; the Communication object is excluded since it has its own export path.
  • Import: for each tracked devices/*.xml, the matching direct DEVICE child is found by name, its children are removed first, then the xml is imported natively. A missing device raises an error naming it.
  • Save As Template: children of tracked device-tree devices are removed from the template copy.

Opt-out: add a _NO_EXPORT folder as a direct child of the PLC device to disable the device-tree export. The existing _NO_EXPORT under Communication continues to disable only the Communication export.

CI: device_tree_import_export added to the import smoke list. ASCII check, IronPython compile and import smoke all pass locally.

Live validation required before merge

  • Round-trip a project with an Ethernet or Modbus device next to Plc Logic: export, import into a fresh template copy, confirm the device configuration survives.
  • On the CR711s compound project (CoDeScribe-test-2.project), confirm SafetyPLC and StandardPLC are NOT exported a second time under devices/. The contains-Application check is the guard for this.
  • Confirm Save As Template removes the children of tracked device-tree devices from the template copy.

Stacking note

This PR is stacked on #25 (backport/ws1-bugfixes) and retargets to main automatically when that merges. If the staging-export PR merges first, this branch will need a trivial rebase, as both touch src/script_export_to_files.py.

gsokoll added 2 commits June 12, 2026 15:24
On standard CODESYS hardware, Ethernet, Modbus and fieldbus devices sit in
the device tree as direct DEVICE children of the PLC device, next to
Plc Logic, and codescribe did not track them. Add
src/device_tree_import_export.py to export each such sibling as a native
recursive xml file under <device>/devices/<name>.xml, import them back, and
strip their children in Save As Template.

Children that carry an Application anywhere in their subtree are excluded
from the export. In compound safety projects such as the IFM CR711s the
SafetyPLC and StandardPLC each carry their own Application and are already
exported through their own device entrypoint, so exporting them here would
duplicate them. The Communication object is also excluded since it has its
own export path.

Adding a _NO_EXPORT folder as a direct child of the PLC device disables the
device-tree export. The existing _NO_EXPORT under Communication keeps
disabling only the Communication export.

Credit: reimplemented from ipfedor/codescribe commit 6e08a99. Refs #24.
get_src_folder(template_project) points at <name>_template_vX, which never
exists on disk, so remove_tracked_device_tree_devices returned early and the
template kept its tracked device-tree children. The tracked list lives in the
primary project export folder.
@gsokoll

gsokoll commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

Pushed b48c95d on top: the Save As Template wiring now resolves the tracked device list from the primary project export folder. get_src_folder(template_project) pointed at _template_vX, which never exists on disk, so the removal was a no-op.

…ices

Live testing on an IFM CR711s compound project showed two faults in the
original import design. Children of package-fixed devices (Local_IO/Inputs,
HMI/User_LEDs) cannot be removed, which aborted the whole import. And
import_native pastes the archived object as a child of the receiving node
rather than replacing in place, so importing a device xml onto the device
itself produced a rejected HMI_1 paste dialog.

Import now removes the matching device and imports the xml into the PLC
device, which recreates it. Package-fixed devices that refuse removal are
skipped with a message, since the project template carries their
configuration, the same contract as the fixed top-level communication
devices. A device missing from a fresh template-derived project imports
directly instead of raising. Save As Template applies the same semantics.
@gsokoll

gsokoll commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

Live validation on CODESYS V3.5 SP11 (CR711s compound test project) found two real design faults in the original import path; both are fixed in 0bc31fd.

Found and fixed

  1. Children of package-fixed devices (Local_IO/Inputs, HMI/User_LEDs on IFM hardware) cannot be removed; child.remove() raised StandardError and aborted the whole import. The fork has the same flaw; it never surfaced there because its sibling devices are user-added.
  2. import_native pastes the archived object as a child of the receiving node, never replacing in place. Importing a device xml onto the device itself attempted to add HMI_1 inside HMI and CODESYS rejected it with a blocking native dialog. Import now removes the matching device and imports the xml into the PLC device (recreating it), mirroring the proven communication-import mechanism. Package-fixed devices that refuse removal are skipped with a message, since the template carries their configuration, and a device missing from a fresh template-derived project imports directly instead of raising.

Passed after the fix

  • Export produces devices/Local_IO.xml and devices/HMI.xml for both PLCs; no SafetyPLC/StandardPLC double export (they are project-level entrypoints, and the contains-Application guard holds).
  • Full round-trip (import with fixed-device skip messages, build, re-export): tree identical, devices/*.xml byte-stable, so fixed-device exports do not churn in git.

Outstanding

  • Positive path with a removable user-added sibling device (remove and recreate on import). The CR711s test project has none; needs a device added in the GUI if the IFM package allows it, or validation on non-IFM hardware.

@gsokoll

gsokoll commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

Outstanding-item result: on the CR711s, Add Device / Append Device offers nothing under the PLC device, so the IFM package fixes the whole sibling tree. The remove-and-recreate import path therefore cannot be exercised on this hardware at all; on IFM projects this feature is export-plus-skip-on-import, which the round-trip validated. The positive path (a removable user-added sibling device being removed and recreated on import) remains covered by design reasoning and by the fork author's non-IFM hardware only. Worth a quick test if we ever have a standard CODESYS target with an Ethernet adapter available.

@gsokoll gsokoll deleted the branch backport/ws1-bugfixes June 12, 2026 07:33
@gsokoll gsokoll closed this Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant