Skip to content

feat: EtherCAT ESI support (merge development sync) - #730

Closed
marconetsf wants to merge 22 commits into
developmentfrom
feat/ethercat-support-v2
Closed

feat: EtherCAT ESI support (merge development sync)#730
marconetsf wants to merge 22 commits into
developmentfrom
feat/ethercat-support-v2

Conversation

@marconetsf

Copy link
Copy Markdown
Contributor

Summary

Brings the feat/ethercat-support-v2 branch up to date with development, incorporating the latest CI sync workflow and documentation updates. The EtherCAT ESI feature (editor adapter, ESI UI components, parser, IPC handlers) was already implemented in prior commits on this branch.

This PR represents the desktop editor side of the EtherCAT ESI feature. The backend and web adapter are delivered in companion PRs.

What this branch contains (EtherCAT ESI feature)

Desktop editor adapter

  • src/middleware/adapters/editor/esi-adapter.ts — implements EsiPort via Electron IPC, injecting project path from callback
  • 12 IPC channels in main.ts / renderer.ts for ESI operations

ESI Service (main process)

  • src/backend/editor/ethercat/esi-service.ts — persistence layer managing devices/esi/ directory within projects
  • Supports v1→v2 index migration, per-project ESI repository

Shared backend (parser + channel utilities)

  • src/backend/shared/ethercat/esi-parser-main.tsparseESILight + parseESIDeviceFull using fast-xml-parser
  • src/backend/shared/ethercat/esi-parser.ts — PDO-to-channel conversion, IEC address generation, default mapping generation

ESI UI Components

  • esi-upload.tsx — drag-and-drop upload with progress, 100 MB limit
  • esi-repository.tsx / esi-repository-table.tsx — library management
  • esi-channels-table.tsx — channel-to-variable mapping
  • esi-device-info.tsx — device detail panel
  • repository-tab.tsx — tab orchestrating the above
  • channel-mapping-table.tsx, configured-devices.tsx, advanced-tab.tsx — device configuration

Port contract

  • src/middleware/shared/ports/esi-port.ts — 6 methods (loadRepositoryLight, migrateRepository, parseAndSaveFile, deleteRepositoryItem, clearRepository, loadDeviceFull)
  • src/types/ethercat/esi-types.ts — 627 lines of ESI domain types

Merge with development

Latest merge incorporates CI sync workflow (ci-sync.yml), updated documentation (CLAUDE.md), and new comparison scripts for cross-repo surface validation.

Companion PRs

  • autonomy-edge — backend endpoints (Autonomy-Logic/autonomy-edge#173)
  • openplc-web — web adapter (Autonomy-Logic/openplc-web#360)

Test plan

  • npm run dev — application starts and ESI tab works
  • Upload ESI XML → appears in repository table
  • Load device full → channels shown in configuration
  • Delete item → removed from table
  • Clear repository → all items gone
  • npm test — unit tests pass
  • Architecture validation (npm run validate:arch) passes

🤖 Generated with Claude Code

thiagoralves and others added 20 commits April 10, 2026 10:07
Port EtherCAT type definitions and PLC schema extensions. Move all
EtherCAT business logic to src/backend/shared/ethercat/ as the single
source of truth for both Electron and web backends.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add EtherCAT runtime discovery methods to RuntimePort (scan, test,
validate, status, interfaces). Create EsiPort interface for ESI
repository operations (load, parse, save, delete, migrate). Wire
EsiPort into PlatformPorts. Add hasEthercat capability flag and
useEsi() convenience hook.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add updateEthercatConfig action to project slice. Include EtherCAT
channel mappings in IEC address collection to prevent conflicts with
Modbus. Extend remote device IO point selector to collect EtherCAT
channel aliases. Port use-device-configuration hook using EsiPort
instead of window.bridge for on-demand device loading.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Port 21 EtherCAT editor components from src/renderer/ to src/frontend/.
Replace all window.bridge calls with useRuntime() and useEsi() hooks.
Update import paths for shared backend utils and frontend assets.
Route EtherCAT protocol to dedicated EtherCATEditor in workspace screen.
Enable EtherCAT option in create-element card.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Import generateEthercatConfig from shared backend and wire it into
the Runtime v4 compilation pipeline. Generates conf/ethercat.json
alongside existing Modbus, S7Comm, and OPC-UA configs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove VPP-specific imports, methods, and compilation export that
leaked into the EtherCAT branch during cherry-pick conflict resolution.
Fix corrupted escaped quotes in renderer.ts line 1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Port feat/ethercat-task-selection changes to the refactored architecture:
- Add isSystemTask/associatedDevice fields to PLCTask schema
- Add enabled field to EtherCATMasterConfig schema
- Create ethercat-task-helpers in shared backend (task naming, cycle
  time conversion)
- Auto-create/delete/rename system tasks when EtherCAT devices are
  managed in the project slice
- Sync cycle time changes to system task interval
- Preserve system tasks during task list updates
- Prevent editing/deleting/reordering system tasks in task table and
  task editor UI
- Add task_name and enabled filter to EtherCAT config generator
- Add Enable Plugin toggle to global settings tab

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace direct openPLCStoreBase import in editor-platform.ts with a
setProjectPath() setter pattern matching the existing setRuntimeIpAddress
approach. The store import was causing a circular dependency that
resulted in a blank screen on startup. App.tsx now syncs the project
path to the platform adapter via useEffect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Port all additional work from feat/ethercat-task-selection including:
- Restructured EtherCAT editor with tab layout (Network, Devices,
  Repository, Diagnostics, Advanced)
- New EtherCATDeviceEditor for individual slave device editing
- Side-by-side scan/configured tables with device tree navigation
- Offline device management and improved network interface handling
- Standardized device names and hex formatting
- plc-ethercat-device editor model and tab type for slave devices
- ethercatDeviceActions in shared slice (delete/rename slaves)
- Enable plugin filter in config generator
- Default task priority changed from 0 to 1
- Error propagation fix in IPC POST request handler

Note: ProjectTreeExpandableLeaf (device tree in explorer) deferred
to follow-up due to type system differences between architectures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add expandable leaf component to project tree that supports hierarchical
navigation — EtherCAT buses expand to show their configured slave devices
as child leaves. Each slave device leaf supports rename, delete, and
opens the dedicated EtherCATDeviceEditor.

Changes:
- Add ProjectTreeExpandableLeaf component with collapse/expand, rename,
  delete, and context menu support
- Add ethercatDevice leafLang and LeafSources entry
- Add busName/deviceId props to ProjectTreeLeaf for ethercat slaves
- Add ethercat device rename/delete handling in ProjectTreeLeaf
- Update explorer to render EtherCAT buses as expandable leaves with
  slave devices as children

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ports the 6 unpushed commits from feat/ethercat-task-selection:

- d784f3e3 refactor: replace colored IN/OUT badges with plain text in
  channel tables
- 969ecd8f refactor: update channel filter buttons to match console tab
  style
- 98e870ec feat: add task priority setting to EtherCAT advanced config
- 4213c4d3 fix: prevent duplicating system task properties when creating
  new tasks (also applied to the ROWS_NOT_SELECTED path, which copies
  from task in this branch)
- 5a635e33 feat: sort tasks by priority in ST/XML generation and rename
  tab to Bus
- a1df55a1 feat: add breadcrumb trails for remote devices, servers, and
  EtherCAT slaves

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The breadcrumb above already shows the bus and device context, making
the "<name> — Position N — Bus: <bus>" subtitle redundant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The tab for EtherCAT slave devices (type 'ethercat-device') was falling
through to the default ILIcon because the TabIcons map and the
languageOrDerivation union had no case for it. Add the mapping so the
tab matches the blue DeviceTransferIcon already shown in the project
tree.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The button was rendered conditionally in the tab body, so appearing/
disappearing caused the tables below to shift vertically. Place it in
the right slot of the existing Scanned Devices header (symmetric with
the +/- actions on Configured Devices) and keep it always visible,
disabled when nothing is selected. Layout is now stable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adding an EtherCAT slave (via scan or repository) was leaving
channelMappings as an empty array. The compiler reads that field to
assign IEC locations (%QX0.0, %IX0.0, ...) when generating the runtime
config; without entries, every channel was emitted with an empty
iec_location, so outputs never bound to PLC variables and the slave
appeared inert until the user opened its editor page (where a useEffect
in use-device-configuration was lazily filling the mappings).

Move the population to the add path:

- enrichDeviceData(device, usedAddresses?) now also returns
  channelMappings, generated via generateDefaultChannelMappings against
  the project-wide set of already-used IEC addresses.
- New util collectUsedIecAddresses gathers IEC locations from every
  remote device's Modbus I/O points and EtherCAT channel mappings.
  ethercat-device-editor.tsx and the add handlers both consume it.
- handleAddSelectedFromScan accumulates freshly assigned addresses
  between iterations so devices added in the same batch don't collide.

The lazy-init in use-device-configuration is left in place as a fallback
for projects saved before this fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts:
#	src/backend/editor/compiler/compiler-module.ts
#	src/main/modules/ipc/main.ts
#	src/main/modules/ipc/renderer.ts
#	src/types/PLC/units/task.ts
Slave tabs (elementType.type === 'ethercat-device') were never
registered in the files store, so closeFile's getSavedState lookup
defaulted to false and triggered the "Unsaved changes — save?" modal on
every close, even when nothing had been edited. Worse, clicking "Save"
in that modal called executeSaveFile, which also failed on the missing
files entry, so the tab refused to close ("Don't Save" worked because
its handler bypassed the result).

Treat ethercat-device tabs as views over the parent remote device's
data: they own no file and have no per-tab dirty state. Short-circuit
closeFile to forceCloseFile for that tab type. Real edits to slave
config still dirty the parent bus tab via syncDevicesToStore, so the
project-level save flow is unaffected.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Upstream commit 1554301 moved the shared PLC type schemas from
src/types/PLC/ to src/backend/shared/types/PLC/ (and deleted
src/types/PLC/runtime-logs.ts in favor of the existing definition in
middleware/shared/ports/types.ts) but did not update every importer.
Eight files were left referencing the old paths, breaking tsc with 13
"Cannot find module" / cascading implicit-any errors.

Repoint each importer to the new location:

- @root/types/PLC/devices             -> @root/backend/shared/types/PLC/devices
- @root/types/PLC/open-plc            -> @root/backend/shared/types/PLC/open-plc
- @root/types/PLC/runtime-logs        -> @root/middleware/shared/ports

Also re-sorts adjacent imports in the touched files via eslint --fix to
satisfy simple-import-sort.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…support-v2

# Conflicts:
#	package-lock.json
#	package.json
#	src/frontend/screens/workspace-screen.tsx
#	src/middleware/editor-platform.ts
@coderabbitai

coderabbitai Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cc5ec100-e468-4e78-84e8-7cf3b0493851

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ethercat-support-v2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

marconetsf and others added 2 commits April 16, 2026 12:44
Moves the canonical ESI type definitions from src/types/ethercat/ to
src/middleware/shared/ports/esi-types.ts so ports can import them
without violating the architecture layer rule (ports -> [utils, ports]).

The original file at src/types/ethercat/esi-types.ts becomes a
re-export barrel so the 30+ existing consumers continue working
without import changes.

Also fixes Prettier formatting on 6 EtherCAT files flagged by CI.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Resolves architecture validation failures by ensuring ESI types live
exclusively in src/middleware/shared/ports/esi-types.ts (the ports
layer) and all 30 consumers import from there directly.

The previous approach (re-export barrel in types/ethercat/) violated
two architecture rules simultaneously: ports->types and types->ports
were both forbidden. This commit eliminates the barrel entirely —
types/ethercat/index.ts no longer re-exports ESI types, and all
imports now use @root/middleware/shared/ports/esi-types.

Also runs lint:fix to resolve import sorting issues in synced files.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@marconetsf marconetsf closed this Apr 16, 2026
@marconetsf
marconetsf deleted the feat/ethercat-support-v2 branch April 16, 2026 11:29
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.

2 participants