Step 0
Before you start
You need a Raspberry Pi with Bluetooth, Raspberry Pi OS Bookworm, Home Assistant admin access, physical access to each shade, and the owner's Tilt account if a new pairing key is required.
The original Tilt app may stop controlling that shade. Pair one shade at a time, keep the travel path clear, and begin with movement disabled.
Hardware button timing varies by shade revision. Use the physical pairing instructions for your model. The tool waits for the exact Tilt pairing advertisement and refuses ambiguous scans.
Step 1
Prepare Home Assistant
- Open Settings, Apps, Install app and install the official Mosquitto broker app.
- Create a dedicated bridge user under Settings, People, Users. Enable Advanced mode in your profile if Users is hidden.
- Accept the discovered MQTTintegration under Devices & services and leave discovery enabled.
Maintained reference: Home Assistant MQTT
Step 2
Install the bridge on the Pi
Place the Pi in the same room for the first run. The installer creates a locked-down service account and a disabled system service. It does not contact or move a shade.
git clone https://github.com/Sunrise-Labs-Dot-AI/tilt-local-bridge.git
cd tilt-local-bridge
sudo ./scripts/install.sh --activate --install-system-packagesStore the dedicated MQTT username and password in/etc/tilt-local-bridge/. Keep both files readable only by root and the tiltbridge service group.
Step 3
Pair exactly one shade
Put one shade into physical pairing mode, then run the one-shot tool. Your password is entered without echo and is never written to disk. The resulting 32-byte shade key is stored privately.
sudo env PYTHONPATH=/opt/tilt-local-bridge/src \
python3 -m tilt_local_bridge.tilt_pairing \
--output /var/lib/tilt-local-pairing/office_shade.key \
--scan-timeout 30 \
--permit-live-pairingEnter the account email and password at the interactive prompts. Success prints the shade's BLE address. Record it only in the protected local config, then install the key under/etc/tilt-local-bridge/keys/ and remove the staging copy. Do not paste pairing output into chat, logs, screenshots, or public issues. The email prompt is visible on screen, so redact it from any terminal output you share. The detailed pairing guide explains protected key import and ambiguous final acknowledgements.
Step 4
Configure, then verify without movement
Replace every sample value. The BLE address below is deliberately fake. Start with position writes set to false.
{
"version": 1,
"access": {
"allow_reads": true,
"allow_position_writes": false
},
"mqtt": {
"host": "homeassistant.local",
"port": 1883,
"username_file": "/etc/tilt-local-bridge/mqtt.username",
"password_file": "/etc/tilt-local-bridge/mqtt.password"
},
"shades": [{
"id": "office_shade",
"name": "Office Shade",
"mac": "02:00:00:00:00:01",
"pairing_key_file": "/etc/tilt-local-bridge/keys/office_shade.key"
}]
}Run check-runtime --expect-shade-reads, followed by a single probe-status --allow-shade-reads. A valid probe reports position, battery, charging state, and calibration without moving the shade.
Enable the read-only service. Home Assistant should discover one device per shade with a Cover, Position slider, and Battery sensor.
Step 5
Enable exact position control
Change allow_position_writes to true in the config, then add the independent launch-time gate:
sudo ./scripts/install.sh \
--activate \
--enable \
--allow-position-writesStart from a known calibrated endpoint and request a small change, such as 100 to 95 percent. During movement, the bridge publishes observed positions, keeps the cover available, blocks overlapping commands, and performs bounded readback checks.
Step 6
Add the covers to Google Home
Home Assistant Cloud
The shorter route. It is paid after the trial. Connect Google Assistant under Home Assistant Cloud, then expose only each shade's Cover entity.
Manual integration
No Home Assistant subscription fee. You need a public HTTPS Home Assistant URL, a Google Home developer project, HomeGraph, and a service account.
For the free route, follow Home Assistant's maintained manual Google Assistant flow, then allowlist only your cover entities:
google_assistant:
project_id: YOUR_PROJECT_ID
service_account: !include SERVICE_ACCOUNT.json
report_state: true
expose_by_default: false
entity_config:
cover.office_shade:
name: Office Shade
expose: true
room: OfficeMaintained reference: manual Google Assistant setup
Recovery
Know the exit path
Stop all local control withsudo systemctl disable --now tilt-local-bridge.service. This does not change the key again. To keep status but remove movement, set the write gate to false and reinstall without--allow-position-writes.
Pairing relies on legacy account endpoints that Sunrise Labs does not operate. If those endpoints disappear, an existing protected shade key can continue to support local control, but this project cannot manufacture a replacement key offline.