Android app that behaves like an ESPHome Bluetooth proxy and exposes the ESPHome native API on 6053/tcp.
It is designed for Home Assistant users who want to run BLE proxying on an Android phone instead of on an ESP32.
- Runs as a foreground service with a persistent notification.
- Hosts an ESPHome-compatible native API server.
- Supports plaintext or Noise-encrypted ESPHome API transport.
- Forwards BLE advertisements to Home Assistant.
- Supports BLE GATT connections through the ESPHome Bluetooth proxy API.
- Supports pair, unpair, and clear-cache requests through Android BLE APIs.
- Publishes
_esphomelib._tcp.localmDNS/NSD advertisements. - Lets you choose which network transport mDNS should use:
auto,wifi,cellular,vpn, ordisabled. - Generates a stable default Bluetooth MAC identity and a stable default ESPHome API encryption key.
- Provides runtime logs in-app with copy, clear, and wrap toggle support.
- Preserves the most recent production crash locally with copy, save, and clear controls after restart.
-
Foreground, screen on: The app uses broad callback-based BLE scanning. This is the best mode for discovery and initial learning.
-
Background, screen on: The app keeps running through a foreground service, persistent notification, and partial wake lock. This is suitable for normal proxy use while another app is open.
-
Screen off / device locked: The app switches to targeted Android
ScanFilterentries built from the savedManaged Target Deviceslist if Lock-Screen Scanning is enabled for them. This is important because broad unfiltered scans are not reliable on locked devices on stock Android and Xiaomi firmware. -
Lock-screen target learning: If
Auto-add matched devicesis enabled and at least one advertisement filter is enabled, the app can learn exact MAC targets from matched advertisements while the screen is on.
- Install the app.
- Grant Bluetooth, location, and notification permissions.
- Set battery mode to unrestricted and enable any Xiaomi-specific
Autostart/No restrictionsbehavior. - Start the proxy from the home screen.
- If you want encrypted ESPHome API transport, keep the generated key or replace it with your own 32-byte base64 key.
- If your BLE device requires a PIN or passkey, pair it on the Android phone first and complete the system pairing dialog there. The proxy reuses Android's stored bond on reconnect.
- Add the device in Home Assistant through the ESPHome integration.
- If you use WireGuard or another VPN, set mDNS interface mode to
VPNso discovery is advertised on that transport. - If you need reliable scanning while the screen is locked:
Create one or more advertisement filters.
Enable
Auto-add matched devicesor manually add exact managed target devices with Lock-Screen Scanning enabled. Let the app see the devices while the screen is on. Lock the phone after those targets are saved.
There is no Home Assistant URL or Home Assistant API token in the normal flow. Home Assistant talks to the app over the ESPHome API directly.
-
ESPHome node name: Internal ESPHome device name used by the API server and mDNS. -
Friendly name: Human-readable label shown in Home Assistant. -
API port: TCP port used by the ESPHome API server. Default is6053. -
Scanner mode:Passiveuses lower-power scanning.Activeuses low-latency scanning and is usually better for aggressive discovery. -
Ad flush interval (ms): How often queued BLE advertisement updates are flushed to connected clients. -
Ad dedup window (ms): Per-address deduplication window for discovery traffic.0disables dedup. -
Discovery throttle interval (ms): Limits how often the same address is forwarded during discovery traffic. Devices unseen for 30 minutes are treated as rediscovered and forwarded immediately. -
Watchdog check interval (ms): How often the app evaluates scanner health. -
Low-rate checks before restart: How many consecutive poor-health samples are required before scanner recovery triggers. -
Advertisement filters: Regex-based rules applied with OR logic. If no enabled filters exist, the app forwards all advertisements. -
Managed Target Devices: A consolidated list of exact MAC addresses and/or exact device names. These determine behavior based on two toggles:- Lock-Screen Scanning: Used to build Android hardware scan filters when the screen is off.
- Auto-Pair Device: Forces the Android OS to immediately prompt for Bluetooth pairing/bonding natively upon connection, preventing GATT cache drops on strict BLE devices.
-
Auto-add matched devices: When enabled, advertisements that match at least one enabled advertisement filter can add an exact managed target device automatically. If no enabled advertisement filters exist, this feature stays idle and adds nothing. -
Bluetooth MAC address: Identity reported by the proxy. By default the app generates and persists a stable locally administered MAC address. -
ESPHome API encryption key: Base64-encoded 32-byte key for ESPHome Noise transport. Empty value means plaintext API transport. -
Verbose GATT packet logs: Keeps normal GATT state logs enabled while optionally adding per-packet notify data lines to the runtime log. Default isoffbecause it gets noisy quickly. -
mDNS advertise interface: Controls which transport NSD/mDNS registration should prefer.VPNis useful when you want discovery on WireGuard instead of local Wi-Fi. -
Auto start on boot: Starts the foreground proxy service after device boot.
- Screen-on broad discovery works without a saved target list.
- Screen-off scanning is intentionally target-based. Save exact devices via
Managed Target Devicesif you expect the proxy to keep seeing them while locked. - For Xiaomi devices, battery restrictions are often the difference between working and failing background BLE behavior.
- Pair, unpair, and clear-cache behavior depends on Android OEM BLE stack behavior.
- For strict Bluetooth devices (like certain motorcycle stacks) that require a PIN or passkey, you can enable
Auto-Pair Devicein the target list so the proxy triggers an OS-level pairing prompt natively before Home Assistant drops the connection. After Android stores the bond, the proxy safely avoids redundant discoveries.
If the app terminates unexpectedly, reopen it and look for the Previous Abnormal Exit card above the runtime log. Use Copy or Save to collect the report without USB debugging or Logcat, then use Clear after the problem is resolved.
The report is bounded, redacts common secrets and network/device addresses, stays in Android's no-backup app storage, and is never uploaded automatically. Java/Kotlin exceptions are captured on every supported Android version; Android 11 and newer also provide historical reasons for ANRs, native crashes, initialization failures, and memory/resource termination.
- Download APK directly
- Use Obtainium (recommended)
Requirements:
- Android SDK
- Java 17 or newer
JAVA_HOMEconfigured
Examples:
./gradlew :app:compileDebugKotlin
./gradlew :app:lintDebug
./gradlew :app:assembleReleaseYou can override the Android version fields at build time:
./gradlew :app:assembleRelease \
-PreleaseVersionName=2026.0.3 \
-PreleaseVersionCode=20260003The repository includes a tag-driven GitHub Actions workflow.
- Create a tag like
v2026.0.3 - Push the tag
- The workflow derives:
versionName=2026.0.3versionCode=20260003 - It builds the Android release APK
- It creates a GitHub release for that tag
- It uploads the APK and a SHA-256 checksum file
Current behavior:
- The workflow expects Android signing secrets and produces a signed installable release APK.
Required GitHub Actions repository secrets:
ANDROID_RELEASE_KEYSTORE_BASE64ANDROID_RELEASE_STORE_PASSWORDANDROID_RELEASE_KEY_ALIASANDROID_RELEASE_KEY_PASSWORD
Generate the base64 keystore payload with:
base64 -w 0 android-release.jks > android-release.jks.base64Implemented:
- ESPHome API hello, ping, disconnect, device info, and entity listing completion
- BLE advertisement forwarding
- BLE GATT connect, discover, read, write, descriptor access, and notifications
- BLE pair, unpair, and clear-cache requests
- mDNS interface selection
- Runtime log viewer and copy support
- Managed Target Devices configuration for lock-screen scanning and immediate auto-pairing
Known practical limitation:
- Broad BLE discovery while the device is locked is not reliable on stock Android. Use exact Lock-Screen Scanning toggles for locked scanning.





