ble2wled.states - Beacon State Management
Beacon state management with timeout and fade-out.
This module provides the BeaconState class for tracking BLE beacons with automatic timeout and fade-out effects. Beacons update their “life” value from 1.0 (fully visible) to 0.0 (faded out) as they age.
Example
Track beacons and get their current state:
state = BeaconState(timeout_seconds=6.0, fade_out_seconds=4.0)
state.update('beacon_1', -50) # Update with RSSI
beacons = state.snapshot() # Get current beacons
for beacon_id, (rssi, life) in beacons.items():
print(f"{beacon_id}: RSSI={rssi}, life={life}")
- class ble2wled.states.BeaconState(timeout_seconds: float = 5.0, fade_out_seconds: float = 3.0)[source]
Bases:
objectManages the state of detected beacons with automatic timeout and fade-out.
This class maintains a thread-safe collection of beacons with their RSSI values and life metrics. Beacons automatically timeout when not updated and fade out gracefully over a configurable period.
- __init__(timeout_seconds: float = 5.0, fade_out_seconds: float = 3.0)[source]
Initialize beacon state tracker.
- Parameters:
Example
Create a beacon state tracker with 6-second timeout and 4-second fade:
state = BeaconState(timeout_seconds=6.0, fade_out_seconds=4.0)
- update(beacon_id: str, rssi: int) None[source]
Update beacon with signal strength.
Updates or creates a beacon entry with the current timestamp and RSSI. Thread-safe operation.
- Parameters:
Example
Update beacon with RSSI value:
state.update('beacon_1', -50) # Update beacon_1 with -50 dBm
- snapshot() Dict[str, Tuple[int, float]][source]
Get current active beacons with RSSI and life values.
Returns a thread-safe snapshot of all active beacons. Automatically removes beacons that have completely faded out. Each beacon entry includes its RSSI and life value (0.0 = invisible, 1.0 = fully visible).
- Returns:
- Dictionary mapping beacon_id (str) to (rssi, life) tuples.
rssi (int): Signal strength in dBm. life (float): Beacon visibility (0.0 to 1.0).
- Return type:
Example
Get current beacon snapshot:
beacons = state.snapshot() if 'beacon_1' in beacons: rssi, life = beacons['beacon_1'] print(f"Beacon 1: {rssi} dBm, {life*100:.0f}% visible")
Overview
The states module manages beacon state and lifecycle. It tracks:
Active beacons and their positions
Signal strength (RSSI) over time
Beacon timeouts (when beacons disappear)
Fade-out animations for departing beacons
Key Classes
Beacon
Represents a single beacon with its current state.
BeaconState
Tracks all active and fading beacons.
Quick Example
from ble2wled.states import BeaconState, Beacon
# Create beacon state tracker
state = BeaconState(
timeout_seconds=6.0, # Beacon times out after 6 seconds
fade_out_seconds=4.0 # Fade out over 4 seconds after timeout
)
# Add a beacon (usually from MQTT)
state.update_or_create(
beacon_id='device_123',
position=30, # Position on LED strip (0-60)
rssi=-45 # Signal strength in dBm
)
# Get active beacon
beacon = state.beacons['device_123']
print(f"Position: {beacon.position}, RSSI: {beacon.rssi}")
# Check if beacon is in timeout
if beacon.is_in_timeout:
print("Beacon has timed out!")
# Update beacon positions/signals
state.update_or_create('device_123', position=32, rssi=-48)
# Cleanup expired beacons
state.cleanup()
Classes
Beacon
A single beacon with position and signal information.
Attributes:
beacon_id(str) - Unique beacon identifierposition(float) - Position on LED strip (0 to led_count)rssi(int) - Signal strength in dBm (typically -20 to -100)last_update_time(float) - Timestamp of last updatetimeout_at(float) - Timestamp when beacon times outis_in_timeout(bool) - Whether beacon has timed out
Methods:
should_be_removed(current_time: float) -> bool- Check if beacon should be removedget_fade_factor(current_time: float) -> float- Get fade factor (0.0-1.0) during fade-out
BeaconState
Tracks all active and fading beacons.
Attributes:
beacons(Dict[str, Beacon]) - Active and fading beaconstimeout_seconds(float) - Beacon timeout durationfade_out_seconds(float) - Fade-out animation duration
Methods:
update_or_create(beacon_id: str, position: float, rssi: int)- Update or create beaconcleanup()- Remove expired beaconsclear()- Remove all beacons
Examples
Basic Beacon Tracking
from ble2wled.states import BeaconState
state = BeaconState()
# Update beacon position and signal
state.update_or_create('beacon_1', position=15, rssi=-50)
state.update_or_create('beacon_2', position=45, rssi=-60)
# Check active beacons
print(f"Active beacons: {len(state.beacons)}")
for beacon_id, beacon in state.beacons.items():
print(f" {beacon_id}: pos={beacon.position}, rssi={beacon.rssi}")
Beacon Lifecycle
from ble2wled.states import BeaconState
import time
state = BeaconState(timeout_seconds=2.0, fade_out_seconds=1.0)
# Beacon appears
state.update_or_create('device_1', position=30, rssi=-45)
print(f"Beacon active: {state.beacons['device_1'].is_in_timeout}") # False
# After 2 seconds without update: beacon times out
time.sleep(2.1)
print(f"Beacon timed out: {state.beacons['device_1'].is_in_timeout}") # True
# Get fade factor for animation
fade = state.beacons['device_1'].get_fade_factor(time.time())
print(f"Fade factor: {fade}") # 0.5 (halfway through fade-out)
# After 3 seconds: beacon is removed
time.sleep(1.0)
state.cleanup()
print(f"Beacon count: {len(state.beacons)}") # 0
MQTT Integration
from ble2wled.states import BeaconState
from ble2wled.mqtt import EspresenseBeaconListener
state = BeaconState()
# MQTT listener updates beacon state automatically
listener = EspresenseBeaconListener(
state,
broker='localhost',
location='living_room'
)
listener.start()
# Beacon state is automatically updated from MQTT
time.sleep(0.1)
for beacon_id, beacon in state.beacons.items():
print(f"{beacon_id}: {beacon.position} @ {beacon.rssi} dBm")
Animation Integration
from ble2wled.states import BeaconState
from ble2wled.colors import position_to_color_hue
state = BeaconState()
state.update_or_create('beacon_1', position=30, rssi=-50)
# Get beacon for animation
beacon = state.beacons['beacon_1']
# Calculate color based on distance/signal
hue = position_to_color_hue(beacon.position, led_count=60)
print(f"Color hue: {hue}")
# Use fade factor if beacon is timing out
brightness = 1.0 * beacon.get_fade_factor(time.time())
print(f"Brightness: {brightness}")
Custom Timeout Configuration
from ble2wled.states import BeaconState
# Fast timeout: 2 seconds active, 1 second fade-out
state_fast = BeaconState(timeout_seconds=2.0, fade_out_seconds=1.0)
# Slow timeout: 10 seconds active, 5 seconds fade-out
state_slow = BeaconState(timeout_seconds=10.0, fade_out_seconds=5.0)
# Very persistent: 30 seconds before timeout
state_persistent = BeaconState(timeout_seconds=30.0, fade_out_seconds=2.0)
See Also
Configuration - Configure timeout values
ble2wled.colors - Color Calculations - Color mapping for beacons
ble2wled.animation - Animation Loop - Animation loop using beacon state
ble2wled.mqtt - MQTT Beacon Listener - MQTT listener that updates beacon state