Skip to content

Instantly share code, notes, and snippets.

@kmdm
Last active June 26, 2024 17:13
Show Gist options
  • Save kmdm/c01c0693b1380d826af200a3e9b2a656 to your computer and use it in GitHub Desktop.
Save kmdm/c01c0693b1380d826af200a3e9b2a656 to your computer and use it in GitHub Desktop.
esphome, esp32 ble tracker and Home Assistant mqtt_room sensors
# 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
@gastonMM
Copy link

gastonMM commented Aug 9, 2022

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

@mihsu81
Copy link

mihsu81 commented Dec 25, 2022

@kmdm Would it be possible to specify only certain UUIDs?

@greghesp
Copy link

@mihsu81 you can do this on the HA side. It'll just ignore the rest that's sent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment