ble2wled.mqtt - MQTT Beacon Listener
MQTT listener for BLE beacon data from espresense.
This module provides the EspresenseBeaconListener class for receiving beacon data from espresense via MQTT.
espresense is a distributed Bluetooth scanner that publishes BLE beacon locations to MQTT. This listener subscribes to beacon topics and updates the beacon state with RSSI values.
- MQTT Topic Structure:
espresense/devices/{beacon_id}/{location}
Example
Listen for beacons from a specific location:
from ble2wled.mqtt import EspresenseBeaconListener
from ble2wled.states import BeaconState
state = BeaconState()
listener = EspresenseBeaconListener(
state,
broker='192.168.1.100',
location='living_room',
port=1883
)
listener.start()
- class ble2wled.mqtt.EspresenseBeaconListener(state: BeaconState, broker: str, location: str = 'balkon', port: int = 1883, username: str | None = None, password: str | None = None)[source]
Bases:
objectListens for BLE beacon data from espresense MQTT broker.
Subscribes to espresense/devices/{beacon_id}/{location} topics and filters for messages from a specific location. Extracts beacon ID and RSSI from the topic and JSON payload.
- state
BeaconState instance to update with beacon data.
- Type:
- __init__(state: BeaconState, broker: str, location: str = 'balkon', port: int = 1883, username: str | None = None, password: str | None = None)[source]
Initialize espresense beacon listener.
Connects to MQTT broker and subscribes to beacon topics.
- Parameters:
state (BeaconState) – BeaconState instance to update with beacon data.
broker (str) – MQTT broker hostname or IP address.
location (str) – Location name to filter for (e.g., ‘balkon’). Default: ‘balkon’.
port (int) – MQTT broker port. Default: 1883.
username (str) – MQTT broker username for authentication. Default: None (no authentication).
password (str) – MQTT broker password for authentication. Default: None (no authentication).
Example
Create and start listener without authentication:
listener = EspresenseBeaconListener( state, broker='192.168.1.100', location='bedroom', port=1883 ) listener.start()
Create and start listener with authentication:
listener = EspresenseBeaconListener( state, broker='192.168.1.100', location='bedroom', port=1883, username='mqtt_user', password='mqtt_pass' ) listener.start()
- on_connect(client: Client, userdata: object, flags: dict, rc: int) None[source]
Handle MQTT connection.
Called when the client connects to the broker. Subscribes to beacon topics and logs connection status.
- Parameters:
Note
This is a callback method called by paho-mqtt library.
- on_message(client: Client, userdata: object, msg: MQTTMessage) None[source]
Handle incoming MQTT message from espresense.
Parses topic and payload to extract beacon ID and RSSI. Validates data consistency and updates beacon state.
Topic format: espresense/devices/{beacon_id}/{location} Payload format: {“id”: “…”, “rssi”: -50.5, …}
- Parameters:
client (mqtt.Client) – MQTT client instance (unused).
userdata (object) – User data (unused).
msg (mqtt.MQTTMessage) – MQTT message with topic and payload.
Example
This method is called automatically by the MQTT library when messages arrive on subscribed topics.
Note
This is a callback method called by paho-mqtt library.
- ble2wled.mqtt.BeaconMQTTListener
alias of
EspresenseBeaconListener
Overview
The mqtt module provides MQTT listener for receiving beacon data from espresense devices. It:
Connects to MQTT broker
Subscribes to beacon topic
Updates beacon state with position and signal strength
Handles connection failures gracefully
Supports username/password authentication
Quick Example
from ble2wled.mqtt import EspresenseBeaconListener
from ble2wled.states import BeaconState
# Create beacon state tracker
state = BeaconState()
# Create MQTT listener
listener = EspresenseBeaconListener(
state,
broker='localhost',
location='living_room'
)
# Start listening (non-blocking, runs in background)
listener.start()
# Beacon state is updated automatically as messages arrive
import time
time.sleep(5)
print(f"Active beacons: {len(state.beacons)}")
# Stop listener
listener.stop()
Classes
EspresenseBeaconListener
Listens for beacon data from espresense devices via MQTT.
Attributes:
beacon_state(BeaconState) - Beacon state to updatebroker(str) - MQTT broker hostname or IPport(int, default 1883) - MQTT portlocation(str) - Location/room identifierusername(str, optional) - MQTT usernamepassword(str, optional) - MQTT passwordclient- paho-mqtt client instance
Methods:
start()- Start listening (non-blocking, runs in background thread)stop()- Stop listening and disconnect
Behavior:
Subscribes to topic: espresense/devices/{location}/#
Handles message format:
{
"distance": 2.5,
"id": "device_id",
"mac": "aa:bb:cc:dd:ee:ff",
"rssi": -45,
"name": "Device Name",
"timestamp": 1234567890
}
Example:
from ble2wled.mqtt import EspresenseBeaconListener
from ble2wled.states import BeaconState
state = BeaconState()
# Basic listener
listener = EspresenseBeaconListener(
state,
broker='192.168.1.50',
location='bedroom'
)
listener.start()
# Listener with authentication
listener_auth = EspresenseBeaconListener(
state,
broker='192.168.1.50',
port=1883,
location='bedroom',
username='mqtt_user',
password='mqtt_password'
)
listener_auth.start()
Configuration
The MQTT topic is derived from location:
Location:
living_roomTopic:
espresense/devices/living_room/#
This subscribes to all devices reporting from that location.
Topic format:
espresense/devices/{location}/{mac_address}
Messages contain beacon distance, RSSI, and device info.
MQTT Message Format
espresense messages contain:
{
"distance": 2.5,
"id": "device_id",
"mac": "aa:bb:cc:dd:ee:ff",
"rssi": -45,
"name": "Device Name",
"timestamp": 1234567890
}
The listener extracts:
id- Unique beacon identifierdistance- Estimated distance from device (meters)rssi- Signal strength (dBm)
Examples
Basic MQTT Listening
from ble2wled.mqtt import EspresenseBeaconListener
from ble2wled.states import BeaconState
import time
# Setup
state = BeaconState()
listener = EspresenseBeaconListener(
state,
broker='localhost',
location='test'
)
# Start listening
listener.start()
print("Listening for beacon data...")
# Let it collect data
time.sleep(10)
# Check collected beacons
print(f"Received {len(state.beacons)} beacons")
for beacon_id, beacon in state.beacons.items():
print(f" {beacon_id}: position={beacon.position}, rssi={beacon.rssi}")
# Stop listening
listener.stop()
With Configuration
from ble2wled.config import Config
from ble2wled.mqtt import EspresenseBeaconListener
from ble2wled.states import BeaconState
# Load configuration from .env
config = Config('.env')
# Create listener with config
state = BeaconState(
timeout_seconds=config.beacon_timeout_seconds,
fade_out_seconds=config.beacon_fade_out_seconds
)
listener = EspresenseBeaconListener(
state,
broker=config.mqtt_broker,
port=config.mqtt_port,
location=config.mqtt_location,
username=config.mqtt_username,
password=config.mqtt_password
)
listener.start()
With WLED Animation
from ble2wled.mqtt import EspresenseBeaconListener
from ble2wled.states import BeaconState
from ble2wled.wled import WLEDUDPController
from ble2wled.animation import run_wled_beacons
# Setup
state = BeaconState()
listener = EspresenseBeaconListener(
state,
broker='localhost',
location='living_room'
)
controller = WLEDUDPController('192.168.1.100', 60)
# Start MQTT listener
listener.start()
# Run animation (blocks)
try:
run_wled_beacons(
controller,
led_count=60,
beacon_state=state
)
finally:
listener.stop()
With Authentication
from ble2wled.mqtt import EspresenseBeaconListener
from ble2wled.states import BeaconState
state = BeaconState()
# With credentials for secured MQTT broker
listener = EspresenseBeaconListener(
state,
broker='192.168.1.50',
port=1883,
location='kitchen',
username='mqtt_user',
password='secure_password'
)
listener.start()
Multiple Locations
Monitor multiple locations with separate listeners:
from ble2wled.mqtt import EspresenseBeaconListener
from ble2wled.states import BeaconState
# Create state for each location
living_room_state = BeaconState()
kitchen_state = BeaconState()
# Create listeners
living_room_listener = EspresenseBeaconListener(
living_room_state,
broker='localhost',
location='living_room'
)
kitchen_listener = EspresenseBeaconListener(
kitchen_state,
broker='localhost',
location='kitchen'
)
# Start both
living_room_listener.start()
kitchen_listener.start()
# Process both state streams...
# Stop both
living_room_listener.stop()
kitchen_listener.stop()
Error Handling
Connection Failures
The listener handles connection failures gracefully:
from ble2wled.mqtt import EspresenseBeaconListener
from ble2wled.states import BeaconState
state = BeaconState()
listener = EspresenseBeaconListener(
state,
broker='192.168.1.100', # Non-existent broker
location='test'
)
listener.start() # Doesn't raise, just logs error
# Check logs for connection errors
Authentication Failures
from ble2wled.mqtt import EspresenseBeaconListener
from ble2wled.states import BeaconState
state = BeaconState()
listener = EspresenseBeaconListener(
state,
broker='localhost',
location='test',
username='wrong_user',
password='wrong_password'
)
listener.start() # Doesn't raise, but won't receive messages
# Check logs: "MQTT authentication failed"
Troubleshooting
No Beacons Received
Check MQTT broker is running:
mosquitto_sub -h localhost -t "espresense/devices/test/#"
If this doesn’t show messages, broker isn’t receiving espresense data.
Verify location matches espresense configuration
Check authentication credentials
Check network connectivity:
ping <mqtt-broker-ip>
Connection Refused
Verify broker is running and accessible
Check port (default 1883)
Verify IP/hostname is correct
Check firewall rules
Authentication Failed
Verify username and password are correct
Check user account exists in MQTT broker:
# Mosquitto sudo mosquitto_passwd -l /etc/mosquitto/passwd
Check broker authentication is enabled
Performance
Message Rate
MQTT listener receives messages for each detected beacon. Typical rates:
1-5 beacons: 10-50 messages/second
10+ beacons: 100+ messages/second
The listener is non-blocking and handles high message rates efficiently.
State Updates
Beacon state is updated immediately as messages arrive. No polling needed.
Examples per Second
Low: 1-2 messages/second (1-2 beacons with slow scan)
Medium: 10-20 messages/second (3-5 beacons)
High: 100+ messages/second (10+ beacons with fast scan)
See Also
ble2wled.states - Beacon State Management - Beacon state management
MQTT Authentication - MQTT authentication guide
Configuration - Configuration reference
Quickstart - Quick start with MQTT