-
Notifications
You must be signed in to change notification settings - Fork 1
Connecting
How the config tool reaches a NaviCore controller and keeps that link healthy. The Connect button opens a modal with three methods — a direct USB cable, a relay through a tethered WCB, or a port shared across browser tabs — and this page covers all three plus the watchdogs and auto‑reconnect that keep the UI honest.
This is the connection reference. For the full remote‑management walkthrough see Remote Management over WCB; for the credential fields see WCB Network; for the tool tour see Config Tool Guide.
Click Connect in the top bar. If you're already connected the same button reads Disconnect and clicking it tears the session down instead. Otherwise it opens the Connect modal, which offers exactly three methods:
| Method | Button | When to use it |
|---|---|---|
| Direct USB | 🔌 Connect via USB | A USB cable runs straight into the NaviCore's OTG port. |
| Via a WCB | 📡 Via a WCB | You're plugged into any USB‑tethered WCB on the mesh; it relays over ESP‑NOW to the controller. |
| Shared port | 🔗 Shared port (across tabs) | Another same‑origin tab (e.g. the WCB Wizard) already owns the WCB port — reuse it with no second cable. |
All three open the serial port at 115200 baud and end with the same handshake, so the live UI — SBUS monitor, channel grid, mode indicator — looks identical no matter which transport carried the data.
Pick 🔌 Connect via USB and choose the controller's serial port in the browser picker. The tool then runs an auto‑detecting handshake:
-
Open the port at
115200baud and start reading. -
Settle — wait ~4 s for the board to finish booting (
settleMs=4000). -
Probe direct — send
{"type":"PING"}up to 6 times, 500 ms apart, watching for aPONG. -
Auto‑fallback — if no direct
PONGarrives, the tool assumes the port is actually a tethered WCB, flips into Via WCB mode, and re‑pings the bridge. If neither transport answers it reverts to Direct so no stale Via‑WCB flag lingers. -
Load + monitor — send
GET_CONFIG, thenSTART_MONITOR, then push the current debug‑flag state to the board.
🚀 Tethering to a WCB "just works." Because Direct probes first and silently falls back to Via WCB, you can pick plain USB even when you're plugged into a WCB — the tool detects it and bridges automatically. The Via WCB checkbox in the top bar reflects whichever transport ended up live.
Every fresh connect starts in Direct‑USB mode: the Via‑WCB flag is forced false at the top of the handshake and is deliberately not restored from localStorage on page load (a stale true would silently strip WCB‑Network edits out of a Save).
Pick 📡 Via a WCB and choose the WCB's serial port. This path skips the direct probe and starts bridging immediately: outbound JSON is wrapped ;w20,<json> and the tethered WCB relays it over ESP‑NOW to the controller, which always lives at the fixed special‑peer slot 20 (RC_WCB_DEVICE_ID = 20). All inbound rc_* telemetry is filtered by id === 20.
A few things worth knowing about this mode:
- The top‑bar "Via WCB" checkbox reflects and can toggle the transport mid‑session, but it is per‑session — reset to Direct on every connect and disconnect, and never persisted.
-
The subscription gate. The controller only streams high‑rate channel data (
rc_ch) while it has seen inbound JSON within the last 15 s (WCB_SUBSCRIPTION_MS = 15000). To keep the live channel grid flowing during passive monitoring, the tool fires a silentPINGevery 10 s while Via WCB is active (this also fires in shared mode, where there is no local port). -
Config still works.
GET_CONFIG/SET_CONFIGare fragmented into ESP‑NOW‑sized packets and reassembled on the controller — see the Reference table and Remote Management over WCB.
For the one‑time network setup and what does / doesn't work over the bridge, see Remote Management over WCB and WCB Network.
A WebSerial port can be open in exactly one browsing context at a time — so the WCB Wizard and this config tool can't each hold their own cable to the same tethered WCB. Shared port solves that: one tab owns the physical port and mirrors its traffic to every other tab, so both tools talk to one board over one cable.
Requirements:
-
Chromium browser. Sharing needs
navigator.serial+navigator.locks+BroadcastChannel; without all three the tool alerts and aborts. -
Same‑origin tabs.
BroadcastChanneland Web Locks are origin‑scoped, so the Wizard and the config tool must be served from the same origin. Different origins never see each other and each opens its own port.
To join:
- Pick 🔗 Shared port (across tabs).
- If this is the first tab to share, choose the WCB port in the picker — this tab becomes the owner. If another tab already owns it, just cancel the picker — this tab joins as a follower and mirrors the owner's data.
- The tool waits up to ~4 s for the shared port to come up. Once it's open the tool enters Via WCB mode automatically (the shared port is a WCB gateway → relay
;w20), then runs the samePING→GET_CONFIG→START_MONITORhandshake. If no tab has opened the port yet it parks on "waiting for a tab to open the port."
Under the hood the shared port is managed by WcbSerialHub (config_tool/serial-hub.js). It shares one WebSerial port across same‑origin tabs using two browser primitives:
- A
BroadcastChannelnamedwcb-shared-serial— the cross‑tab bus. Followers post their outbound bytes onto it; the owner posts every byte it reads back onto it. - A single exclusive Web Lock named
wcb-shared-serial-owner. Every tab queues for it; the one tab holding it is the leader (owner) and opens the physical port. The rest are followers.
Failover, not live handoff. The port has one sticky owner: the tab that picked it keeps it. When that owner tab closes (or leaves the session), the browser hands the lock to the next queued tab, which promotes itself and re‑adopts the origin‑granted port with no user gesture — but only on a genuine failover (it must have actually seen a prior owner hold an open port, so it can never grab some unrelated port). Visibility‑driven handoff between foreground and background tabs is deliberately off, because re‑opening the port toggles DTR and would reboot the tethered WCB on every tab swap.
⚠️ The hub never asserts DTR — and that's intentional. Asserting DTR fires the WCB's one‑shot RC‑differentiator reset, rebooting it mid‑handshake. The WCB forwards UART↔USB without host DTR anyway, soassertDTRstaysfalse. Don't "fix" it.
Resilience. If the read stream ends or errors, the owner waits a 250 ms backoff and re‑acquires, giving up only after 6 consecutive empty sessions (the port is genuinely dead). Opening the port is retried 4× at 300 ms to ride over the just‑closed owner's OS‑handle release window.
Once connected, the controller streams a few message types. The rates are:
| Stream | Rate | Interval | Notes |
|---|---|---|---|
rc_hb (heartbeat) |
0.5 Hz | HB_INTERVAL_MS = 2000 |
Always on — lets the Wizard discover the RC even when nothing's monitoring. |
rc_ch (channels) |
20 Hz | CH_INTERVAL_MS = 50 |
Gated on an active subscriber; carries 24 channel values. Raised from the old 5 Hz. |
PWM_UPDATE (Direct USB) |
20 Hz | WS_MONITOR_INTERVAL_MS = 50 |
The direct‑cable equivalent of rc_ch. |
rc_ch is subscriber‑gated: it only broadcasts while inbound JSON has arrived within WCB_SUBSCRIPTION_MS = 15000 ms, so a Direct‑USB‑only network (which never pings over WCB) never starts it and no ESP‑NOW airtime is wasted. The tool's 10 s keep‑alive PING holds the subscription open while you passively watch the channel grid.
Two independent watchdogs keep the SBUS RECEIVER dot honest:
-
Universal staleness watchdog (
SBUS_STALE_MS = 4000). A 500 ms tick repaints the dot red as "No data — link idle" — with a visibly climbing age — whenever more than 4 s pass with no fresh data on any transport. Real data resets the clock; watchdog‑forced reds don't. It also re‑checks the instant the tab becomes visible again, which fixes the classic stale‑green after the laptop slept symptom. The 4 s window is sized to tolerate the slowest legitimate source (the 0.5 Hz heartbeat) plus one dropped beat. -
Via‑WCB silence watchdog (>1.5 s). While Via WCB is active, this flips the dot red if
rc_chgoes silent for more than 1500 ms — catching loss of the WCB link itself, distinct from SBUS‑side loss (which the RC reports directly in its heartbeat).
The SBUS RECEIVER dot, at a glance:
| Dot | Meaning |
|---|---|
| 🟢 Green | Receiving live SBUS. |
🔴 No signal / FAILSAFE
|
SBUS‑side loss — the receiver or transmitter dropped (see Failsafe and Signal Loss). |
🔴 No data — link idle
|
No telemetry at all for >4 s — the tab slept, the cable pulled, or the board rebooted. |
A link that dies on its own — host sleep/hibernate, an unplugged cable, a board reboot — is caught two ways: the navigator.serial disconnect event, and the read loop falling out while the port is still set. Both route to handleLinkLost(), which:
- Paints the SBUS dot stale‑red immediately (no waiting for the 4 s watchdog).
- Runs a bounded teardown.
- Arms a one‑shot heal (
_wantAutoReconnect = true) — this loss was not user‑initiated. - Shows "Connection lost — click Connect to resume" and, unless the tab is hidden, calls
tryAutoReconnect()(a hidden tab retries on wake instead).
Auto‑reconnect is deliberately conservative. It acts only when exactly one previously‑granted port exists and a board actually answers a
PONG— so it can never grab the wrong serial device. With zero or 2+ granted ports it does nothing and leaves it to you. A failed attempt disarms itself, and it only ever arms after an unintentional loss: every manual Disconnect clears the flag, so the tool never re‑opens a port you closed on purpose.
Channel calibration is Direct‑USB only. If Via WCB (or shared port, which forces Via WCB) is active, the Calibrate button alerts and refuses — you must Disconnect, uncheck Via WCB, plug USB into the RC's OTG port, Connect, then Calibrate. This is enforced both by an explicit block and by wiring: only the Direct‑USB PWM_UPDATE handler feeds the live calibration display; the rc_ch handler never does.
The block's on‑screen text still cites "5 Hz" for Via WCB and "~30 Hz" for Direct USB. Both figures are stale — both transports now run at 20 Hz — but the Direct‑USB‑only requirement itself still stands.
| Constant | Value | Where | Meaning |
|---|---|---|---|
RC_WCB_DEVICE_ID |
20 |
index.html |
Fixed special‑peer slot the bridge targets; inbound telemetry filtered by id === 20. |
| baud rate | 115200 |
index.html, serial-hub.js
|
Serial speed for all three transports. |
CH_INTERVAL_MS |
50 (20 Hz) |
rc_telemetry.h |
rc_ch channel‑stream cadence. |
HB_INTERVAL_MS |
2000 (0.5 Hz) |
rc_telemetry.h |
rc_hb heartbeat cadence (always on). |
WS_MONITOR_INTERVAL_MS |
50 (20 Hz) |
NaviCore.ino |
Direct‑USB PWM_UPDATE cadence. |
WCB_SUBSCRIPTION_MS |
15000 |
rc_telemetry.h |
rc_ch stops after this long with no inbound JSON. |
| keep‑alive PING | every 10000 ms |
index.html |
Renews the rc_ch subscription while Via WCB. |
SBUS_STALE_MS |
4000 |
index.html |
Universal "no data — link idle" threshold. |
| channel values | 24 |
rc_telemetry.h |
Size of every rc_ch payload (sbusValues[24]). |
channelName |
wcb-shared-serial |
serial-hub.js |
Cross‑tab BroadcastChannel bus. |
lockName |
wcb-shared-serial-owner |
serial-hub.js |
Exclusive Web Lock — the single "who owns the port" token. |
assertDTR |
false |
serial-hub.js |
Never asserted, so sharing can't reset the tethered WCB. |
FRAG_CHUNK_BYTES |
80 |
rc_telemetry.h, index.html
|
JSON bytes per fragment when a config crosses the ESP‑NOW cap. |
FRAG_MAX_PARTS |
192 (≈15 KB) |
rc_telemetry.h, index.html
|
Max fragments per reassembled payload. |
FRAG_TIMEOUT_MS |
5000 |
rc_telemetry.h |
A stalled reassembly session is dropped after this. |
NaviCore — Astromech Animation Controller · Home · WCB v3.2 / ESP32‑S3
Setup
- Setup Guide — start here
- PCB Assembly and BOM
- Hardware and Wiring
- Flashing the Firmware
- Transmitter Setup
- Connecting
- Config Tool Guide
- Maestro Setup
Reference
- Action Editor and Command Library
- Actions Reference
- WLED and HCR Audio
- Record and Replay
- Cheat Sheet
- Configuration Schema
- WCB Network
- Remote Management over WCB
- Serial JSON Protocol
- CLI Commands
- Failsafe and Signal Loss
- Glossary
Help