ESPHome and Android Beacon Simulator - the perfect presence detection (almost there!)

I’m trying to combine Android Beacon Simulator, ESPHome and ble_presence for presence detection.

The Android Beacon Simulator emits an IBeacon with a UUID. I’m trying to capture that UUID with esphome as follows:

binary_sensor:
  - platform: ble_presence
    service_uuid: '50B04BBB-7B26-06AC-7441-92140A6A9E2b'
    name: "Ronald BLE GSM"

If I turn on very_verbose logging, I see the UUID passing by but it is not yet recognized by ESPHome.
So, I think there still is a bug… see https://github.com/esphome/issues/issues/1486

Is there anybody with some C++ knowledge and BLE knowledge who can chip in?

2 Likes

Mmm, I might be able to get it to work using

Bingo:

[00:24:29][D][ble_adv:404]: New BLE device
[00:24:29][D][ble_adv:415]:   Advertised manufacturer data:
[00:24:29][D][ble_adv:417]:     - 02.15.2B.9E.6A.0A.14.92.41.74.AC.06.26.7B.BB.4B.B0.50.00.00.00.00.BF (23)

This is broadcasted every 15sec or so. I hope I can finally make my presence detection working!

And? Did you?
:slight_smile:

You can share the code in ESP32. I’m not wise how to set it. Mac address is tracked phone? Service uuid id is uuid what creates Beacon Simulator? If I set up scan esp32 ble tracker won’t find mac phone.Thank you

1 Like

I tried the nrfConnect app and it works well for rssi ESP32, but I didn’t find how to let it run in the background so it’s not very useful.

Not yet - not enough time :frowning:

1 Like

Are you able to share your esphome.yaml file showing how you used
on_ble_manufacturer_data_advertise
and possibly your beacon simulator settings?

I can’t figure out how to get it working.
Thank you!

Here you go… if you make it happen, please share back :slight_smile:

esp32_ble_tracker:
  on_ble_advertise:
    - then:
        # - if: 
        #     condition:
        #       lambda: |-
        #         for (auto data : x.get_manufacturer_datas()) {
        #           return (strcmp(hexencode(data.data).c_str(), "02.15.2B.9E.6A.0A.14.92.41.74.AC.06.26.7B.BB.4B.B0.50.00.00.00.00.BF (23)") == 0);
        #         }
        #         return false;
        #     then:
              
        - lambda: |-
            ESP_LOGD("ble_adv", "New BLE device");
            ESP_LOGD("ble_adv", "  rssi: %d", x.get_rssi());
            ESP_LOGD("ble_adv", "  Advertised manufacturer data:");
            for (auto data : x.get_manufacturer_datas()) {
              ESP_LOGD("ble_adv", "    - %s", hexencode(data.data).c_str());
              if (strcmp(hexencode(data.data).c_str(), "02.15.2B.9E.6A.0A.14.92.41.74.AC.06.26.7B.BB.4B.B0.50.00.00.00.00.BF (23)") == 0) {
                ESP_LOGD("ble_adv", "in if");
              }
            }
2 Likes

I think this works

esp32_ble_tracker:
  on_ble_advertise:
    - then:
        - lambda: |-
            bool redmi_note_9_pro_status = false;
            
            for (auto data : x.get_manufacturer_datas()) {
              if (strcmp(hexencode(data.data).c_str(), "02.15.49.01.F3.6B.E9.1A.44.B7.B3.62.FF.2E.B6.43.05.04.00.00.00.00.BF (23)") == 0) {
                ESP_LOGD("ble_adv", "redmi_note_9_pro found");
                redmi_note_9_pro_status = true;
              }
              ESP_LOGD("ble_adv", "    - %s", hexencode(data.data).c_str());
            }
            
            id(redmi_note_9_pro).publish_state(redmi_note_9_pro_status);
            
            
binary_sensor:
  - platform: template
    device_class: presence
    name: "Redmi Note 9 Pro BLE presence"
    id: redmi_note_9_pro
    filters:
      - delayed_off: 3s

whit this code (thank @rdehuyss) I can track my android phone with the app beacon simulator

3 Likes

That’s better:

binary_sensor:
  - platform: template
    device_class: presence
    name: "Lenovo P2 BLE"
    id: Lenovo_P2

script:
  - id: ble_off_script
    mode: restart
    then:
      - binary_sensor.template.publish:
          id: Lenovo_P2
          state: true
      - delay: 60s
      - binary_sensor.template.publish:
          id: Lenovo_P2
          state: false

esp32_ble_tracker:
  on_ble_advertise:
    - then:
        - lambda: |-
            for (auto data : x.get_manufacturer_datas()) {
              if (strcmp(hexencode(data.data).c_str(), "02.15.1A.D3.91.06.87.AC.4D.35.A3.60.5A.96.49.FC.E7.2E.00.00.00.00.BF (23)") == 0) {
                ESP_LOGD("ble_adv", "Lenovo P2 found");
                id(ble_off_script).execute();
              }
              else
              {
                ESP_LOGD("ble_adv", "    - %s", hexencode(data.data).c_str());
              }
            }

2 Likes

thanks, and thank you to the original poster for this. I just got it working myself. I find the range is a bit limited to usefull for me… It is really only for one room around 5-6 m away from the ESP32 device.

how would this look for two devices?

This part I have figured out ofc.

  - id: ble_off_script_phone1
    mode: restart
    then:
      - binary_sensor.template.publish:
          id: Lenovo_P2
          state: true
      - delay: 60s
      - binary_sensor.template.publish:
          id: Lenovo_P2
          state: false
  - id: ble_off_script_phone2
    mode: restart
    then:
      - binary_sensor.template.publish:
          id: Lenovo_P3
          state: true
      - delay: 60s
      - binary_sensor.template.publish:
          id: Lenovo_P3
          state: false
  - id: etc

But what part needs to be copied in the “on_ble_advertise:” part?

Try this

esp32_ble_tracker:
  on_ble_advertise:
    - then:
        - lambda: |-
            for (auto data : x.get_manufacturer_datas()) {
              if (strcmp(hexencode(data.data).c_str(), "02.15.1A.D3.91.06.87.AC.4D.35.A3.60.5A.96.49.FC.E7.2E.00.00.00.00.BF (23)") == 0) 
              {
                ESP_LOGD("ble_adv", "Lenovo P2 found");
                id(ble_off_script_phone1).execute();
              }
              else if (strcmp(hexencode(data.data).c_str(), "02.15.1A.D3.91.06.87.AC.4D.35.A3.60.5A.96.49.FC.E7.2E.00.00.00.00.BF (23)") == 0) 
              {
                ESP_LOGD("ble_adv", "Lenovo P3 found");
                id(ble_off_script_phone2).execute();
              }
              else
              {
                ESP_LOGD("ble_adv", "    - %s", hexencode(data.data).c_str());
              }
            }
1 Like

Thanks. that looks nice and logical as well :slight_smile:

You may also need to increase the delay. I stopped at 120s for now.

If you go with the if, else if, else solution, I get a multiline warning.

Compiling /data/wemos_d1_mini_1/.pioenvs/wemos_d1_mini_1/src/main.cpp.o
src/main.cpp:331:3: warning: multi-line comment [-Wcomment]
   //     - lambda: !lambda "for (auto data : x.get_manufacturer_datas()) \n{\n  if (strcmp(hexencode(data.data).c_str(),\
   ^

but the code works anyway. So I dont bother too much about it.

PS, what is the range you guys get with this BLE solution?

Somewhere 5 meters. You can increase the power in Android Beacon Simulator, but that’s enough for me.

Is there any posibility to send to HA the RSSI power by a sensor addiotionally to send Home/Not Home binary sensor?.

I want to mix this functionnality with Room Assistant, but I don’t know how to do it…

Thanks,

Jose

Should be possible
Create a binary sensor and have it turn on off above of below a threshold. You can do inside ESPHOME code.
If you dont know how, i can look tonight

Thank you to everyone on this thread. I was finally able to get an RSSI sensor set up using Beacon Simulator. Until I came across this I couldn’t figure out why I could never find the beacon via UUID.

For anyone else that is trying to do the same, here’s the relevant yaml I used to get it to work, where C3:D1:26:E2:7E:B1:43:EF:AE:59:82:48:D5:33:17:1C is the UUID entered in the Beacon Simulator app:

esp32_ble_tracker:
  on_ble_advertise:
    - then:
        - lambda: |-
            if(x.get_ibeacon().has_value()) {
              auto ibeacon = x.get_ibeacon().value();
              if(strcmp(ibeacon.get_uuid().to_string().c_str(), "C3:D1:26:E2:7E:B1:43:EF:AE:59:82:48:D5:33:17:1C") == 0) {
                id(my_rssi).publish_state(x.get_rssi());
              }
            }

sensor:
  - platform: template
    id: my_rssi
    name: "$friendlyname My RSSI"
    icon: "mdi:mdi-signal-distance-variant"
    update_interval: never
    unit_of_measurement: "dBm"
    filters:
      - sliding_window_moving_average:
          window_size: 5
          send_every: 1
4 Likes