A custom Home Assistant integration for controlling Sandsara Mini Pro kinetic sand tables via Bluetooth Low Energy (BLE).
- Light Control: On/off, brightness, RGB color
- Media Player: Play, pause, next track, sleep
- Ball Speed Control: Adjustable motor speed (1-100)
- LED Animation Speed: Adjustable LED rotation speed (1-100)
- Auto-Discovery: Automatically detects Sandsara devices via Bluetooth
- ESP32 BLE Proxy Support: Works with ESPHome Bluetooth proxies
- Home Assistant 2024.1.0 or newer
- Bluetooth adapter or ESP32 BLE proxy with available connection slot
- Sandsara Mini Pro (firmware v6.3.1 tested)
- Install HACS if you haven't already: HACS Installation Guide
- Add Custom Repository:
- Go to HACS → Integrations
- Click the three dots menu (⋮) → Custom repositories
- Add repository URL:
https://github.com/monxas/sandsara-hacs - Category: Integration
- Click ADD
- Install Integration:
- Search for "Sandsara" in HACS
- Click DOWNLOAD
- Restart Home Assistant
- Add Integration:
- Go to Settings → Devices & Services
- Click "+ ADD INTEGRATION"
- Search for "Sandsara"
- Follow the configuration wizard
- Copy the
custom_components/sandsarafolder to your Home Assistantconfig/custom_components/directory - Restart Home Assistant
- Go to Settings → Devices & Services → Add Integration → Sandsara
Once configured, the integration creates the following entities:
| Entity | Type | Description |
|---|---|---|
light.sandsara_led |
Light | LED on/off, brightness, color |
media_player.sandsara_playback |
Media Player | Play/pause/next/stop |
number.sandsara_ball_speed |
Number | Motor speed (1-100) |
number.sandsara_led_animation_speed |
Number | LED rotation speed (1-100) |
The Sandsara requires a persistent BLE connection to operate. This means:
- The device occupies one BLE connection slot permanently
- If using ESP32 proxies, ensure
max_connectionsis set high enough (default is 3) - The ball stops moving when the BLE connection drops
If your Sandsara is only reachable via ESP32 BLE proxies, increase the connection limit in the proxy's ESPHome config:
bluetooth_proxy:
active: true
cache_services: true
max_connections: 5The Mini Pro requires colors to be sent as gradients, even for solid colors. The integration handles this automatically.
See docs/PROTOCOL_NOTES.md for the complete reverse-engineered BLE protocol specification.
Sandsara uses a unique "binary CSV" format for pattern files (.bin). Each point is 6 bytes:
| Offset | Size | Description |
|---|---|---|
| 0 | 2 | X coordinate (int16, little-endian) |
| 2 | 1 | Comma separator (0x2C) |
| 3 | 2 | Y coordinate (int16, little-endian) |
| 5 | 1 | Newline (0x0A) |
Coordinates range from -32768 to +32767, representing positions on a unit circle.
import struct
def parse_sandsara_pattern(filepath):
"""Parse a Sandsara .bin pattern file into (x, y) tuples."""
with open(filepath, 'rb') as f:
data = f.read()
points = []
for i in range(0, len(data), 6):
if i + 6 > len(data):
break
# X (int16 LE) + ',' + Y (int16 LE) + '\n'
x = struct.unpack('<h', data[i:i+2])[0]
y = struct.unpack('<h', data[i+3:i+5])[0]
# Normalize to -1.0 to 1.0
points.append((x / 32767.0, y / 32767.0))
return pointsThe web/ directory contains a web-based pattern viewer built with FastAPI.
cd web
pip install fastapi uvicorn
python app.py
# Open http://localhost:8095| Method | Endpoint | Description |
|---|---|---|
| GET | /api/patterns |
List all available pattern files |
| GET | /api/patterns/{name} |
Get parsed points for a pattern |
| POST | /api/patterns/upload |
Upload a new .bin pattern |
| POST | /api/patterns/generate/{type} |
Generate test pattern (circle, spiral, flower, star) |
The tools/ directory contains Python scripts for direct device communication:
sandsara_controller.py- CLI controller for testingsandsara_test_server.py- Persistent connection server for protocol exploration
Your BLE proxies are full. Either:
- Increase
max_connectionsin your ESP32 proxy config - Move the Sandsara closer to your HA server's built-in Bluetooth adapter
- Disconnect other BLE devices to free up slots
- Check Settings → System → Logs for "sandsara" entries
- Verify the device is connected (entities should be "available")
- Ensure the init handshake completed (look for "Sandsara initialized" in logs)
- Ensure Sandsara is powered on
- Check that at least one Bluetooth adapter/proxy can see it
- The device advertises with service UUID
fd31a2be-22e7-11eb-adc1-0242ac120002
MIT
Protocol reverse-engineered from the official Sandsara Android app and HCI packet captures.