Reading a SwitchBot Motion Sensor Over BLE Directly
This article may contain affiliate links. Its content is not affected by advertising.
In short
Receive a SwitchBot motion sensor's BLE advertisements directly and it works as a presence trigger entirely locally, with no Hub and no cloud in between.
The normal setup versus reading it directly
A SwitchBot motion sensor is normally used along the path “sensor → Hub → cloud → app / integration”. That is convenient, but it requires a Hub and assumes the cloud.
The sensor, meanwhile, broadcasts BLE advertisements continuously. Receive and parse those in your own program and everything stays local, with no Hub and no cloud in between. Latency drops too.
If the existing notifications and integrations do what you need, the former is plenty. The latter is only worth choosing when you want to drop presence detection into a system you are building yourself.
What you need
- A SwitchBot motion sensor
- A computer that can receive BLE (a Raspberry Pi or an Android device both work)
No extra gateway is required.
What it does
BLE advertisements carry vendor-specific data (Service Data / Manufacturer Data). Detected / not detected lives in there, so you parse it out. The data format has been published by community reverse-engineering (pySwitchbot and others), which is what I relied on.
Three points to the implementation.
- Filter on the target sensor’s MAC and pick up only that
- Stay resident and keep receiving
- Buffer locally and send on afterwards, so a dropped advertisement is survivable
The third matters most. BLE advertisements sometimes do not arrive, so build with offline tolerance from the start.
Where it got hard
① BLE scanning needs location permission (Android)
On Android, BLE scanning requires location permission, and without it you get zero detections with no error.
Nothing appears in the log either. This is where the most time went, with no visible cause.
② Left alone, scanning stops
Unless it is a resident service and excluded from battery optimisation, reception quietly stops at some point for OS reasons.
③ Dropped advertisements are a given
As above. Without a design that buffers locally and resends, the record comes out full of gaps.
What the three have in common
Lined up, all three take the shape of “you cannot tell that it stopped”. ① produces no error, ② stops at some point, ③ is noticed as gaps after the fact.
What eats time when working with BLE was usually not the parsing but this silent failure. Building a way to confirm from outside that reception is alive, before anything else, makes later investigation completely different.
Frequently asked questions
Q1Does it really work without buying a Hub?
It does. The sensor broadcasts BLE advertisements continuously, so any computer that can receive BLE can parse them directly. No extra gateway is needed. That said, if the SwitchBot app's notifications or the existing integrations do what you need, buying a Hub is overwhelmingly easier.
Q2Detection stays at zero and nothing happens. Where do I look?
On Android, check the location permission. BLE scanning returns zero results with no error and no exception if location is not granted. It does not appear in the log either, which makes it easy to burn time with no visible cause.
Q3How should dropped advertisements be handled?
Design on the premise that BLE advertisements sometimes do not arrive. Unless received values are buffered locally and sent on afterwards, the record comes out full of gaps.
What this article is based on
- Markdown file
Every claim in this article comes from the records above. The repositories we operate are private so we cannot link to them, but which file, which lines, and at which commit we read them is recorded for every article. Nothing here is written from guesswork.