-
Notifications
You must be signed in to change notification settings - Fork 3
Connecting the Dongle
The dongle is the host's interface to the rest of the system. It's a small USB-C-attached box that contains:
- An ESP32-S2 microcontroller running
os4_dongle.ino. - An nRF24L01+ radio for the 2.4 GHz custom protocol.
- A 433 MHz transmitter for legacy Bilusocn one-way receivers.
- Three switches the operator interacts with: start/stop, arm, and manual fire.
- 7 NeoPixel status LEDs.
The host computer talks to the dongle exclusively over USB-CDC at 115200 8N1.
There's a chain of three components:
[ Daemon (in Docker) ]
│ TCP to host.docker.internal:9000
▼
[ tcp_serial_bridge (Python, on host) ]
│ pyserial @ 115200 8N1
▼
[ Dongle USB-CDC serial ]
Why the bridge? Docker Desktop on macOS and Windows runs in a VM that doesn't get easy access to the host's USB devices. The bridge runs natively on the host, holds the serial connection open, and exposes it as TCP. The daemon (which lives in the container) connects via TCP. On Linux you could in principle skip the bridge and pass /dev/ttyACM* straight into the container with a devices: mapping, but the bridge keeps the architecture identical across all three OSes — so we use it everywhere.
| OS | Run this | Typical answer |
|---|---|---|
| macOS | ls /dev/tty.usbmodem* |
/dev/tty.usbmodem01 (or /dev/tty.usbmodem1101 etc.) |
| Linux | ls /dev/ttyACM* /dev/ttyUSB* |
/dev/ttyACM0 |
Pi (installed via install.sh) |
ls -l /dev/byh_dongle |
/dev/byh_dongle -> ttyACM0 |
| Windows | Device Manager → Ports (COM & LPT) |
COM5 (varies) |
Set the result as system.dongle_port in host/config/systemcfg.json:
{
"host_version": 0.08,
"system": {
"dongle_port": "/dev/tty.usbmodem01",
"dongle_baud": 115200,
"dongle_protocol": "BKYD_TS_HYBRID"
}
}dongle_baud is fixed at 115200 by the dongle hardware — do not change it.
On a Pi installed with host/run/pi/install.sh, the installer drops a udev rule that creates the stable symlink /dev/byh_dongle pointing at whatever /dev/ttyACM* slot the dongle landed on. The installer also auto-fills this path into systemcfg.json during install, so a fresh Pi just works:
"dongle_port": "/dev/byh_dongle"Reasons to prefer the symlink over the raw /dev/ttyACM* path:
- It survives
/dev/ttyACM0 ↔ /dev/ttyACM1order swaps when the dongle re-enumerates after a reboot or reflash. -
flash_dongle.pyuses it as its top-priority port-discovery candidate — so the same script that boots the host can also flash the dongle without configuration drift. -
update_dongle.sh(the Pi's one-button dongle-firmware updater) assumes it.
After running the platform's launcher (host/run/pi/start.sh, host/run/osx/start.sh, or host/run/windows/start.bat), the bridge log will print:
Serial connected: /dev/tty.usbmodem01 at 115200 baud
TCP server listening on 0.0.0.0:9000
Accepted connection from ('192.168.65.2', 53114)
In the web UI's status bar (bottom of every page), you should see:
- Link light: green ("WS connected, daemon fresh").
- Daemon light: green.
-
Dongle: shows the active protocol (e.g.
BKYD_TS_HYBRID), a small TX activity pulse, and the dongle's command-queue gauge.
If Dongle is yellow ("Silent") for more than ~10 s after start, the daemon is connected to the bridge but isn't getting per-second status frames back from the dongle. Likely causes:
- Wrong serial port in
systemcfg.json. - Dongle firmware not flashed (USB enumerates but no JSON comes back). See Flashing a Dongle.
- Bad cable. Try another USB-C cable — some are charging-only and don't carry data.
The bridge automatically reopens the serial port if the dongle reboots (its hardware watchdog firing during a hostile RF link, or you unplug/replug). Backoff goes from 1 s to 5 s. You'll see lines like Serial auto-reconnected: ... once it comes back.
The dongle's hardware watchdog has a 10-second timeout (see Dongle firmware → Watchdog). If the daemon stops getting status frames for >10 s during normal operation, that's the most likely culprit — the bridge will silently reconnect.
If you have multiple USB-CDC devices and the order can shift across reboots, you can pin a name with udev. On a Pi this is automatic via install.sh — you'll already have /dev/byh_dongle. For other Linux hosts, save as /etc/udev/rules.d/99-byh-dongle.rules:
SUBSYSTEM=="tty", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="80??", \
SYMLINK+="byh_dongle"
(Use lsusb to confirm the vendor/product IDs for your dongle.) Then:
sudo udevadm control --reload && sudo udevadm triggerSet dongle_port: "/dev/byh_dongle" in systemcfg.json and you'll be immune to enumeration-order changes.
These are read by the dongle firmware, encoded into a JSON gpio_status message every state change, and sent up to the daemon. The daemon then enforces interlocks (you can't load a show with the start switch up; you can't fire manually without arm + start + manual fire all engaged).
| Switch | UP / open (HIGH) | DOWN / closed (LOW) |
|---|---|---|
| Start / Stop | STOP — show paused / cannot start | START — show schedule running |
| Arm | DISARMED — fire commands rejected | ARMED — fire commands allowed |
| Manual fire | OFF — show mode | ON — manual cue firing only |
The UI shows each switch's current state in the status bar and gates its action buttons accordingly. See Show lifecycle for how these interact during a show.
Two options:
- Physical: unplug and replug. The bridge will auto-reconnect within a couple of seconds.
-
From the UI: click the Restart button next to "Dongle" in the status bar — this re-sends the
select_serialconfiguration command to the bridge, which closes and reopens the port.
You should not need to do this routinely. The dongle is intended to stay up across days.
Getting started
- Overview
- Desktop installers (macOS / Windows)
- macOS
- Linux
- Windows
- Production vs Development
- Connecting the dongle
- Flash a receiver
- Flash a dongle
- OTA flashing
Raspberry Pi
System overview
Subsystems
Hardware
- Receiver firmware
- Dongle firmware
- RF protocol
- Contributor Portal — BOMs, schematics, and board resources
UI walkthrough
Reference
Downloads
- Firmware
- Installers
Module Build & User Guides
- Cue
- Receiver
- Dongle