Skip to content

Lights 1: fixtures foundation, Worker sync, BLE link and pairing (#208) - #264

Merged
bubulux merged 2 commits into
mainfrom
feat/208-lights-foundation
Oct 23, 2026
Merged

bubulux merged 2 commits into
mainfrom
feat/208-lights-foundation

Conversation

@bubulux

@bubulux bubulux commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

Closes #208. Part of the Lights epic #206.

Everything the lights need that does not depend on a fixture protocol: shared kinds, the server side, the Bluetooth library, the connection manager, the synced list and the screens. No driver yet, so nothing can be controlled; a light's screen says so. The first driver is #209 (NEEWER), which needs the snoop log from #207.

What changed

Shared (packages/vocab/src/lighting.ts): FIXTURE_KINDS (FS230B, FS300B, PS099S, Aputure MC) with transport, driver id and capabilities; CURVES; LightState; address and limit helpers.

Worker

  • Migration 0027_fixtures.sql (additive): fixtures, mesh_networks. No key material.
  • src/fixtures.ts: GET/PUT/DELETE /api/fixtures[/:id] and /api/mesh-networks[/:id], rigs' upsert and workspace rules. Strict checks: known kind, address format, mesh fields only on a mesh kind and only with a network of the same workspace (another workspace's network answers 400 like a missing one), one unicast address per network (409). Deleting a network leaves its fixtures, unprovisioned.
  • Tenancy kinds fixture, mesh_network; all six routes in the tenancy map, a fixture and network in the test world, four reference cases; fixtures.test.ts for the rules.

Phone

  • @sfourdrinier/react-native-ble-plx 3.9.3 (pinned; published 2026-07-28, MIT, no install script) with its config plugin: no background mode, scanning declared as never used for location. Needs a new dev build.
  • src/ble/link.ts is the only user of the library; src/ble/permissions.ts asks for Nearby devices (Android 12+) or location (older).
  • src/fixtures/: driver seams (Link, Driver, Session), queue.ts (one write at a time per connection, newer command of the same op replaces a queued one and moves to the back), hubCore.ts (leases per screen or sequence, 2 s grace, backoff 1/2/5/15/30 s, close in the background and reopen on return), registry.ts (empty driver table, model guess from the scan), library.ts (synced like rigs, also on every flush).
  • Setup → Lights: list, Add light (10 s scan, likely fixtures first, already-paired greyed out, confirm the model, name), Edit light, and a light's screen holding its connection open.

Decisions

  • Coalescing moves the newer command to the back of the queue, so "power off" after a colour change is still sent last. Tests cover it.
  • The connection manager has no React Native in it, so it is tested with a fake link and fake timers.
  • The model guess is only a suggestion: NEEWER names vary by firmware, so the person pairing always confirms. A test caught a serial number containing "300" being taken for an FS300B.
  • FS230B/FS300B have no green/magenta in their capabilities until the snoop log shows whether the app sends it.
  • Tap on a light opens it; long press or its Edit button edits it.
  • The phone storage keys for mesh networks and sequence numbers are not added yet (the issue listed them): they belong to Lights 4: Bluetooth Mesh client stack in TypeScript #211/Lights 5: mesh provisioning and network keys #212, which will use them.
  • The mobile test script now runs src/**/*.test.ts, so tests in subfolders run.

Checked

  • make check: lint, typecheck, all unit and route tests (121 in fixtures + tenancy), build dry runs, Expo export. Green.
  • expo prebuild once locally: the manifest keeps the app's unconditional location permission; the plugin's extra location entries are capped at Android 11. The generated folder was removed.
  • Local Worker smoke test with curl: network, MC on it, refused FS230B with mesh fields, list, network delete leaves the fixture unprovisioned, delete.

Not clicked through

Nothing ran on a phone: the permission prompt, scanning, pairing, the list sync and GPS still working after the manifest change. Listed in docs/known-issues.md. Migration 0027 is not applied remotely.

🤖 Generated with Claude Code

bubulux and others added 2 commits October 23, 2026 16:11
Shared fixture kinds and capabilities in packages/vocab/src/lighting.ts.
Migration 0027 adds fixtures and mesh_networks (no key material);
/api/fixtures and /api/mesh-networks follow the rigs' upsert and
workspace rules, with strict kind, address and mesh checks. Both are in
the tenancy map and the test world; fixtures.test.ts covers the rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…one (#208)

Adds the Bluetooth library (@sfourdrinier/react-native-ble-plx 3.9.3,
config plugin with scanning marked as never used for location) behind
src/ble/link.ts. src/fixtures holds the driver seams (Link, Driver,
Session), a per-link command queue with latest-wins coalescing, and a
React-Native-free connection manager with leases, grace period,
backoff and background suspend, all unit-tested with a fake link and
fake timers. The fixture list syncs like the rigs and on every flush.
Setup gains Lights: list, scan and pair, edit, and a light's screen
showing its connection. No driver yet, so nothing can be controlled.

Docs: features/lights.md, phone app, testing, known issues. The mobile
test script now runs src/**/*.test.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bubulux
bubulux merged commit 2781c40 into main Oct 23, 2026
5 checks passed
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.

Lights 1: fixtures foundation, Worker sync, BLE link and pairing

1 participant