Skip to content

led-bridge: manage the serial connection lifecycle (reconnect on drop)#16

Merged
Julie Krasnick (jckras) merged 1 commit into
mainfrom
led-bridge-connection-lifecycle
Jun 5, 2026
Merged

led-bridge: manage the serial connection lifecycle (reconnect on drop)#16
Julie Krasnick (jckras) merged 1 commit into
mainfrom
led-bridge-connection-lifecycle

Conversation

@jckras

Copy link
Copy Markdown
Contributor

Summary

Makes led-bridge resilient to the serial device coming and going. Previously it opened the serial port once at construction and held that handle forever — so if the ESP ever reset or dropped off USB (a reflash, a USB blip, a loose connection), led-bridge kept writing to a now-dead handle. Every write failed with EIO, last_state froze at the last successfully-written value, and it stayed stuck until viam-server was restarted. It also failed to build at all if the device wasn't present at startup.

This reworks the connection as a managed lifecycle: the port can be absent, drop, and return, and led-bridge rides all of it.

What changed (all in resources/led-bridge/led-bridge.go)

  • One path for connect & reconnectopenLocked() opens the port on demand; a nil port simply means "disconnected." First-connect, reconnect-after-drop, and absent-at-boot all flow through the same code, so there's no special-case "reopen" branch to keep in sync.
  • Self-heals on drop — a failed write closes the stale handle, so the next write reconnects to the live device. The "stuck forever on the last state" failure is gone.
  • Reconnect backoff — redials are throttled (reconnectBackoff, 2s) so an absent device isn't dialed every tick. Important because opening the port resets the ESP — unthrottled retries would reboot-loop it.
  • Build-safe — construction no longer fails if the device is missing. led-bridge comes up connected: false, logs it, and connects when the device appears (instead of the whole resource going unavailable).
  • ObservabilityStatus() now reports a connected flag alongside the existing write-health counters.

No new goroutine: reconnection rides the existing poll loop, which is correct for a write-driven service (a disconnect only matters at the next write, which is exactly when reconnection triggers).

Notes

Test plan

  • go build ./... and go vet pass
  • Unplug/replug the ESP while running → led-bridge logs reconnect and messages_sent resumes, no viam-server restart needed
  • Reflash the ESP while running → led-bridge recovers on its own within ~2s
  • Start viam-server with the ESP unplugged → led-bridge builds, reports connected: false, then connects when plugged in
  • Status() shows connected: true and last_state tracking voice-command during normal operation

Treat the serial port as a connection that can be absent, drop, and return,
rather than a permanent handle opened once at construction:

- Lazy/ensured connect: openLocked() opens the port on demand and is the
  single path for both first connect and reconnect (nil port = disconnected).
- Drop-on-failure: a failed write closes the handle so the next write
  reconnects to the live device — fixes the case where the device reset and
  led-bridge kept writing to a stale handle forever (frozen on the last state).
- Reconnect backoff: throttle redials so an absent device isn't dialed every
  tick (opening the port resets the ESP, which would otherwise reboot-loop).
- Build-safe: construction no longer fails if the device is absent; it comes
  up disconnected, logs it, and connects when the device appears.
- Status() reports a `connected` flag alongside the existing write health.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@jckras
Julie Krasnick (jckras) merged commit 60ae6b3 into main Jun 5, 2026
3 checks passed
@jckras
Julie Krasnick (jckras) deleted the led-bridge-connection-lifecycle branch June 5, 2026 19:49
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