Skip to content

refactor(bldc_haptics): standard OTA / coredump / haptics modules + discovery - #768

Open
finger563 wants to merge 8 commits into
mainfrom
feat/haptics-advertise
Open

refactor(bldc_haptics): standard OTA / coredump / haptics modules + discovery#768
finger563 wants to merge 8 commits into
mainfrom
feat/haptics-advertise

Conversation

@finger563

@finger563 finger563 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Modernize the bldc_haptics example: standard OTA / coredump / haptics modules + discovery

Brings the bldc_haptics example fully in line with the other framed-USB examples
and wires it into dispatcher capability discovery (#767).

1. Migrate to espp::Dispatcher + advertise

The example drove a raw stream_frame::StreamParser with a manual
frame.module == kModule filter. It now routes through an espp::Dispatcher and
advertises itself for capability discovery, so the browser Device Hub lists it.

2. Split OTA / core dump onto their own modules

Instead of multiplexing an OTA subset + a crash-report command into the haptics
protocol (module 2), the example now runs the standard protocols on their own
dispatcher modules:

  • OTA → module 0 — a handler speaking the espp ota_stream protocol, reusing
    the existing espp::Ota. The plain ota_console.html updates this device.
  • Core dump → module 4 — an espp::CoreDump + espp::CoreDumpService (full
    download/erase). The dump is no longer erased at boot (the console downloads +
    erases it); the boot summary log stays. coredump_console.html works against it.
  • Haptics stays module 2 — commands + telemetry only.

All three are registered + advertised (OTA / Core Dump / BLDC Haptics), so the hub
discovers a device with three modules and links to each dedicated console.

3. Drop the inline OTA / crash UI from the haptics console

webapp/index.html loses its Firmware-update panel + crash fetch (and the
associated protocol types / plumbing) — the hub + dedicated consoles cover it.
PROTOCOL.md / README updated accordingly.

Verified

  • Firmware builds clean, manager-off, on IDF v6.0.1 (esp32s3).
  • Haptics web console passes node --check with no dangling references.

🤖 Generated with Claude Code

The bldc_haptics example was the one framed-USB example still driving a raw
stream_frame::StreamParser (with a manual `frame.module == kModule` filter)
instead of an espp::Dispatcher, so it could not advertise itself to the browser
Device Hub. Migrate it and advertise.

- Replace the raw parser + module filter with an espp::Dispatcher: register the
  haptics protocol on module 2 (proto::kModule) with a handler that gates on
  !is_reply() (unchanged semantics), and feed()/reset() the dispatcher from the
  USB RX worker. The example's OTA subset + haptics commands all ride module 2's
  message types, so this stays a single-module protocol.
- Advertise it: register_module(..., ModuleInfo{"BLDC Haptics",
  "haptics_console.html", ...}), set_device_info(usb_cfg.product), and
  serve_discovery() routed through the existing tx_mutex-guarded usb_send.
- Add the dispatcher component to the example's EXTRA_COMPONENT_DIRS and to the
  main component's REQUIRES.

Also complete the dispatcher README module-id table (add 2 = BLDC haptics,
6 = MCP266).

This finishes the set: every framed-USB example (ota, coredump, can_bridge,
mcp266, haptics) now advertises over the reserved discovery module 0xFF.

Verified: builds clean, manager-off, on IDF v6.0.1 (esp32s3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 4, 2026 17:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Pull request overview

Migrates the bldc_haptics framed-USB example from a raw StreamParser + manual module filtering to espp::Dispatcher, and enables capability discovery advertising so it can be listed by the browser Device Hub.

Changes:

  • Replace StreamParser parsing/filtering with espp::Dispatcher routing on module 2.
  • Advertise the module and serve discovery responses via the existing USB TX path.
  • Wire the new component dependency in CMake and update dispatcher module-id documentation.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
components/dispatcher/README.md Adds missing module-id entries for BLDC haptics (2) and MCP266 (6).
components/bldc_haptics/example/main/bldc_haptics_example.cpp Switches to Dispatcher, registers/advertises module 2, and routes discovery replies through USB send.
components/bldc_haptics/example/main/CMakeLists.txt Adds dispatcher to the example main component requirements.
components/bldc_haptics/example/CMakeLists.txt Adds dispatcher to EXTRA_COMPONENT_DIRS for the example build.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread components/bldc_haptics/example/main/bldc_haptics_example.cpp
Comment on lines +699 to +701
// same tx_mutex-guarded usb_send as every other frame.
dispatcher.serve_discovery(
[&](std::span<const uint8_t> f) { usb_send(std::vector<uint8_t>(f.begin(), f.end())); });
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

✅Static analysis result - no issues found! ✅

finger563 and others added 2 commits September 4, 2026 13:29
Bring the haptics example in line with the other framed-USB examples: instead of
multiplexing an OTA subset + a crash-report command into the haptics protocol
(module 2), run the STANDARD protocols on their own dispatcher modules so the
device is discovered as three modules and the plain ota / coredump web consoles
work against it directly.

- OTA -> module 0: a handler speaking the espp ota_stream protocol (Begin/Data/
  Finish/Abort -> make_ok/make_error), reusing the existing espp::Ota. Removed
  the Ota* message types from haptics_usb_protocol.hpp + the cases from the
  haptics handler.
- Core dump -> module 4: an espp::CoreDump + espp::CoreDumpService (full download/
  erase protocol). The dump is no longer erased at boot (the coredump console
  downloads + erases it); the boot-time summary log stays. Removed GetCrash/Crash
  from the haptics protocol + the raw esp_core_dump usage.
- Haptics stays module 2 (commands + telemetry only).
- Register + advertise all three (OTA / Core Dump / BLDC Haptics); add the
  coredump component to the example deps.

Web console cleanup (drop the now-moved OTA + crash UI) follows in a separate
commit. Verified: builds clean, manager-off, IDF v6.0.1 (esp32s3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Now that OTA is dispatcher module 0 and core dump is module 4 (not multiplexed
into the haptics protocol), remove their UI from the haptics console: the device
hub discovers all three modules and links to the standard ota_console /
coredump_console, which speak those modules directly.

- webapp/index.html: remove the Firmware-update (OTA) panel + upload flow, the
  GET_CRASH fetch, the OTA/crash message types + progress plumbing, and the now-
  unused constants/CSS. Haptics controls + telemetry are unchanged.
- PROTOCOL.md: module 2 now documents haptics only; note OTA=module 0 /
  coredump=module 4 as separate standard protocols.
- README.md: point firmware update / crash inspection at the ota / coredump
  consoles (and the device hub) instead of an inline panel.

Web app passes node --check; no dangling references remain.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@finger563 finger563 changed the title feat(bldc_haptics): advertise for dispatcher capability discovery refactor(bldc_haptics): standard OTA / coredump / haptics modules + discovery Sep 4, 2026
finger563 and others added 2 commits September 4, 2026 16:14
…e checks

The haptics console refactor left a call to updateUploadUI() (removed along
with the OTA upload panel) inside setConnectedUI(). Since setConnectedUI runs
early in connect(), it threw a ReferenceError before the RX pump and the init
handshake started -- the page connected (dial showed "waiting for telemetry")
but never sent GET_INFO / SET_STREAMING, so no telemetry ever arrived. Drop
the stale call.

Also harden the ota / coredump / haptics WebUSB consoles:
- default device filter is now VID-only (any espp device, VID 0x1209) instead
  of VID+PID, so a multi-module device is offered in every console; "show all
  devices" uses {filters:[{}]} (ota_console's invalid acceptAllDevices fixed).
- on connect each console queries the reserved dispatcher discovery module
  (0xFF ListModules, reusing Dispatcher::describe's TLV) and warns if its own
  module is not advertised, then continues anyway; firmware without the
  discovery module simply never replies and is tolerated silently.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The OTA cases that used this std::error_code moved to handle_ota_frame (which
has its own), leaving handle_frame's `ec` unused -- cppcheck's unusedVariable
failed the static-analysis gate. Remove it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The cross-layer firmware, protocol, discovery, and console changes warrant final human review despite only minor findings.

Review details

Suppressed comments (3)

components/bldc_haptics/example/PROTOCOL.md:47

  • The protocol no longer has two unsolicited frame kinds after OTA_PROGRESS was removed; only telemetry remains. Please make this singular so implementers are not told to expect a second undocumented event.
sending the next. Two device-to-host frame kinds may arrive *unsolicited* and
must be tolerated at any time:

- `TELEMETRY (0x93)` — when streaming is enabled.

components/bldc_haptics/example/webapp/index.html:513

  • The adjacent comment still says the default matches this example's exact VID/PID, but the changed filter now matches every PID under the espp VID; the checkbox broadens that further to all USB devices. Update the comment to match the selector behavior.
          : { filters: [{ vendorId: DEFAULT_VID }] };  // any espp device (VID 0x1209), any PID

components/coredump/web/coredump_console.html:617

  • The adjacent comment still describes an exact example VID/PID default and says the checkbox only adds other espp devices. The new selector already includes every espp PID by default, while the checkbox includes all USB vendors, so the documentation is now misleading.
        : { filters: [{ vendorId: DEFAULT_VID }] };  // any espp device (VID 0x1209), any PID
  • Files reviewed: 10/10 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread components/bldc_haptics/example/main/bldc_haptics_example.cpp Outdated
Comment thread components/bldc_haptics/example/main/haptics_usb_protocol.hpp Outdated
finger563 and others added 3 commits September 4, 2026 17:00
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Addresses the review note on the discovery reply path: usb_send took a
`const std::vector<uint8_t>&`, so the serve_discovery and CoreDumpService reply
callbacks (which receive a std::span) had to copy their bytes into a fresh
vector on every reply. usb_send now takes `std::span<const uint8_t>` and calls
write_vendor (which already accepts a span) directly:
- the vector-building callers (proto::build / ota_stream make_*) still work via
  the implicit vector->span conversion, no copy;
- the discovery and coredump callbacks forward their span with no allocation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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