-
-
Save kmdm/c01c0693b1380d826af200a3e9b2a656 to your computer and use it in GitHub Desktop.
# MQTT broker configuration | |
mqtt: | |
broker: !secret mqtt_broker | |
username: !secret mqtt_username | |
password: !secret mqtt_password | |
discovery: False # Only if you use the HA API usually | |
id: mqtt_client | |
# Define the room for this ESP32 node | |
substitutions: | |
room_name: bedroom | |
# Push the room name into a global | |
globals: | |
- id: room_topic | |
type: std::string | |
initial_value: '"room_presence/${room_name}"' | |
# Configure the esp32_ble_tracker to push beacon advertisements to MQTT | |
esp32_ble_tracker: | |
on_ble_advertise: | |
- then: | |
- lambda: |- | |
if (x.get_ibeacon().has_value()) { | |
std::string uuid; | |
esp_bt_uuid_t raw_uuid = x.get_ibeacon().value().get_uuid().get_uuid(); | |
char sbuf[64]; | |
char *bpos = sbuf; | |
switch (raw_uuid.len) { | |
case ESP_UUID_LEN_128: | |
for (int8_t i = 0; i <= 15; i++) { | |
sprintf(bpos, "%02x", raw_uuid.uuid.uuid128[i]); | |
bpos += 2; | |
if (i == 6 || i == 8 || i == 10 || i == 12) | |
sprintf(bpos++, "-"); | |
} | |
sbuf[47] = '\0'; | |
uuid.assign(sbuf); | |
break; | |
default: | |
uuid = x.get_ibeacon().value().get_uuid().to_string(); | |
std::transform(uuid.begin(), uuid.end(), uuid.begin(), [](unsigned char c){ return std::tolower(c); }); | |
break; | |
} | |
char mbuf[32] = {0}; | |
sprintf(mbuf, "-%hu-%hu", x.get_ibeacon().value().get_major(), x.get_ibeacon().value().get_minor()); | |
uuid.append(mbuf); | |
int8_t tx_power = x.get_ibeacon().value().get_signal_power(); | |
if (tx_power >= 100) { | |
tx_power = -69; | |
} | |
float dist = pow(10, (float)(tx_power - x.get_rssi()) / (10 * 2)); | |
if (dist < 50) { | |
ESP_LOGD("ble_adv", "Sending MQTT room update for '%s' (%s): %.03fm (%d rssi, %d sigpow)", | |
x.get_name().c_str(), uuid.c_str(), dist, x.get_rssi(), tx_power); | |
id(mqtt_client).publish_json(id(room_topic), [=](JsonObject root) { | |
root["id"] = uuid; | |
root["name"] = x.get_name(); | |
root["distance"] = dist; | |
root["rssi"] = x.get_rssi(); | |
root["tx_power"] = tx_power; | |
}); | |
} else { | |
ESP_LOGD("ble_adv", "Skipping MQTT room update for '%s' (%s): %.03fm (%d rssi, %d sigpow)", | |
x.get_name().c_str(), uuid.c_str(), dist, x.get_rssi(), tx_power); | |
} | |
} |
# Configure the sensors in Home Assistant as normal: | |
sensor: | |
- platform: mqtt_room | |
name: Test beacon 1 | |
device_id: aabbccdd-eeff-1122-3344-5566778899aa-0001-0002 | |
state_topic: room_presence |
Is there a way we can modify this to include a maximum distance, so that anything over that distance doesn't get reported to HA. Similar to how Room Assistant works?
I know there's a power value, and a calculation to determine the distance so shouldn't be too difficult, however C++(?) isn't my strongest area. A simple if(distance < X) mqtt.publish
i guess would do it (in C++)?
Something like this: https://gist.github.com/greghesp/fec67e356d7d761bc626891dbd0d5032
Not sure if the logic or variable types are correctly done though
@greghesp Ah, & removed!
I think you mean if (dist < max_distance)
otherwise you're only submitting readings over the max_distance which seems to be the opposite of what you'd like!
Out of interest, what's the use case for filtering here instead of just letting HA decide which room the device is in?
@greghesp Ah, & removed!
I think you mean
if (dist < max_distance)
otherwise you're only submitting readings over the max_distance which seems to be the opposite of what you'd like!Out of interest, what's the use case for filtering here instead of just letting HA decide which room the device is in?
Whoops! Bit sleepy still. I'm also not sure if 5
is a correct float.
As for the distance. I've not got presence sensors in every room, so I may go into 1 room and it reports to HA that I'm in room X when I'm not even in a room with a sensor. This way, HA would just report that I'm home, rather than in a room im not
The bottom of this post gives a good example:
https://www.reddit.com/r/homeassistant/comments/ma02pv/how_to_fine_tune_room_assistant_ble/?utm_medium=android_app&utm_source=share
@greghesp I've updated the gist to include a better calculation for distance using the signal power reported by the BLE beacon. I've added a dist filter but just hardcoded it at 50.
(In the HA companion app you can set what this value is)
The check for a tx_power of 100 is for some weird beacons I have which appear to set the transmit power to 100 so it's just badly fixed back to the default I was using before, it could be unnecessary for you but you can monitor the rssi/tx_power values on the esp32 logs and also the MQTT broker since I've added those values there as well (although any dist >= 50 won't be on MQTT obviously).
@kmdm What is the dist value measured in? Im assuming its not meters?
Thank you so much for sharing it.
modify the max_distance and remove almost all false positives. Is there any other parameter that you recommend me to change?
Thanks again
@kmdm Would it be possible to specify only certain UUIDs?
@mihsu81 you can do this on the HA side. It'll just ignore the rest that's sent
It looks like PR 3289 was included in the latest 2022.3.1 version that is now available
@kmdm - I am now getting a compile failure though, seems the gist still includes the ampersand on line 60