Skip to content

fix(canopen): restart the block-download request timer per confirmed segment, ignore heartbeats with the reserved bit 7 - #267

Merged
dborgards merged 3 commits into
mainfrom
fix/canopen-sdo-block-timer-heartbeat-bit7
Oct 3, 2026
Merged

dborgards merged 3 commits into
mainfrom
fix/canopen-sdo-block-timer-heartbeat-bit7

Conversation

@dborgards

Copy link
Copy Markdown
Owner

What does this change?

  • C12 (deep review § 2.8) — The block-download client restarted its request timer only when the server answered. A sub-block that takes longer to send than SdoTimeout (127 segments at 10 kbit/s is over a second against the 1 s default) therefore timed out before the ACK could even be asked for, and the timeout that fired during the batch made the client discard the healthy server's ACK. The timer now restarts at every confirmed segment (SendOrderedControlFrames gained an onFrameConfirmed callback); after the last segment it measures the wait for the ACK alone. SdoTimeout's documentation says so.
  • CANopen: a heartbeat with the reserved bit 7 set is reported as a heartbeat #266 — A heartbeat that sets the reserved bit 7 (a bystander's guarding reply, or a malformed frame) is no longer reported as HeartbeatReceived; CiA 301 §7.2.8.3.2.2 makes the bit reserved and always 0. It still counts as a sign of life and is still recorded for the NMT master, as before. This also covers 0x80, the case fix(canopen): report a short classic upload, refuse a long one, stop reporting reserved heartbeat states as boot-up #265 fixed for state 0 only.

Not in this PR, on purpose:

Closes #266.

Type of change

  • feat — new behaviour (minor release)
  • fix / perf — bug or performance fix (patch release)
  • docs / test / refactor / chore / ci — no release
  • Breaking change (! in the title, plus a BREAKING CHANGE: footer explaining the migration)

Checklist

  • dotnet build CanKit.Pro.sln -c Release succeeds (with -p:CI=true)
  • dotnet test CanKit.Pro.sln -c Release passes (net10.0; net48 only runs in CI)
  • Public API changes are documented with XML comments
  • New behaviour is covered by a test
  • The requirement or ADR this relates to is referenced (FR-CO-004, FR-CO-008)

Mutation checks: removing the per-segment restart fails the new C12 test (three segments confirmed 600 ms apart on a virtual clock against a 1 s timeout: no gap reaches the timeout, their sum does); removing the bit-7 condition fails the 0x80 and 0x84 rows.

🤖 Generated with Claude Code

…segment, ignore heartbeats with the reserved bit 7

C12: the block-download client restarted its request timer only when the server answered, so a
sub-block that took longer to send than SdoTimeout (127 segments at 10 kbit/s) timed out
before its ACK could be asked for, and the healthy server's ACK was then discarded. The timer
now restarts at every confirmed segment; after the last one it measures the wait for the ACK.

#266: a heartbeat that sets the reserved bit 7 (a bystander's guarding reply, or a malformed
frame) is no longer reported as HeartbeatReceived; it still counts as a sign of life.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes SDO block-download timeout semantics and heartbeat event filtering; both are protocol-edge fixes with targeted tests but affect transfer timing and observable heartbeat events.

Overview
Fixes two CANopen client bugs: block-download timeouts during long sub-blocks and false boot-up heartbeats when bit 7 is set.

Block download (C12): The SDO client timer used to measure only server silence after a sub-block was fully sent. A slow bus could exhaust SdoTimeout while segments were still transmitting, aborting a healthy transfer and discarding a later ACK. The timer now re-arms on each confirmed segment via a new onFrameConfirmed hook on SendOrderedControlFrames, with RearmBlockClient posted on the actor when the send is still live (IsLiveBlockSend). SdoTimeout XML docs describe this semantics.

Heartbeats (#266): HeartbeatReceived is raised only when bit 7 is clear and the state byte is valid—frames like 0x80/0x84 (guarding toggle or malformed) are no longer reported as boot-up/Initializing. They still refresh the heartbeat consumer and NMT slave tracking.

Tests cover cumulative segment timing vs timeout, late confirmation after timeout, and stricter heartbeat reporting expectations.

Reviewed by Cursor Bugbot for commit ba1f28d. Bugbot is set up for automated code reviews on this repo. Configure here.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-03T16:08:36.088559Z ba1f28d New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@codecov

codecov Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

…t block download; drop a redundant guard

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 650957c2f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/CanKit.Pro.CANopen/CanOpenNode.cs
… document the approximated-confirmation limit

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@dborgards
dborgards merged commit acfa6bd into main Oct 3, 2026
14 checks passed
@dborgards
dborgards deleted the fix/canopen-sdo-block-timer-heartbeat-bit7 branch October 3, 2026 16:16
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.

CANopen: a heartbeat with the reserved bit 7 set is reported as a heartbeat

1 participant