No idea if this has been covered before but my plan is to put a bunch of esphome ESP-32 based sensor nodes around the house (standard stuff) but I was also thinking that with the ESP-32’s having BLE built-in it would be good if those nodes could also act as BLE room presence sensors to avoid having to install dedicated nodes with, say, ESP32-mqtt-room on them.
I couldn’t find a sensible way of doing this “out of the box” with esphome but I have managed to create something that appears to work quite well with my solitary test iBeacon (nrf51822) and test sensor node.
I think that your approach is very interesting. I’m using some esp32 directly with mqtt_room integration and it’s working well, but access by ESPHome is more easy to configure and change parameters and upload to the esp32 devices. But integrating directly with mqtt_room (without ESPHome) I use Atom to upload the configuration to each ESP32, but in this integration you can fix the distance that you consider when a beacon for example is in one room or not. I cant see in your approach how is possible to fix this distance for each room esp32 that I have.
For example, in the configuration file that I use there are the following variables that you can fix to change some functionalities:
// Define bluetooth scan parameters
#define scanInterval 5 // Define the interval in seconds between scans
#define singleScanTime 5 // Define the duration of a single scan in seconds
#define activeScan true // Active scan uses more power, but get results faster
#define bleScanInterval 0x80 // Used to determine antenna sharing between Bluetooth and WiFi. Do not modify unless you are confident you know what you're doing
#define bleScanWindow 0x10 // Used to determine antenna sharing between Bluetooth and WiFi. Do not modify unless you are confident you know what you're doing
// Maximum distance (in meters) to report. Devices that are calculated to be further than this distance in meters will not be reported
#define maxDistance 6
Waht do you think about this?,
mmmm, its is possible to define the distance modifiying your code, for example:
Similar situation here, and I like the look of how you’re doing this.
I used your code, however I’m not seeing my phone show up anywhere (using the Beacon suppor tin the Android app)
My full yaml is below. If I don’t use your lamda function and disable the mqtt functionality, then it shows up as a binary sensor in HA, so I know the BLE part works there from the ESP32. Any ideas?
esphome:
name: office-plant-monitor
platform: ESP32
board: esp-wrover-kit
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
substitutions:
room_name: office
globals:
- id: room_topic
type: std::string
initial_value: '"room_presence/${room_name}"'
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.1.242
gateway: 192.168.1.1
subnet: 255.255.255.0
ap:
ssid: "Office-Esp32 Fallback Hotspot"
password: "h3KtOafB1jpR"
esp32_ble_tracker:
on_ble_advertise:
- then:
- lambda: |-
if (x.get_ibeacon().has_value()) {
// Convert the uuid from 11:22:33:44:55... to 12345678-1234-1234-1234....
std::string orig_uuid = x.get_ibeacon().value().get_uuid().to_string();
std::string uuid;
std::transform(orig_uuid.begin(), orig_uuid.end(), orig_uuid.begin(),
[](unsigned char c){ return std::tolower(c); });
for (int i = 0; i < 46; i += 3) {
uuid.append(orig_uuid.substr(i, 2));
if (i == 3 * 3 || i == 5 * 3 || i == 7 * 3 || i == 9 * 3) {
uuid.append("-");
}
}
// Add major and minor to the uuid
char sbuf[11] = {0};
uint16_t major = x.get_ibeacon().value().get_major();
uint16_t minor = x.get_ibeacon().value().get_minor();
sprintf(sbuf, "-%02x%02x-%02x%02x",
major >> 8, major & 0xFF, minor >> 8, minor & 0xFF);
uuid.append(sbuf);
// Calculate the distance
int8_t tx_power = -69;
float dist = pow(10, (float)(tx_power - x.get_rssi()) / (10 * 2));
ESP_LOGD("ble_adv", "Sending MQTT room update for '%s' (%s): %.03fm (%d rssi)",
x.get_name().c_str(), uuid.c_str(), dist, x.get_rssi());
id(mqtt_client).publish_json(id(room_topic), [=](JsonObject &root) {
root["id"] = uuid;
root["name"] = x.get_name();
root["distance"] = dist;
});
}
binary_sensor:
- platform: ble_presence
ibeacon_uuid: '9aef3cee-c905-408d-b90e-53dc2b2e0782'
name: "Greg Phone Beacon"
sensor:
- platform: xiaomi_hhccjcy01
mac_address: 'C4:7C:8D:6C:D5:7E'
temperature:
name: "Rubber Plant Temperature"
moisture:
name: "Rubber Plant Moisture"
illuminance:
name: "Rubber Plant Illuminance"
conductivity:
name: "Rubber Plant Soil Conductivity"
battery_level:
name: "Rubber Plant Battery Level"
- platform: xiaomi_hhccjcy01
mac_address: 'C4:7C:8D:6C:08:EA'
temperature:
name: "Avocado Plant Temperature"
moisture:
name: "Avocado Plant Moisture"
illuminance:
name: "Avocado Plant Illuminance"
conductivity:
name: "Avocado Plant Soil Conductivity"
battery_level:
name: "Avocado Plant Battery Level"
- platform: wifi_signal
name: "Office Plant Monitor Signal Sensor"
update_interval: 60s
- platform: uptime
name: "Office Plant Monitor Uptime Sensor"
# Enable logging
logger:
level: VERBOSE
# Enable Home Assistant API
api:
ota:
Ah that makes sense! I’m just trying it now, but still seemingly have the same problem.
I can see all the requests for my Xiaomi plant sensors showing up and sending, but it doesn’t seem to detect the phone from the advertisement. Only as a binary sensor
Ah OK, now I’ve got it working, however the name is blank from the HA app and Beacon Simulator [17:20:24][D][ble_adv:063]: Sending MQTT room update for '' (9aef3ceec90540-8db9-0e53-dc2b-2e0782-100-1): 3.981m (-81 rssi)
It seems this isn’t broadcast from Android, however I’ve noticed that in the app, my uuid is 9aef3cee-c905-408d-b90e-53dc2b2e0782, however the your function seems to record it as 9aef3ceec90540-8db9-0e53-dc2b-2e0782-100-1
I’ve put together something similar, adding a filtering scheme similar to ESPresense. It also only reports devices that are manually whitelisted, and reports unknown when the beacon is not detected for a configurable amount of time. It uses a template sensor and the HA API instead of MQTT, and the logic is in a header file so your lambdas are a single line instead of cluttering up the config file. It’s available on github at GitHub - rpatel3001/BleDistance: Distance tracking for BLE iBeacons in esphome
Kenny, I think your approach might be simplified by using the ble_rssi sensor and a template sensor that calculates the distance in a lambda instead of doing all the processing that’s already in ble_rssi.