Skip to content

feat(kscan): support peripheral diagnostics via QueryPeripheral relay#112

Merged
cormoran merged 4 commits into
mainfrom
worktree-bridge-cse_01JHCKa9RXRq7oGxzpBqpcPj
Jul 12, 2026
Merged

feat(kscan): support peripheral diagnostics via QueryPeripheral relay#112
cormoran merged 4 commits into
mainfrom
worktree-bridge-cse_01JHCKa9RXRq7oGxzpBqpcPj

Conversation

@cormoran

Copy link
Copy Markdown
Owner

Summary

Implements the web UI side of zmk-feature-kscan-diagnostics PR #2 — peripheral kscan diagnostics over the split event-relay.

  • Proto: add QueryPeripheral (request) and PeripheralEvent (notification) messages; regenerate TS bindings
  • Hook (useKscanDiagnostics): loadPeripheralTopologies() discovers peripheral sources by broadcasting GetInfo via QueryPeripheral, then relays the full paginated topology fetch (GetInfo/GetLayout/GetDevice/GetGpioPins/GetPositionMap) for each responding peripheral, collecting PeripheralEvent notifications per page
  • Demo transport: KscanDiagnosticsHandler handles queryPeripheral (returns Ok, fires a PeripheralEvent notification 50ms later for a simulated 4×6 right-half peripheral at source=1); demo.ts wires the notify pipeline
  • UI (KscanDiagnosticsSection): calls loadPeripheralTopologies() on expand, shows a loading indicator, and renders each peripheral's wiring as a KscanKeyboardView labeled "Peripheral N"

Test plan

  • TypeScript compiles clean (npx tsc --noEmit)
  • demo-kscan-diagnostics tests all pass (16 tests, including 2 new queryPeripheral tests that verify Ok return and notification delivery)
  • Open the app in demo mode → expand "Key Switches" → confirm "Peripheral 1" wiring section appears alongside the central view
  • On real split hardware with zmk-feature-kscan-diagnostics PR Initial implementation #2 flashed: expand "Key Switches" → peripheral wiring loads within ~3s per page

🤖 Generated with Claude Code

cormoran and others added 3 commits July 12, 2026 23:01
Implements the web UI side of zmk-feature-kscan-diagnostics PR #2
(peripheral kscan diagnostics over the split event-relay).

Protocol:
- Add QueryPeripheral and PeripheralEvent messages to the proto and
  regenerate the TypeScript bindings.

Hook (useKscanDiagnostics):
- queryPeripheral() helper wraps any inner Request in a QueryPeripheral
  RPC and awaits matching PeripheralEvent notifications via
  zmkApp.onNotification, resolving on the target source's response or
  a configurable timeout.
- fetchPeripheralTopology(source) relays the full paginated topology
  fetch (GetInfo / GetLayout / GetDevice / GetGpioPins / GetPositionMap)
  for one peripheral source.
- loadPeripheralTopologies() broadcasts GetInfo for discovery, then
  fetches topology for every responding source.
- New return values: peripheralTopologies, isLoadingPeripheralTopologies,
  peripheralTopologyErrors, loadPeripheralTopologies.

Demo transport:
- KscanDiagnosticsHandler handles queryPeripheral: returns Ok and
  fires a PeripheralEvent notification (50 ms later) for a simulated
  4x6 right-half peripheral (source=1).
- demo.ts wires the kscan notify callback into the transport pipeline.

UI (KscanDiagnosticsSection):
- Calls loadPeripheralTopologies() alongside loadTopology() on expand.
- Shows a loading indicator while peripheral data is being fetched.
- Renders each peripheral's wiring as a KscanKeyboardView labeled
  "Peripheral N".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The baseKscan() helper in the section test was missing the new peripheral
props introduced in the previous commit, causing CI to throw
"Cannot read properties of undefined (reading 'entries')" when the
component tried to iterate peripheralTopologyErrors.

Also updates the expand test to assert that loadPeripheralTopologies is
called alongside loadTopology on first expand.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ReturnType<typeof useContext<typeof ZMKAppContext>> evaluates to
typeof ZMKAppContext (the Context object itself), not the value it holds.
This caused three TS errors in CI:
- onNotification does not exist on Context<UseZMKAppReturn | null>
- UseZMKAppReturn not assignable to Context<UseZMKAppReturn | null>

Fix: use a conditional type to extract the value type from the Context
and strip null, giving ZmkApp = UseZMKAppReturn as intended.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 12, 2026

Copy link
Copy Markdown

🚀 Cloudflare Workers Preview

Preview URL: https://87ecac6c-dya-studio-dev.cormoran707.workers.dev

Deployed from commit 2c6089f

… timeout

When QueryPeripheral is supported but no peripheral sends a PeripheralEvent
within the discovery window, set peripheralDiscoveryError and display a
SectionError in KscanDiagnosticsSection so the user knows the query timed out.
Firmware that lacks QueryPeripheral support still silently skips.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cormoran cormoran merged commit b1ff42f into main Jul 12, 2026
3 checks passed
@cormoran cormoran deleted the worktree-bridge-cse_01JHCKa9RXRq7oGxzpBqpcPj branch July 12, 2026 16:42
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.

1 participant