Skip to content

Instantly share code, notes, and snippets.

@patrickdk77
Last active February 17, 2021 00:22
Show Gist options
  • Save patrickdk77/168c001abdbf5548887ef284b6096709 to your computer and use it in GitHub Desktop.
Save patrickdk77/168c001abdbf5548887ef284b6096709 to your computer and use it in GitHub Desktop.
HomeAssistant mqtt_room presense detection
# https://www.home-assistant.io/integrations/mqtt_room
substitutions:
display_name: "Tracker01"
name: tracker01
heartbeat: "900s"
defaulttxrssi: "-72"
maxdistance: "5.0"
room: "garage"
channel: "room_presence"
tele: "presense_nodes/${name}/tele"
availability: "presense_nodes/${room}"
esphome:
name: "${name}"
platform: ESP32
board: mhetesp32minikit
board_flash_mode: dout
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_pass
fast_connect: true
manual_ip:
static_ip: !secret ip_tracker01
gateway: !secret ip_gateway
subnet: !secret ip_subnet
dns1: !secret ip_dns1
dns2: !secret ip_dns2
logger:
baud_rate: 0
ota:
#web_server:
# port: 80
#api:
globals:
- id: devices
type: int
restore_value: false
initial_value: "0"
- id: reported
type: int
restore_value: false
initial_value: "0"
mqtt:
id: mqttid
broker: !secret mqtt_broker
port: !secret mqtt_port
username: !secret mqtt_user
password: !secret mqtt_pass
discovery: true
discovery_retain: true
birth_message:
topic: "${availability}"
payload: "CONNECTED"
will_message:
topic: "${availability}"
payload: "DISCONNECTED"
# reboot_timeout: 0s
log_topic:
esp32_ble_tracker:
scan_parameters:
active: false
# window: 140ms
# interval: 320ms
on_ble_advertise:
- then:
- lambda: |-
char buf[256];
int rssi=(int)x.get_rssi();
id(devices)++;
if(!strcmp(x.get_name().c_str(),"Apple Pencil")) return;
for (auto data : x.get_manufacturer_datas()) {
if(data.uuid.contains(0x06, 0x00)) { // Microsoft 0x0600
return;
}
if(data.uuid.contains(0x4C, 0x00)) { // Apple 0x4c00
if(data.data[0]==0x02 && data.data[1]==0x15) { // iToken 0x02 and length 0x05
float ratio,dist;
if(rssi==0)
dist=-1;
else {
int txrssi=(signed char)data.data[22];
if(txrssi==0) txrssi=${defaulttxrssi};
if(txrssi>0) txrssi*=-1;
ratio=(float)rssi*1.0/(float)txrssi;
if(ratio<1.0)
dist=pow(ratio,10);
else
dist=(0.89976) * pow(ratio,7.7095) + 0.111;
}
if(dist<(float)${maxdistance}) {
sprintf(buf,"{ \"id\":\"%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x-%u-%u\", \"uuid\":\"%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x\", \"major\":%u, \"minor\":%u, \"rssi\"=%d, \"txPower\":%d, \"distance\":%.2f, \"type\":\"iToken\" }",
data.data[2],data.data[3],data.data[4],data.data[5],data.data[6],data.data[7],data.data[8],data.data[9],data.data[10],data.data[11],data.data[12],data.data[13],data.data[14],data.data[15],data.data[16],data.data[17],
((unsigned)data.data[18]<<8)+(unsigned)data.data[19],
((unsigned)data.data[20]<<8)+(unsigned)data.data[21],
data.data[2],data.data[3],data.data[4],data.data[5],data.data[6],data.data[7],data.data[8],data.data[9],data.data[10],data.data[11],data.data[12],data.data[13],data.data[14],data.data[15],data.data[16],data.data[17],
((unsigned)data.data[18]<<8)+(unsigned)data.data[19],
((unsigned)data.data[20]<<8)+(unsigned)data.data[21],
rssi,(signed char)data.data[22],dist);
id(mqttid).publish("${channel}/${room}",buf);
id(reported)++;
}
}
return;
}
if(data.data[0]==0xbe && data.data[1]==0xac && data.data.size()==24) { // Alt Beacon
float ratio,dist;
if(rssi==0)
dist=-1;
else {
int txrssi=(signed char)data.data[22];
if(txrssi==0) txrssi=${defaulttxrssi};
if(txrssi>0) txrssi*=-1;
ratio=(float)rssi*1.0/(float)txrssi;
if(ratio<1.0)
dist=pow(ratio,10);
else
dist=(0.89976) * pow(ratio,7.7095) + 0.111;
}
if(dist<(float)${maxdistance}) {
sprintf(buf,"{ \"id\":\"%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x-%u-%u\", \"uuid\":\"%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x\", \"major\":%u, \"minor\":%u, \"rssi\":%d, \"txPower\":%d, \"distance\":%.2f, \"type\":\"AltBeacon\" }",
data.data[2],data.data[3],data.data[4],data.data[5],data.data[6],data.data[7],data.data[8],data.data[9],data.data[10],data.data[11],data.data[12],data.data[13],data.data[14],data.data[15],data.data[16],data.data[17],
((unsigned)data.data[18]<<8)+(unsigned)data.data[19],
((unsigned)data.data[20]<<8)+(unsigned)data.data[21],
data.data[2],data.data[3],data.data[4],data.data[5],data.data[6],data.data[7],data.data[8],data.data[9],data.data[10],data.data[11],data.data[12],data.data[13],data.data[14],data.data[15],data.data[16],data.data[17],
((unsigned)data.data[18]<<8)+(unsigned)data.data[19],
((unsigned)data.data[20]<<8)+(unsigned)data.data[21],
rssi,(signed char)data.data[22],dist);
id(mqttid).publish("${channel}/${room}",buf);
id(reported)++;
}
return;
}
}
for (auto data : x.get_service_datas()) {
if(data.uuid.contains(0xAA, 0xFE)) { // eddystoneUID 0xAAFE
if((data.data[0]>>4)==0x00) { // UID 0
float ratio,dist;
if(rssi==0)
dist=-1;
else {
int txrssi=(signed char)data.data[1];
if(txrssi==0) txrssi=${defaulttxrssi};
if(txrssi>0) txrssi*=-1;
ratio=(float)rssi*1.0/(float)txrssi;
if(ratio<1.0)
dist=pow(ratio,10);
else
dist=(0.89976) * pow(ratio,7.7095) + 0.111;
}
if(dist<(float)${maxdistance}) {
sprintf(buf,"{ \"id\":\"%x%x%x%x%x%x%x%x%x%x-%x%x%x%x%x%x\", \"namespace\":\"%x%x%x%x%x%x%x%x%x%x\", \"instance\":\"%x%x%x%x%x%x\", \"rssi\":%d, \"txPower\":%d, \"distance\":%.2f, \"type\":\"eddystone UID\" }",
data.data[2],data.data[3],data.data[4],data.data[5],data.data[6],data.data[7],data.data[8],data.data[9],data.data[10],data.data[11],
data.data[12],data.data[13],data.data[14],data.data[15],data.data[16],data.data[17],
data.data[2],data.data[3],data.data[4],data.data[5],data.data[6],data.data[7],data.data[8],data.data[9],data.data[10],data.data[11],
data.data[12],data.data[13],data.data[14],data.data[15],data.data[16],data.data[17],
rssi,(signed char)data.data[1],dist);
id(mqttid).publish("${channel}/${room}",buf);
id(reported)++;
}
return;
}
}
}
float ratio,dist;
int txrssi=${defaulttxrssi};
String mac = x.address_str().c_str();
mac.replace(":","");
mac.toLowerCase();
if(rssi==0)
dist=-1;
else {
if(txrssi>0) txrssi*=-1;
ratio=(float)rssi*1.0/(float)txrssi;
if(ratio<1.0)
dist=pow(ratio,10);
else
dist=(0.89976) * pow(ratio,7.7095) + 0.111;
}
if(dist<(float)${maxdistance}) {
sprintf(buf,"{ \"id\":\"%s\", \"uuid\":\"%s\", \"name\":\"%s\", \"rssi\":%d, \"txPower\":%d, \"distance\":%.2f, \"type\":\"Generic MAC\" }",
mac.c_str(),mac.c_str(),x.get_name().c_str(),rssi,txrssi,dist);
id(mqttid).publish("${channel}/${room}",buf);
id(reported)++;
}
return;
binary_sensor:
- platform: gpio
pin: GPIO16
name: "${display_name} PIR"
retain: False
discovery: True
state_topic: ${tele}/pir
device_class: motion
filters:
delayed_off: 120s
sensor:
- platform: wifi_signal
id: wifi_sig
name: "${display_name} RSSI"
retain: False
discovery: True
state_topic: ${tele}/wifi_rssi
unit_of_measurement: "dBm"
update_interval: 100s
filters:
- median:
window_size: 7
send_every: 5
send_first_at: 5
- or:
- heartbeat: ${heartbeat}
- delta: 3
text_sensor:
- platform: template
id: telem
name: "${display_name} Stats"
update_interval: 60s
retain: False
discovery: True
state_topic: ${tele}
lambda: |-
char buf[256];
sprintf(buf,"{ room:\"${room}\", ip=\"%s\", hostname=\"${name}\", max_dist=%.2f, disc_ct=%d, rept_ct=%d }", WiFi.localIP().toString().c_str(), (float)${maxdistance}, id(devices), id(reported));
id(devices)=0;
id(reported)=0;
return {buf};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment