Skip to content

fix(ble): read sensors from advertisements instead of connecting - #356

Merged
donavanbecker merged 1 commit into
latestfrom
fix/meter-passive
Oct 30, 2026
Merged

donavanbecker merged 1 commit into
latestfrom
fix/meter-passive

Conversation

@donavanbecker

Copy link
Copy Markdown
Contributor

What

Fixes homebridge-switchbot#1437: a Meter added over BLE shows temperature, humidity and battery stuck at 0.

Cause

getBLEStatus() connected to every device to read its status. Meters and other sensors report their state in BLE advertisements, and many refuse connections. The user's log shows the result:

  • Unknown Connection Identifier (0x2) and Command Disallowed (0xc) from noble;
  • then circuit opened - failure rate 1.00.

The connection reply wasn't used anyway: normalizeBLEStatusData returns the cached advertisement data when the reply is a Buffer.

Fix

This follows pySwitchbot, where sensors are passive and status comes from the advertisement parsers.

  • Which devices: WoSensorTH and its subclasses (Meter Plus, Meter Pro, Meter Pro CO2, Indoor/Outdoor), WoContact, WoPresence (motion/presence), WoLeak and WoWaterDetector. They are read from their latest advertisement and never connected to.
  • Freshness: advertisement data newer than 60 s is used as is.
  • Stale data: the device waits up to 10 s for its next advertisement (sensors advertise every few seconds). SwitchBot supplies this via advertisementSource; it runs one short scan shared by all waiting devices if none is running.
  • No new advertisement: the last advertisement is used. If there has never been one, it throws, and getStatusWithFallback falls back to the API.
  • New field: DeviceInfo.bleServiceDataAt records when the advertisement was received.

Non-sensor devices are unchanged.

Tests

test/devices/sensor-advertisement-status.test.ts covers:

  • the reported failure: a meter whose connection is always refused;
  • stale data triggering a fresh advertisement;
  • the last-advertisement and API fallbacks;
  • every sensor class never connecting;
  • non-sensors still connecting;
  • the shared scan: matching by MAC, one scan for several devices, timeout cleanup.

446 tests pass. Build and lint pass.

No breaking changes.


Generated by Claude Code

Status over BLE was read by connecting to the device for every device type.
Meters and other sensors report their state in advertisements and often
refuse connections ("Unknown Connection Identifier (0x2)", "Command
Disallowed"), so reads failed, the BLE circuit breaker opened and values
stayed at 0 (homebridge-switchbot#1437). The reply from the connection was
also discarded: the status came from the cached advertisement anyway.

As in pySwitchbot, meters (Meter, Plus, Pro, Pro CO2, Indoor/Outdoor),
contact, motion, leak and water sensors are now read from their latest
advertisement. When it is older than 60 s, the device listens up to 10 s
for a new one, sharing a single short scan between devices; if none
arrives it returns the last advertisement, or fails over to the API when
there has never been one. Sensors are never connected to.

DeviceInfo gains bleServiceDataAt (when the advertisement was received).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYWa2RXoWsaUTWh76oNv8s
@donavanbecker
donavanbecker merged commit 4112d4b into latest Oct 30, 2026
2 checks passed
@donavanbecker
donavanbecker deleted the fix/meter-passive branch October 30, 2026 21:58
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.

Bug:The meter value could not be retrieved.

2 participants