Note: This project is a work in progress. Features may change and things might break. Contributions, bug reports, and feedback are very welcome!
A MicroPython-based BLE (Bluetooth Low Energy) to ThingsBoard IoT gateway for ESP32 devices. It scans for BLE beacons and forwards their data to a ThingsBoard instance via MQTT.
Critical: This project requires an ESP32 module with PSRAM (SPIRAM) (e.g., ESP32-WROVER or TinyPico). Standard ESP32 modules (like ESP32-WROOM) do not have enough heap memory.
Note: It may be possible to run on standard RAM devices if you pre-compile all Python files to .mpy or freeze them into the firmware image, but this is not tested.
| Beacon Type | Telemetry | Attributes |
|---|---|---|
| iBeacon | RSSI | UUID, Major, Minor, Reference RSSI |
| AltBeacon | RSSI | Company ID, UUID, Major, Minor, Reference RSSI, Mfg Reserved |
| Eddystone UID | RSSI | Namespace, Instance, Reference RSSI |
| RuuviTag | Temperature, Humidity, Pressure, Acceleration (X/Y/Z), Battery Voltage, TX Power, Movement Counter, Measurement Sequence, RSSI | — |
| MikroTik | Temperature, Acceleration (X/Y/Z), Battery, Trigger, Salt, Uptime, RSSI | Version, Encrypted |
- Asynchronous BLE scanning and MQTT communication using
asyncio - Per-beacon-type RSSI filtering
- Per-beacon-type scan interval throttling to reduce traffic
- UUID/Major/Minor/Namespace/Instance filters for iBeacon, AltBeacon, and Eddystone UID
- Runtime configuration updates through ThingsBoard shared attributes
- ESP32 board running MicroPython (≥ 1.20 recommended)
- The following MicroPython libraries (install into
lib/):mqtt_as— async MQTT clientaioble— async BLEringbuf_queue— async ring buffer queueubeacon— BLE beacon parsers (iBeacon, AltBeacon, Eddystone, RuuviTag, MikroTik)
Copy config.example.py to config.py to set your environment:
# ThingsBoard MQTT broker
config["server"] = "192.168.42.246"
config["port"] = 1883
config["user"] = "<DEVICE_ACCESS_TOKEN>"
# Wi-Fi
config["ssid"] = "<WIFI_SSID>"
config["wifi_pw"] = "<WIFI_PASSWORD>"The gwcfg dictionary in config.py defines default values for all gateway settings. These can be overridden at runtime through ThingsBoard shared attributes:
| Key | Default | Description |
|---|---|---|
bleScanInterval |
30000 | BLE scan interval in microseconds |
bleScanWindow |
30000 | BLE scan window in microseconds |
gwStatusInterval |
60 | Gateway telemetry publish interval in seconds |
bleScan<Type>Active |
False |
Enable/disable scanning for a beacon type |
bleScanFilter<Type>Rssi |
False |
Minimum RSSI threshold (dBm), False to disable |
bleScan<Type>ScanInterval |
300 | Per-device scan throttle interval in seconds |
Where <Type> is one of: IBeacon, AltBeacon, RuuviTag, MikroTik, EddystoneUid.
These shared attributes can be set on the gateway device in ThingsBoard to filter beacons by their identifiers:
bleScanFilterIBeaconUuid,bleScanFilterIBeaconMajor,bleScanFilterIBeaconMinorbleScanFilterAltBeaconUuid,bleScanFilterAltBeaconMajor,bleScanFilterAltBeaconMinorbleScanFilterEddystoneUidNamespace,bleScanFilterEddystoneUidInstance
- Flash MicroPython onto your ESP32.
- Copy the project files and dependencies to the device.
- Add the device to your ThingsBoard as gateway, with device profile "ThingsBoard BLE Gateway" (for demo dashboard)
- Edit
config.pywith your Wi-Fi and ThingsBoard credentials. - Enable the beacon types you want to scan in
gwcfg. - Reboot the device —
main.pyruns automatically. - Import Example Dashboard (JSON from resources directory) to ThingsBoard
The gateway will connect to Wi-Fi and ThingsBoard, then begin scanning for BLE beacons. Discovered beacons are registered as devices in ThingsBoard, with their telemetry and attributes forwarded automatically.
Contributions are welcome! Feel free to open issues, suggest features, or submit pull requests.
