App# 🚗 BYD App Bridge (Wireless ADB + MQTT)
A self-healing bridge that connects the official BYD Android App to Home Assistant.
This project runs a Python script in a Docker container that communicates with a dedicated Android phone over Wireless ADB. It "scrapes" the UI of the BYD app to read sensors (Range, SoC, Tire Pressure, Location) and interacts with onscreen buttons to send commands (Lock, Unlock, AC).
The Python script does not handle the connection; it assumes the environment has a valid ADB session. The Docker container handles the Wireless ADB connection at startup.
-
⚡ Adaptive Polling Engine:
- Driving: Polls every 120s (configurable).
- Charging: Polls every 60s.
- Deep Sleep: Polls every 300s (5 mins) when car is off.
- Instant Wake: Command queue executes actions immediately (e.g., Unlock) without waiting for the next poll cycle.
-
🛡️ Robustness:
- Ghosting Protection: Filters out placeholder values (
--,---) so Home Assistant history remains clean. - Race Condition Locking: A global sequence lock prevents commands from firing while the screen is being swiped/read.
- Smart Recovery: Detects if the app is crashed or stuck on the wrong screen and automatically relaunches/navigates back to home.
- Screen Wake Failsafe: Detects if the screen is off (using
dumpsys power) and automatically wakes/swipes up to resume scraping. - Button Refresh: Uses the dedicated "Refresh" button on the home screen for reliable data updates (replacing unreliable swipe gestures).
- Health Watchdog: Exposes a
/healthzHTTP endpoint (default port 8080) that reports 503 if the main loop stalls for >10 minutes.
- Ghosting Protection: Filters out placeholder values (
- Dedicated Android Phone:
- Developer Options enabled.
- USB Debugging enabled.
- Screen Timeout set to "Never" (or "Stay Awake" in Dev Options).
- BYD App installed and logged in (tick "Remember Me").
- Network:
- The phone must be on the same network as the Docker host.
- You need the phone's Static IP Address.
You only need to do this once per phone reboot.
- Connect the phone to your computer (or Docker host) via USB cable.
- Open a terminal/command prompt.
- Run the command to switch ADB to TCP/IP mode:
adb tcpip 5555
- Unplug the USB cable. The phone is now listening for wireless connections.
The container is configured to automatically connect to the phone IP on startup.
Option A: Docker Compose (Recommended)
- Copy the content of
docker-compose.ymlor create a file with that name. - Edit the file to set your
PHONE_IPandMQTT_BROKER. - Start the bridge:
docker-compose up -d
Option B: Docker Run Run the following command (replace variables as needed):
docker run -d --name byd-bridge --restart unless-stopped -e PHONE_IP=192.168.1.x -e MQTT_BROKER=192.168.1.x -e TZ=UTC -v adb_keys:/root/.android ghcr.io/lifeandfate1/byd-bridge:latestNote
The container exposes port 8080 internally for health checks (/healthz). You can map this if needed with -p 8080:8080, but it is not required for normal operation.
Tip
The -v adb_keys:/root/.android volume persists your ADB authentication keys. This means you won't have to tap "Allow USB Debugging" on your phone every time you update the container.
Go to Settings > Devices & Services > MQTT. A new device BYD App Bridge will appear automatically.
| Variable | Default | Description |
|---|---|---|
PHONE_IP |
None | Required. The LAN IP of your Android phone (e.g., 192.168.1.55). |
TZ |
UTC |
Timezone for logs and health check (e.g., Europe/Zurich). |
MQTT_BROKER |
None | Required. IP of Home Assistant/Mosquitto. |
MQTT_PORT |
1883 |
Port for MQTT. |
MQTT_USER |
None | Username for MQTT. |
MQTT_PASS |
None | Password for MQTT. |
ADB_PORT |
5555 |
Port for ADB. |
| Variable | Default | Description |
|---|---|---|
POLL_SHUTDOWN_SECONDS |
300 |
Interval when car is "Switched off" (Deep Sleep). |
POLL_CHARGING_SECONDS |
60 |
Interval when car is charging. |
POLL_RUNNING_SECONDS |
120 |
Interval when car is driving/running. |
| Variable | Default | Description |
|---|---|---|
POLL_VEHICLE_STATUS |
True |
Scrapes Tire Pressure/Doors page. |
POLL_AC |
True |
Scrapes AC page. |
BYD_PIN |
None | Required for Actions. Your car's PIN code. |
| Variable | Default | Description |
|---|---|---|
MQTT_TOPIC_BASE |
byd/app |
Topic prefix. |
BYD_DEVICE_ID |
byd-vehicle |
Unique ID for HA discovery. |
BYD_DEVICE_NAME |
BYD Vehicle |
Friendly name in HA. |
HTTP_STATUS_PORT |
8080 |
Port for health check/metrics. |
DISCOVERY_PREFIX |
homeassistant |
MQTT discovery prefix. |
You can supply sensitive variables via files (e.g., Docker Secrets) by appending _FILE to the variable name.
MQTT_BROKER_FILEPHONE_IP_FILEMQTT_USER_FILEMQTT_PASS_FILEBYD_PIN_FILE
Example:
environment:
- MQTT_PASS_FILE=/run/secrets/mqtt_password
secrets:
- mqtt_passwordQ: The container loops with "Host is down" or "Connection refused".
- Cause: The phone is not in TCP/IP mode.
- Fix: You must plug the phone into USB and run
adb tcpip 5555again (Phase 1). This resets if the phone reboots.
Q: "Unauthorized" in logs.
- Cause: The phone received the connection request but you didn't click "Allow" on the screen.
- Fix: Unlock the phone screen, restart the container, and watch for the "Allow USB Debugging?" popup. Check "Always allow".
Q: Sensors are unavailable.
- Check the logs (
docker logs byd-bridge). If the script cannot dump the XML, it won't publish data.

