ble2wled.colors - Color Calculations
Color conversion and distance estimation from RSSI.
This module provides functions for converting BLE beacon signal strength (RSSI) to distance estimates, mapping distance to colors on a gradient, and generating beacon-specific colors with life-based brightness modulation.
The distance estimation uses the Friis path loss model:
distance = 10^((TX_POWER - RSSI) / (10 * N))
- Color Mapping:
Beacons near (< 0.5m): Yellow (255, 255, 0)
Beacons far (> 10m): Red (255, 0, 0)
Linear gradient between near and far distances
Example
Convert beacon data to RGB color:
rssi = -50
distance = estimate_distance_from_rssi(rssi)
color = ble_beacon_to_rgb('beacon_1', rssi, life=0.8)
print(f"Beacon at {distance:.2f}m: RGB{color}")
- ble2wled.colors.estimate_distance_from_rssi(rssi: int, tx_power: int = -59, n: float = 2.0) float[source]
Estimate distance from signal strength using path loss model.
Uses the Friis free space path loss model to estimate distance from RSSI. The accuracy depends on the environment and the TX power of the beacon.
- Parameters:
- Returns:
Estimated distance in meters.
- Return type:
Example
Estimate distance from RSSI values:
distance = estimate_distance_from_rssi(-50) # ~1 meter distance = estimate_distance_from_rssi(-70) # ~10 meters
- ble2wled.colors.lerp(a: float, b: float, t: float) float[source]
Linear interpolation between two values.
- Parameters:
- Returns:
Interpolated value between a and b.
- Return type:
Example
Interpolate between colors:
mid_value = lerp(0, 255, 0.5) # Returns 127.5
- ble2wled.colors.gradient_color(distance: float, near: float = 0.5, far: float = 10.0) Tuple[float, float, float][source]
Map distance to RGB color gradient (yellow to red).
Maps distance to a color gradient from yellow (near) to red (far). Uses linear interpolation in the middle range. Returns values in 0-1 range.
- Color Mapping:
distance < near: Yellow (1.0, 1.0, 0.0)
distance between near and far: Gradient yellow → red
distance > far: Red (1.0, 0.0, 0.0)
- Parameters:
- Returns:
RGB tuple with values in range 0.0-1.0.
- Return type:
Example
Get color for different distances:
close_color = gradient_color(0.3) # Yellow-ish mid_color = gradient_color(5.0) # Yellow-Red transition far_color = gradient_color(15.0) # Red
- ble2wled.colors.ble_beacon_to_rgb(beacon_id: str, rssi: int, life: float) Tuple[int, int, int][source]
Convert beacon data to RGB color.
Applies distance-based gradient coloring with unique hue offset per beacon, and modulates brightness based on life value. Each beacon gets a consistent hue offset based on its ID hash, ensuring the same beacon is always the same base color.
- Algorithm:
Estimate distance from RSSI
Map distance to base color (yellow to red gradient)
Apply unique hue offset per beacon (0-8% range)
Scale brightness by life value (0-1)
- Parameters:
- Returns:
RGB tuple with values 0-255.
- Return type:
Example
Convert beacon to RGB color:
color = ble_beacon_to_rgb('beacon_1', rssi=-50, life=0.8) r, g, b = color print(f"Color: RGB({r}, {g}, {b})")
Overview
The colors module provides color calculations for LED visualization, including:
Distance-to-color mapping (position on LED strip → hue)
Signal strength mapping (RSSI → brightness)
HSV to RGB conversion
Color utilities for beacon visualization
Color Strategy
BLE2WLED uses a sophisticated color mapping strategy:
Hue Assignment - Each beacon gets a unique hue based on its ID (hash-based)
Distance Mapping - Distance from transmitter maps to saturation/value
Signal Strength - RSSI maps to brightness
Motion Trails - Recent positions brightest, fade out over time
Quick Example
from ble2wled.colors import (
position_to_color_hue,
rssi_to_brightness,
beacon_id_to_hue,
hsv_to_rgb
)
# Get hue for a position on the LED strip
position = 30 # Middle of 60-LED strip
hue = position_to_color_hue(position, led_count=60)
print(f"Position {position} → Hue {hue}")
# Get brightness from signal strength
rssi = -50
brightness = rssi_to_brightness(rssi)
print(f"RSSI {rssi} → Brightness {brightness}")
# Get unique color for each beacon
beacon_id = "device_123"
beacon_hue = beacon_id_to_hue(beacon_id)
print(f"Beacon {beacon_id} → Hue {beacon_hue}")
# Convert HSV to RGB
h, s, v = beacon_hue, 0.8, 1.0
r, g, b = hsv_to_rgb(h, s, v)
print(f"HSV({h}, {s}, {v}) → RGB({r}, {g}, {b})")
Functions
position_to_color_hue()
Map a position on the LED strip to a color hue.
Parameters:
position(float) - Position on LED strip (0 to led_count)led_count(int) - Total number of LEDs
Returns:
float- Hue value (0-360 degrees)
Example:
from ble2wled.colors import position_to_color_hue
# 60-LED strip
hue_start = position_to_color_hue(0, 60) # Red (0°)
hue_middle = position_to_color_hue(30, 60) # Cyan (180°)
hue_end = position_to_color_hue(59, 60) # Purple (359°)
rssi_to_brightness()
Map signal strength (RSSI) to brightness.
Parameters:
rssi(int) - Signal strength in dBm (typically -20 to -100)
Returns:
float- Brightness (0.0-1.0)
Behavior:
Very strong signal (-20 to -30): brightness 1.0 (full)
Strong signal (-30 to -50): brightness 0.8-1.0
Medium signal (-50 to -70): brightness 0.3-0.8
Weak signal (-70 to -100): brightness 0.0-0.3
Example:
from ble2wled.colors import rssi_to_brightness
rssi_strong = -40
rssi_weak = -80
brightness_strong = rssi_to_brightness(rssi_strong) # ~0.9
brightness_weak = rssi_to_brightness(rssi_weak) # ~0.2
beacon_id_to_hue()
Get a unique, consistent hue for each beacon based on its ID.
Parameters:
beacon_id(str) - Unique beacon identifier
Returns:
float- Hue value (0-360 degrees)
Behavior:
Same beacon ID always gets same hue
Different beacon IDs get different hues
Uses hash function for distribution
Example:
from ble2wled.colors import beacon_id_to_hue
beacon1_hue = beacon_id_to_hue("device_123")
beacon2_hue = beacon_id_to_hue("device_456")
# Same beacon, same hue (consistent)
assert beacon_id_to_hue("device_123") == beacon1_hue
# Different beacon, different hue
assert beacon1_hue != beacon2_hue
hsv_to_rgb()
Convert HSV color to RGB.
Parameters:
h(float) - Hue (0-360 degrees)s(float) - Saturation (0.0-1.0)v(float) - Value/Brightness (0.0-1.0)
Returns:
tuple- RGB values (r, g, b) each 0-255
Example:
from ble2wled.colors import hsv_to_rgb
# Red
r, g, b = hsv_to_rgb(0, 1.0, 1.0)
assert (r, g, b) == (255, 0, 0)
# Green
r, g, b = hsv_to_rgb(120, 1.0, 1.0)
assert (r, g, b) == (0, 255, 0)
# Blue
r, g, b = hsv_to_rgb(240, 1.0, 1.0)
assert (r, g, b) == (0, 0, 255)
# Gray (low saturation)
r, g, b = hsv_to_rgb(0, 0.0, 0.5)
assert (r, g, b) == (128, 128, 128)
Examples
Complete Color Calculation
from ble2wled.colors import (
position_to_color_hue,
rssi_to_brightness,
beacon_id_to_hue,
hsv_to_rgb
)
# For a beacon at position 30 with RSSI -50
beacon_id = "device_123"
position = 30
rssi = -50
led_count = 60
# Get base hue from beacon ID (unique per beacon)
hue = beacon_id_to_hue(beacon_id)
# Get saturation from position (distance-based)
# Closer beacons are more saturated
position_hue = position_to_color_hue(position, led_count)
saturation = 1.0 - abs(hue - position_hue) / 180.0
# Get brightness from signal strength
brightness = rssi_to_brightness(rssi)
# Convert HSV to RGB for LED
r, g, b = hsv_to_rgb(hue, saturation, brightness)
print(f"Beacon {beacon_id} at LED {position}")
print(f" HSV: ({hue:.1f}°, {saturation:.2f}, {brightness:.2f})")
print(f" RGB: ({r}, {g}, {b})")
Multiple Beacons
from ble2wled.colors import beacon_id_to_hue, hsv_to_rgb
beacons = {
"device_1": {"position": 10, "rssi": -45},
"device_2": {"position": 30, "rssi": -60},
"device_3": {"position": 50, "rssi": -75},
}
for beacon_id, data in beacons.items():
hue = beacon_id_to_hue(beacon_id)
# ... calculate saturation, brightness ...
r, g, b = hsv_to_rgb(hue, 0.8, brightness)
print(f"{beacon_id}: RGB({r}, {g}, {b})")
Gradient Visualization
from ble2wled.colors import position_to_color_hue, hsv_to_rgb
# Show color gradient across LED strip
led_count = 60
for position in range(0, led_count, 10):
hue = position_to_color_hue(position, led_count)
r, g, b = hsv_to_rgb(hue, 1.0, 1.0)
print(f"LED {position:2d}: RGB({r:3d}, {g:3d}, {b:3d})")
Signal Strength Visualization
from ble2wled.colors import rssi_to_brightness, hsv_to_rgb
# Show brightness at different signal strengths
rssi_values = [-30, -50, -70, -90]
hue = 120 # Green
for rssi in rssi_values:
brightness = rssi_to_brightness(rssi)
r, g, b = hsv_to_rgb(hue, 1.0, brightness)
print(f"RSSI {rssi:3d} dBm: Brightness {brightness:.2f} → RGB({r}, {g}, {b})")
See Also
ble2wled.states - Beacon State Management - Beacon state with position and RSSI
ble2wled.animation - Animation Loop - Animation loop using colors
Configuration - Configure trail and fade