Figured out: How to control a bluetooth device normally controlled via a shell script using esphome BLE, because Bluetooth Proxy can't do it

I have an unknown BLE device that is obscure and no integration exists or will exist. I have a working bash script that calls bluetoothctl and sends 3 commands to get it to do what I need it to do (turn on or turn off). It works fine.

The device is too far away from my HA Pi to be picked up by the bluetooth dongle. I have bought a few Atom Lite esp devices that work fine for “known” BLE devices for which integrations exist.

I believe that In order for me to use one of these Atom Lite devices as an HA bluetooth proxy, there needs to exist an HA integration for the BLE device.

I’ve had people telling me that this should all “just work” but I think they’re assuming that an HA integration exists. Since one doesn’t, is there any way for me to do the following in a bash / shell script, like I do using bluetoothctl:

  1. connect f0:74:59:49:c0:45
  2. select-attribute /org/bluez/hci0/dev_F0_74_59_49_C0_45/service001b/char001e
  3. send "select-attribute /org/bluez/hci0/dev_F0_74_59_49_C0_45/service001b/char001c
  4. send "write “0xa5 0x00 0x00 0x06 0x00 0x67 0x02 0xd8 0x00 0x03 0x10 0x01 0x02 0x12 0x01 0x08 0x2b 0x3b”

Can anyone tell me if my assumptions are correct - if they’re not, I’m keen to find any evidence supporting a method to connect to my BLE device via a shell script, where the device is only accessible via one of these Atom Lite esp32 devices.

That is correct.
bluetoothctl has no clue about HA’s bluetooth proxies.

I had to do the same for an unsupported BLE lightstrip.

But if you can decipher the bluetooth packets, esphome may help you. Not the proxy, but the other ble stuff.

Interesting.
Do you have a specific working example in mind or is theoretical?

Well in terms of sensors, there is an example here. Chinese bluetooth BBQ meat probe with ESP32 - #8 by paulo.richards

In terms of controlling a ble device, there are BLE Client Binary Output — ESPHome and so on.

1 Like

I was able to get this all working! I’m not sure I’ve done it correctly or optimally though so caveat emptor.

I bought several Atom Lite devices (and curiously, though I think I followed the same installation steps, at least one of them identifies as arduino in the sense that there’s arduino references in its configuration - yet the others don’t). I have one of these set up as a Bluetooth proxy for my AC Infinity fan and that’s working. So I then set up another one using the esphome web page, to control my obscure and unknown Bluetooth device (it’s a fibre optic star ceiling controller). I then edited the configuration to include ble_client and the appropriate _write commands.

A while ago I’d used sniffers etc to watch how the included phone app talks to the device and identified the service and attributes and the values sent to it. I’d turned that into a single line script to turn it on:

$gatttool --adapter=BC:14:EF:62:4A:B3 -i hci0 -b FF:21:03:29:C8:09 --char-write-req -a 0x000a -n a5ff010602ffdba4003900ff05ff01ff010500aa

What doesn’t show up here though is the service and characteristic UUID that’s needed. In order to recall the service uuid and characteristic uuid I had to go back into Bluetoothctl and connect to the device. Once connected it then lists all the values found for the device.

I could then replicate this one-liner in the esp32 yaml:

ble_client:
  - mac_address: FF:21:03:29:C8:09
    id: YX_LED
    on_connect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Connected to BLE device");
    on_disconnect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Disconnected from BLE device");

switch:
  - platform: template
    name: "starceiling"
    turn_on_action:
      - ble_client.ble_write:
          id: YX_LED
          service_uuid: 0000ffb0-0000-1000-8000-00805f9b34fb
          characteristic_uuid: 0000ffb1-0000-1000-8000-00805f9b34fb
          value: [0xa5, 0xff, 0x01, 0x06, 0x02, 0xff, 0xdb, 0xa4, 0x00, 0x39, 0x00, 0xff, 0x05, 0xff, 0x01, 0xff, 0x01, 0x05, 0x00, 0xaa]
      - ble_client.ble_write:
          id: YX_LED
          service_uuid: 0000ffb0-0000-1000-8000-00805f9b34fb
          characteristic_uuid: 0000ffb1-0000-1000-8000-00805f9b34fb
          value: [0xa5, 0xff, 0x01, 0x06, 0x02, 0xff, 0xdb, 0xa4, 0x00, 0x39, 0x00, 0xff, 0x05, 0xff, 0x01, 0xff, 0x01, 0x05, 0x00, 0xaa]

    turn_off_action:
      - ble_client.ble_write:
          id: YX_LED
          service_uuid: 0000ffb0-0000-1000-8000-00805f9b34fb
          characteristic_uuid: 0000ffb1-0000-1000-8000-00805f9b34fb
          value: [0xa5, 0x00, 0x01, 0x06, 0x02, 0xff, 0xdb, 0xa4, 0x00, 0x39, 0x00, 0xff, 0x05, 0xff, 0x01, 0xff, 0x01, 0x05, 0x00, 0xaa]
      - ble_client.ble_write:
          id: YX_LED
          service_uuid: 0000ffb0-0000-1000-8000-00805f9b34fb
          characteristic_uuid: 0000ffb1-0000-1000-8000-00805f9b34fb
          value: [0xa5, 0x00, 0x01, 0x06, 0x02, 0xff, 0xdb, 0xa4, 0x00, 0x39, 0x00, 0xff, 0x05, 0xff, 0x01, 0xff, 0x01, 0x05, 0x00, 0xaa]

this creates a switch entity in HA - just on or off right now but it works. Usually. It’s always been a bit flaky connecting to the device so I’ve simply executed the gatttool commands twice (send the “on” or “off” command twice). So in the esp32 yaml I also repeat the command twice.

1 Like

Very cool!
Maybe rename the thread to what you actually did (so not using a bluetooth proxy but esphome BLE) and mark your post as the solution, so that other users can find it properly…

Hello! Would you happen to still a copy of the script you made for controlling the ble device direct from your HA Raspberry Pi? I have an obscure Bluetooth led light that is right near my Pi and I’m using a really roundabout, inconsistent method at the moment. Thank you!

1 Like