Skip to content

fix: re-take an unowned lease after a PLC restart (#7) - #8

Merged
rafalmaciag merged 3 commits into
masterfrom
fix/issue-7-unowned-lease-retake
Oct 8, 2026
Merged

rafalmaciag merged 3 commits into
masterfrom
fix/issue-7-unowned-lease-retake

Conversation

@rafalmaciag

Copy link
Copy Markdown
Contributor

Fixes #7.

After a PLC power-cycle the PLC came back with LeaseOwner = 0. The driver kept beating, the tick latched LeaseHeld ("another commander took the axis"), IsConnected stayed true, and the connector never re-attached. The device was dead until reconfigured.

Fix (protocol § FR-11 "Advisory lease"). A tick that reads LeaseOwner = 0 while attached is a PLC restart or a clean release, never another commander. The device re-takes the lease in place along the initial attach path:

  1. The tick's status block is checked before any write: map version, limit publication, reading range.
  2. LeaseOwner = own id, then WatchdogFault = 0.
  3. A fresh read is checked again.
  4. The engine re-attaches: CommandSeq continues from CommandAck, Enable follows the PLC state, stale edges are cleared. A verb in flight fails CommunicationLost naming the dropped lease and writes nothing more.
  5. One Warning: LeaseOwner (C+9 = holding 9) = 0 while attached as 1 — PLC restarted or lease released; lease re-taken. …

The axis then shows whatever the PLC reports, typically Disabled and not homed, so the next move is refused NotHomed. A foreign non-zero owner still latches LeaseHeld. A refused re-take latches ProtocolMismatch or OutOfRange and writes nothing. A Transport failure is the existing CommunicationLost path. The connector is unchanged.

Tests

  • GA-I-25 (MiniPlc, real Modbus TCP): MiniPlc.PowerCycle() → lease re-taken, watchdog re-armed, IsConnected true, one Warning, no LeaseHeld; MoveAbsolute refused NotHomed; after Home it moves. Red on master (commit 1846a74), green with the fix.
  • GA-U-12b: write order of the re-take (LeaseOwner, WatchdogFault, [Command, CommandSeq = CommandAck]); sequence continues from the restarted PLC's ack.
  • GA-U-12c: a re-take onto map version 2 writes nothing and latches ProtocolMismatch.
  • GA-U-12 (foreign owner 65534-style takeover → LeaseHeld) unchanged and green.

Gates

  • dotnet build src/GenericAxis.sln: 0 warnings, 0 errors.
  • dotnet test src/GenericAxis.sln: Plugin.Tests 62 → 62, Tests 203 → 206, TestApp.Tests 261 → 261, all passed.
  • C# conformance checker against the TestApp simulator (port 5033): 16/16, RESULT: PASS.

🤖 Generated with Claude Code

rafalmaciag and others added 3 commits October 8, 2026 15:57
…se (#7, red)

MiniPlc.PowerCycle clears the command block (LeaseOwner 0, WatchdogFault 0), State Disabled, Homed off,
CommandAck 0. GA-I-25 fails on master: the driver keeps beating a PLC whose LeaseOwner stays 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A tick that reads LeaseOwner = 0 while attached is a PLC restart or a clean release, never another commander.
The device now re-attaches in place along the initial attach path: the tick's status block is checked before
any write (map version, limit publication, reading range), LeaseOwner = own id, WatchdogFault = 0, a fresh read
is checked again, and the engine re-attaches (CommandSeq continues from CommandAck, Enable from the PLC state,
a verb in flight fails CommunicationLost naming the dropped lease). One Warning names the register read. The axis
then shows whatever the PLC reports (typically Disabled, not homed). A foreign non-zero owner still latches
LeaseHeld; a refused re-take latches ProtocolMismatch / OutOfRange; a Transport failure is CommunicationLost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… is re-taken in place (#7)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rafalmaciag
rafalmaciag merged commit 04eac2e into master Oct 8, 2026
5 checks passed
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.

PLC restart under a live session leaves the device in LeaseHeld forever (LeaseOwner reads 0, driver keeps beating, connector never reconnects)

1 participant