fix(docs): rename canopen CAN console to avoid apps/ basename collision - #753
Merged
Conversation
The docs build hosts every components/*/web/*.html by flattening them into docs/apps/ (cp -L in build_and_publish_docs.yml). #748 added a second can_console.html (components/canopen/web/) while components/twai/web/ already had one ("CAN Bus Console (slcan)"), so the copy failed: cp: will not overwrite just-created ../docs/apps/can_console.html with ../components/twai/web/can_console.html Rename the newer canopen bridge console to can_bridge_console.html (the twai console keeps its published apps/can_console.html URL) and update its three references: the example README link, the WebUSB landing_page_url baked into the firmware descriptor, and the canopen.rst doc link. The apps index globs the directory, so the renamed file is listed automatically. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
✅Static analysis result - no issues found! ✅ |
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The rename removes the apps/ basename collision and all updated links consistently point to the new hosted filename.
Pull request overview
This PR fixes a documentation-site build failure caused by two web apps sharing the same basename (can_console.html) when the docs workflow flattens components/*/web/*.html into docs/apps/. It resolves the collision by renaming the CANopen bridge console HTML file and updating the in-repo references to point at the new hosted URL.
Changes:
- Rename the CANopen-hosted console web app to
can_bridge_console.htmlto avoidapps/basename collisions. - Update documentation and example README link to the new
apps/can_bridge_console.htmlURL. - Update the WebUSB
landing_page_urlin the CAN bridge firmware example to match the new hosted page.
File summaries
| File | Description |
|---|---|
| doc/en/buses/canopen.rst | Updates the hosted web app link to the renamed CAN bridge console. |
| components/canopen/web/can_bridge_console.html | Adds the renamed single-file CAN bridge console web app under a unique basename. |
| components/canopen/can_bridge_example/README.md | Updates the README hyperlink to the new hosted console URL. |
| components/canopen/can_bridge_example/main/can_bridge_example.cpp | Updates the WebUSB landing page URL baked into the USB descriptor. |
Review details
- Files reviewed: 3/4 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
finger563
added a commit
that referenced
this pull request
Sep 2, 2026
…e logging - setStatusLine() now reflects the bus run state in the controls (only while connected): Apply + Start are disabled while the bus is running (SET_CONFIG is rejected by the firmware then) and Stop is disabled while stopped - matching the CAN bridge console, so Apply is not clickable with its "only while stopped" tooltip during a run. - onIncoming() logged every non-SDO CAN frame to the DOM unconditionally; on a live CANopen bus (heartbeats / PDOs / EMCY) that floods the DOM and freezes the UI. Gate it behind a new "log bus frames" toggle (default off), mirroring the SDO-frame toggle. - Update the can_console.html references to can_bridge_console.html (renamed on main in #753). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
finger563
added a commit
that referenced
this pull request
Sep 2, 2026
… bridge) (#752) * feat(canopen): add DS402 drive panel web app (in-browser SDO over the CAN bridge) A single-file, offline, dependency-free browser front-end that commissions a CANopen CiA 402 (DS402) drive through the existing USB<->CAN bridge (can_bridge_example). It reuses the CAN console's transport + stream_frame framing to move raw CAN frames and layers all CANopen/DS402 logic in the browser ("architecture option A") - the firmware stays a dumb raw-CAN pipe, no firmware change needed. Includes: - An in-browser CANopen SDO client: expedited + segmented upload (read) and download (write) on the default SDO channel (0x600/0x580 + nodeId), with abort decoding and one-transaction-at-a-time serialization. - A DS402 panel: statusword (0x6041) -> power-drive-system state decode, controlword (0x6040) command buttons + enable sequence / quick-stop / fault-reset, mode of operation (0x6060/0x6061), target and actual velocity/position/torque, and an opt-in live poll. - Node identity (0x1000/0x1008/0x1018) and NMT controls. - A generic object-dictionary panel to read/write ANY index:subindex with a chosen data type (u8..i32/string/raw hex), for vendor-specific objects. Because it drives the node over SDO (not cyclic PDOs) it is a commissioning / bring-up tool; the bus must be in Normal mode so the bridge ACKs the node. The apps index auto-lists it from its <title>/<meta description>; canopen.rst links it next to the CAN console. Verified: node --check clean, and a runtime test of the SDO expedited/segmented up/download codec + DS402 state decode against a mock CANopen server (13/13 round-trips). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(canopen): escape invalid < in ds402_panel meta description The <meta name="description"> content had a literal "USB<->CAN"; an unescaped < makes the tag invalid HTML. Reword to "USB-to-CAN" (same fix as can_console). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(canopen): DS402 panel review - SDO channel cleanup, toggle check, poll re-entrancy Address the review on the DS402 web app: - Disconnect / link-loss now abort any outstanding SDO transaction: new abortSdo() clears the waiter timer, rejects its pending Promise, and resets sdoTxnActive. Without this a link drop mid-SDO left the channel wedged ("SDO channel busy" / "another SDO transaction in progress") after reconnect and a Promise pending until timeout. Called from disconnect() and onLinkLost(). - Segmented SDO download now validates the server echoed the expected toggle bit (like the upload path) and throws on mismatch, so a desynced channel cannot silently corrupt a write. - refreshDs402() is guarded by a refreshInFlight flag around the whole multi-read sequence: sdoTxnActive is released between individual reads, so a poll tick or manual refresh could otherwise start a second refresh mid-sequence and interleave reads. The manual button no longer needs its own sdoTxnActive check. - Clarified the NMT comment: the UI always targets the selected node (1-127, shared with the SDO client); it does not expose CANopen node-0 broadcast. Verified: node --check clean, and the SDO codec round-trip test still passes (segmented upload + download with the new toggle check). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(canopen): DS402 panel review - run-state buttons + gated bus-frame logging - setStatusLine() now reflects the bus run state in the controls (only while connected): Apply + Start are disabled while the bus is running (SET_CONFIG is rejected by the firmware then) and Stop is disabled while stopped - matching the CAN bridge console, so Apply is not clickable with its "only while stopped" tooltip during a run. - onIncoming() logged every non-SDO CAN frame to the DOM unconditionally; on a live CANopen bus (heartbeats / PDOs / EMCY) that floods the DOM and freezes the UI. Gate it behind a new "log bus frames" toggle (default off), mirroring the SDO-frame toggle. - Update the can_console.html references to can_bridge_console.html (renamed on main in #753). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(canopen): DS402 panel review round 3 - SDO robustness + real enable sequence Address the SDO/DS402 correctness review on the DS402 web app: - SDO response matching: sdoDeliver() now requires an EXACT 8-byte standard (non-RTR, non-extended) frame and, for phases whose response echoes the multiplexer (expedited/initiate/abort), that index:subindex matches the pending transfer. A late response for an earlier index can no longer complete the next transaction with stale data / a false ack, and stray bus traffic on the response COB-ID is no longer zero-padded into a fake response. Segment phases carry no multiplexer and stay matched by phase + toggle. - Node snapshot: withSdo() captures the node id ONCE and threads it through the whole transaction, so a node-field change mid segmented transfer cannot send the initiate and later segments to different servers. - Segmented upload rejects a short transfer (declared size > delivered bytes) instead of returning truncated data as a successful read. - Scalar writes are range-validated before encoding (u8=-1 / i16=65535 / oversized 32-bit no longer silently wrap); scalar reads reject an undersized object instead of zero-extending it into a valid-looking value. Zero-length writes are rejected (no valid SDO expedited encoding). Target/controlword handlers only log the value as sent when the write actually succeeded. - The "Enable operation" button now performs the real state-aware enable sequence (Shutdown -> Switch On -> Enable Operation, with fault reset and quick-stop exit), polling the statusword between transitions - it no longer just writes 0x000F, which fails from Switch-on-disabled. Relabeled "Enable sequence". Verified: node --check clean + a runtime test of the range/undersized/truncation/ empty-write/segmented-codec logic (15/15). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(canopen): DS402 panel review round 4 - node pinning, cancellation, address bounds Address the remaining SDO/DS402 robustness review: - Node pinning across multi-transaction actions: withSdo() accepts an explicit node (default = the field value). The enable sequence and the identity read now snapshot the node ONCE and pass it to every readObject/sdoDownload, so editing the node field mid-action can no longer read state from one drive and command another. The enable sequence also locks the node field while it runs. - Enable sequence is cancellable: Quick stop sets a cancel flag (and waits for the sequence to release the SDO channel) before issuing quick stop, checked after every awaited SDO op - so quick stop can no longer be undone by the sequence driving the state machine back to Operation enabled. - Fault reset performs both controlword writes (clear -> 0x80) DIRECTLY instead of via sendControlword, whose trailing refreshDs402() would grab the SDO channel and fail the second write, so bit 7 now gets its rising edge. - Object address validation: sdoUpload/sdoDownload reject index outside 0x0000..0xFFFF and subindex outside 0..255 before packing the low bits, so a typo like hex 16040 (0x16040) can no longer be silently sent as 0x6040. - Segmented uploads are bounded (SDO_MAX_TRANSFER = 64 KiB) for both a declared oversized total and a node that never sets the last-segment bit; on overflow we send a client SDO abort and fail, so a faulty node cannot grow browser memory. - Serial read loop treats a clean EOF while still reading as a link failure (not a silent normal return), so a port that closes under us tears the UI down instead of leaving it "Connected". Normal cancellation during close() is unaffected. - Mode-of-operation set logs success only inside the successful write path (no more success message after an SDO abort/timeout/busy error). Verified: node --check clean + runtime tests of the address-validation and upload-bound logic. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(canopen): DS402 panel self-review - serialize SDO via a queue + related fixes A focused self-review (plus an independent adversarial pass) surfaced one real bug and several hardening items: - HIGH: Quick stop could be silently dropped. The enable sequence's finally ran refreshDs402() which re-acquired the SDO channel exactly as the cancelled sequence handed control back to Quick stop, so the quick-stop write failed with "another SDO transaction in progress" and was never sent. Root cause: the SDO channel failed fast on contention. Replace the fail-fast mutex with a QUEUE (withSdo enqueues; pumpSdoQueue runs one transaction at a time in FIFO order), so a poll tick, the enable sequence and manual commands serialize instead of the loser being dropped. abortSdo() now also drains the queue on disconnect. Additionally the enable sequence skips its trailing refresh when cancelled, so the quick-stop write runs immediately. - Manual commands issued during a live-poll burst (or a trailing refresh) are no longer dropped with a "busy" error - they queue and run in order. - The enable sequence now locks the competing command controls (controlword / mode / target / OD-write / NMT / node field) while it runs; Quick stop stays enabled (it cancels the sequence) and reads stay enabled. - currentNode() rejects an out-of-range node id (1..127) instead of silently clamping to 1, so a command / identity read can no longer target a different drive than the field shows. The enable-sequence and identity handlers surface the error. - disconnect()/onLinkLost() set the sequence cancel flag (matching the comment) and the sequence's finally no longer refreshes after a disconnect (was spamming "not connected"). - OD read shows scalar hex at the object's own width (i16 -1 -> 0xffff, not 0xffffffff). Connecting with Live poll pre-ticked now actually starts polling. Verified: node --check clean + a runtime test of the queue (serialization, FIFO order, abort-drain), currentNode validation, and hex width (13/13). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The docs build (
build_and_publish_docs.yml) hosts everycomponents/*/web/*.htmlby flattening them intodocs/apps/withcp -L. #748 addedcomponents/canopen/web/can_console.html, butcomponents/twai/web/can_console.html(“CAN Bus Console (slcan)”) already existed — so the copy collides and fails the docs job:Fix
Rename the newer canopen bridge console →
can_bridge_console.html(the twai console keeps its incumbentapps/can_console.htmlURL). Updated its three references:README.mdlinklanding_page_urlbaked into the firmware descriptor (can_bridge_example.cpp)canopen.rstdoc linkThe apps index globs the directory, so the renamed file is listed automatically. Verified there are no remaining duplicate basenames under
components/*/web/.🤖 Generated with Claude Code