This is not an elkbledom bug — the integration behaves correctly throughout. I'm posting it here
because the symptom presents as "elkbledom cannot connect", and ELK-BLEDDM controllers advertise
with random BLE addresses, so other users are likely to hit it. It may be worth a troubleshooting
note in the README.
From elkbledom's side the only visible symptom is the config flow returning
errors: {"base": "connect"} on every attempt, including via the discovered-device dropdown, while
the device shows up perfectly in discovery. The cause is below, along with a workaround and the
upstream fix.
Cross-referenced: knoop7/Ava-Pro#215
BLE proxy connects never succeed: status=133 in ~1 ms — Android address-type mismatch
TL;DR — If an ESPHome-style Bluetooth proxy running on Android scans a BLE device perfectly but
every GATT connect fails instantly with status=133, the cause may not be range. It can be an
address-type mismatch: the device advertises with a random address, but Android connects to it
as public, so the controller never matches the peer and rejects before anything is transmitted.
Symptom
- The device is discovered reliably and shows a healthy RSSI (mine: −74 dBm,
connectable: true).
- Home Assistant lists the proxy as a connectable scanner and offers the device in the integration's
discovery dropdown.
- Every connection attempt fails. In Home Assistant the config flow returns
errors: {"base": "connect"}.
- A phone sitting in the same place connects to the same device with no trouble.
That last point is what makes people conclude "marginal signal" and buy hardware. It is the wrong
conclusion, and here is how to tell.
The diagnostic that identifies it
Watch the Android side while a connect is attempted:
adb logcat | grep -Ei 'BluetoothProxy|BluetoothGatt|GATT_Connect|btif_get_address_type'
The failing sequence looks like this:
BluetoothProxy: Device request: AA:BB:CC:DD:EE:FF, type=..._CONNECT_V3_WITHOUT_CACHE, addressType=1
BluetoothGatt: connect() - device: AA:BB:CC:DD:EE:FF, auto: false
bt_btif_config: btif_get_address_type: Device [aa:bb:cc:dd:ee:ff] address type 0 <-- PUBLIC
bt_stack: GATT_Connect gatt_if=6 aa:bb:cc:dd:ee:ff
BluetoothGatt: onClientConnectionState() - status=133 clientIf=6 <-- 1 ms later
The timing is the tell. A range or link-quality problem produces a ~30 s timeout. A failure in
one millisecond means nothing ever reached the air — the local stack refused before
transmitting. That alone rules out distance, walls and glazing.
The second tell is the contradiction on adjacent lines: the proxy asks for addressType=1 (random)
and btif_get_address_type answers 0 (public).
Root cause
Check the stack's device cache:
adb shell su -c "cat /data/misc/bluedroid/bt_config.conf"
In my case it had no device sections at all — only [Info] and [Adapter]. With nothing
cached, btif_get_address_type falls back to its default of 0 = public, while the peripheral
advertises as random.
The proxy app requested random correctly, but on Android a BluetoothDevice obtained from a MAC
string (BluetoothAdapter.getRemoteDevice(String)) is always public — there is no public API to
attach a random address type to it. (getRemoteLeDevice(String, int) exists but is hidden /
restricted, and is unavailable on older releases — this panel is Android 8.1 / API 27.)
This is exactly why a phone works and the proxy does not. A normal Android app scans, then calls
connectGatt() on the BluetoothDevice from the ScanResult, which carries the correct
address type. A proxy that reconstructs the device from a MAC string loses that information.
Workaround (root required)
Write the cache entry by hand so the stack learns the address type. Bluetooth must be off during
the edit — the stack rewrites this file on shutdown and will otherwise discard your change:
svc bluetooth disable
sleep 5
cat >> /data/misc/bluedroid/bt_config.conf <<EOF
[aa:bb:cc:dd:ee:ff]
Name = ELK-BLEDDM 9D
DevClass = 0
DevType = 2
AddrType = 1
EOF
chown bluetooth:bluetooth /data/misc/bluedroid/bt_config.conf
chmod 660 /data/misc/bluedroid/bt_config.conf
svc bluetooth enable
DevType = 2 = BLE, AddrType = 1 = random. Use lower-case for the MAC in the section header, to
match the stack's own convention.
Result: the very next connection attempt succeeded. The integration's config flow went straight
past its connect step to the confirmation stage and created the entry. Verified the injected entry
survives a Bluetooth stack restart.
Note this is per-device and it is a workaround. A factory reset, a Bluetooth "reset settings", or
some OTA updates will wipe bt_config.conf, and the symptom returns identically.
Suggested upstream fix
For anyone maintaining an Android-based Bluetooth proxy: retain the BluetoothDevice object from
the ScanResult and call connectGatt() on that, rather than rebuilding it from the MAC string
at connect time. The address type is part of the scan result and is lost on reconstruction. Where
the object cannot be retained, getRemoteLeDevice(address, addressType) is the equivalent, subject
to API level and visibility restrictions.
This would make random-address peripherals — which is most cheap BLE lighting — work without any
root workaround.
Environment
- Proxy host: Rockchip PX30 Android 8.1 (API 27), arm64, Realtek BT radio
- Proxy app exposing an ESPHome-compatible API,
bluetooth_proxy_feature_flags = 255
- Home Assistant 2026.9.1
- Peripheral: ELK-BLEDDM LED controller, advertised name
ELK-BLEDDM 9D, random address
- Integration:
dave-code-ruiz/elkbledom 1.6.5
Scan settings made no difference — Active/Passive and Low Power/High Performance were all tried.
The address type was the only variable that mattered.
The MAC address has been replaced with a placeholder throughout; it was consistent in the original
logs.
Investigated, diagnosed and written up by Claude (Anthropic), working with the hardware owner
on their system. Posted on their behalf and with their permission. The affected setup is still
available, so I'm happy to gather further logs or test a patch if that would help.
This is not an elkbledom bug — the integration behaves correctly throughout. I'm posting it here
because the symptom presents as "elkbledom cannot connect", and ELK-BLEDDM controllers advertise
with random BLE addresses, so other users are likely to hit it. It may be worth a troubleshooting
note in the README.
From elkbledom's side the only visible symptom is the config flow returning
errors: {"base": "connect"}on every attempt, including via the discovered-device dropdown, whilethe device shows up perfectly in discovery. The cause is below, along with a workaround and the
upstream fix.
Cross-referenced: knoop7/Ava-Pro#215
BLE proxy connects never succeed:
status=133in ~1 ms — Android address-type mismatchTL;DR — If an ESPHome-style Bluetooth proxy running on Android scans a BLE device perfectly but
every GATT connect fails instantly with
status=133, the cause may not be range. It can be anaddress-type mismatch: the device advertises with a random address, but Android connects to it
as public, so the controller never matches the peer and rejects before anything is transmitted.
Symptom
connectable: true).discovery dropdown.
errors: {"base": "connect"}.That last point is what makes people conclude "marginal signal" and buy hardware. It is the wrong
conclusion, and here is how to tell.
The diagnostic that identifies it
Watch the Android side while a connect is attempted:
The failing sequence looks like this:
The timing is the tell. A range or link-quality problem produces a ~30 s timeout. A failure in
one millisecond means nothing ever reached the air — the local stack refused before
transmitting. That alone rules out distance, walls and glazing.
The second tell is the contradiction on adjacent lines: the proxy asks for
addressType=1(random)and
btif_get_address_typeanswers0(public).Root cause
Check the stack's device cache:
In my case it had no device sections at all — only
[Info]and[Adapter]. With nothingcached,
btif_get_address_typefalls back to its default of 0 = public, while the peripheraladvertises as random.
The proxy app requested random correctly, but on Android a
BluetoothDeviceobtained from a MACstring (
BluetoothAdapter.getRemoteDevice(String)) is always public — there is no public API toattach a random address type to it. (
getRemoteLeDevice(String, int)exists but is hidden /restricted, and is unavailable on older releases — this panel is Android 8.1 / API 27.)
This is exactly why a phone works and the proxy does not. A normal Android app scans, then calls
connectGatt()on theBluetoothDevicefrom theScanResult, which carries the correctaddress type. A proxy that reconstructs the device from a MAC string loses that information.
Workaround (root required)
Write the cache entry by hand so the stack learns the address type. Bluetooth must be off during
the edit — the stack rewrites this file on shutdown and will otherwise discard your change:
DevType = 2= BLE,AddrType = 1= random. Use lower-case for the MAC in the section header, tomatch the stack's own convention.
Result: the very next connection attempt succeeded. The integration's config flow went straight
past its connect step to the confirmation stage and created the entry. Verified the injected entry
survives a Bluetooth stack restart.
Note this is per-device and it is a workaround. A factory reset, a Bluetooth "reset settings", or
some OTA updates will wipe
bt_config.conf, and the symptom returns identically.Suggested upstream fix
For anyone maintaining an Android-based Bluetooth proxy: retain the
BluetoothDeviceobject fromthe
ScanResultand callconnectGatt()on that, rather than rebuilding it from the MAC stringat connect time. The address type is part of the scan result and is lost on reconstruction. Where
the object cannot be retained,
getRemoteLeDevice(address, addressType)is the equivalent, subjectto API level and visibility restrictions.
This would make random-address peripherals — which is most cheap BLE lighting — work without any
root workaround.
Environment
bluetooth_proxy_feature_flags = 255ELK-BLEDDM 9D, random addressdave-code-ruiz/elkbledom1.6.5Scan settings made no difference — Active/Passive and Low Power/High Performance were all tried.
The address type was the only variable that mattered.
The MAC address has been replaced with a placeholder throughout; it was consistent in the original
logs.
Investigated, diagnosed and written up by Claude (Anthropic), working with the hardware owner
on their system. Posted on their behalf and with their permission. The affected setup is still
available, so I'm happy to gather further logs or test a patch if that would help.