GitShow/wesbos/amaran-BLE-control
wesbos

amaran-BLE-control

Direct control of Amaran lights over Bluetooth. No desktop app required.

by wesbos
Star on GitHubForknpm

TypeScript

32 stars7 forks2 contributorsActive · 3w agoSince 2026MIT

Meet the team

See all 2 on GitHub →
wesbos
wesbos23 contributions
kevinschaich
kevinschaich1 contribution

Languages

View on GitHub →
TypeScript57.4%
C40.3%
JavaScript1.6%
CMake0.7%

Commit activity

Last 12 weeks · 10 commits

Full graph →

Community health

2 of 6 standards met

Community profile →
42
✓README✓License○Contributing○Code of Conduct○Issue Template○PR Template

Recent PRs & issues

Active · 3 in progress · Last activity 3w ago
See all on GitHub →
clwill
mqtt: verify on/off commands against fixture status, retry lost sendsOpenPR

Problem Mesh sends are fire-and-forget ( — no ack, no retry). When an on/off PDU is lost in the air, the fixture keeps its old state while the bridge has already optimistically told HA the new one. The post-command auto-refresh (~600 ms) then reads the fixture's true state — and adopts it as an "external change", flipping HA back. Field observation that motivated this: a scripted left the fixture physically on, twice in two days, with HA's state bouncing → ~0.95 s after the command (visible in HA's logbook as two state changes sharing one service-call context). The bridge detected the loss each time — the refresh is what corrected HA — it just reported the failure instead of fixing it. Fix Close the loop that already exists: When dispatching an on/off, record the commanded state and arm a 5 s verification window (). If a status reply contradicts a fresh command, re-send it (bounded, 2 retries) instead of adopting the stale state. Each re-send goes through the normal dispatch, whose fetches a fresh status ~600 ms later — so every retry is itself verified. Retries are dispatched from a one-shot (the same pattern as ), never from the BLE rx path. On confirmation, or once retries/window are exhausted, the pending flag clears and behavior is exactly as before: genuine external changes (phone app, physical knob) still flow to HA. Scope is deliberately on/off only — it's the binary, user-visible failure. A lost brightness/CCT PDU shows as a wrong-looking light, which the existing refresh at least reports honestly. Testing Builds clean (ESP-IDF 5.3, classic ESP32 target). Running in production on a 7-fixture rig: off→on→off cycles confirm the happy path (command → status confirms → clears, no spurious retries), and phone-app changes still propagate to HA. The retry path logs at warning level when it fires. 🤖 Generated with Claude Code https://claude.ai/code/session_014ENfJHGWP7gnG3V7KmbSP9

clwill · 3d ago
clwill
Move ESP32 unicast address clear of app-assigned fixture addressesOpenPR

Problem is hardcoded to with the comment "existing fixtures are at 2/4/6" — true for a three-fixture rig, but the amaran app assigns fixture addresses upward from low values. A seven-fixture rig was observed holding , so the bridge collided with a real fixture at . The symptom is subtle and easy to misdiagnose: the colliding fixture simply never answers a status request (the ESP32 answers for its address), while commands to it still work. Everything looks fine except one light's state never updates in HA. Fix Default to — generous headroom above any realistic fixture count — and document both the app's allocation pattern and the NVS caveat: changing the address on an already-provisioned board requires , because the old address persists. Existing deployments are unaffected by pulling this change (their provisioned address lives in NVS); it only changes what fresh provisions get. Testing Running in production on a 7-fixture rig: with one fixture was silently absent from every status sweep; at (after ) all seven answer. 🤖 Generated with Claude Code https://claude.ai/code/session_014ENfJHGWP7gnG3V7KmbSP9

clwill · 3d ago
clwill
wifi: connect to the strongest AP, not the first channel matchOpenPR

Problem is zero-initialized, which leaves at : the ESP32 associates to the first SSID match in channel scan order and never compares signal strength. On a network where several APs broadcast the same SSID (any multi-AP home), the bridge deterministically picks whichever AP carries the SSID on the lowest-numbered channel — even a distant one. Observed on a real deployment: the bridge sat at −61 dBm on an AP across the house (ch 1) while an AP 8 ft away with line of sight (ch 11) held its ESP32 neighbours at −35 dBm. Since the bridge holds a persistent MQTT connection, a marginal link doesn't fail cleanly — it shows up as HA entities flapping unavailable. Fix + : scan every channel, pick by RSSI. Costs a few hundred ms once at association; no effect on single-AP networks. Testing Running in production on an ESP32-WROOM-32D driving a 7-fixture rig: went from −61 dBm on the wrong AP (with a re-association inside the first 39 min) to −45 dBm on the near AP, zero re-associations in the days since. Compile-time only — a plain picks it up, mesh provisioning in NVS is untouched. One related note, documented so nobody burns an evening on it: does not stick on classic ESP32 once the BLE Mesh stack starts — WiFi/BT coexistence forces modem sleep back on (verified via AP-side powersave flag: off at 5 s uptime, on again by 33 s). The ~70 ms of extra command latency appears to be the floor while BLE is active. 🤖 Generated with Claude Code https://claude.ai/code/session_014ENfJHGWP7gnG3V7KmbSP9

clwill · 3d ago

Recent fixes

View closed PRs →
unusual-audio
Please add open source licenseClosedIssue

Hi! Thanks for publishing this project! I noticed that declares the license as , but the repository doesn’t include a standalone file. Would you be open to adding one? That would make the intended licensing clearer for GitHub users and downstream projects, and it would also allow GitHub to detect and display the license automatically. Assuming MIT is still the intended license, you could use this template: . Thanks again for making this available.

unusual-audio · 3w ago
kevinschaich
Add MIT LicenseMergedPR
kevinschaich · 3w ago
blakeperdue
Patch fails for ESP-IDF v5.3.5, new patch file attachedClosedIssue

In case others come across this, I installed the project on an ESP32-c3 and needed to update the IDF patch file to work properly with v5.3.5. Attached is the file Claude helped me create to update your patch file to work with this newer version of IDF. 0001-amaran-net-recv-status-snoop-v5.3.5.patch

blakeperdue · 4w ago
Structured data for AI agents

Repository: wesbos/amaran-BLE-control. Description: Direct control of Amaran lights over Bluetooth. No desktop app required. Stars: 32, Forks: 7. Primary language: TypeScript. Languages: TypeScript (57.4%), C (40.3%), JavaScript (1.6%), CMake (0.7%). License: MIT. Open PRs: 3, open issues: 0. Last activity: 3w ago. Community health: 42%. Top contributors: wesbos, kevinschaich.

·@ofershap

Replace github.com with gitshow.dev