I have a grage door.
It has an opener.
I am slightly too lazy to wire up the external controls of my garage door opener.
But it does have an app, and the app shows the state of the door opening and closing.
Using the esp32_ble_tracker
and some debugging ESP_LOGD
s, we can see:
[19:25:28][D][ble_adv:060]: Advertised manufacturer data:
[19:25:36][D][ble_adv:062]: - 02026d200000: (length 6)
[19:25:36][D][ble_adv:062]: - 13c000000000000000e489feb375b43104: (length 17)
This is actually a single long advert sequence (that I forgot to keep an example of) that is type-length
decoded to these two separate manufacturing messages.
The manufacturing ID is set to 0x07B4
for both.
Checking over time, we can see something like the following when the garage door is opening:
[19:24:55][D][ble_adv:062]: - 149200000000000000e489feb375b43104: (length 17)
[19:24:55][D][ble_adv:062]: - 149200000000000000e489feb375b43104: (length 17)
[19:24:55][D][ble_adv:062]: - 149400000000000000e489feb375b43104: (length 17)
[19:24:55][D][ble_adv:062]: - 149400000000000000e489feb375b43104: (length 17)
[19:24:55][D][ble_adv:062]: - 149600000000000000e489feb375b43104: (length 17)
[19:24:56][D][ble_adv:062]: - 149800000000000000e489feb375b43104: (length 17)
[19:24:56][D][ble_adv:062]: - 149a00000000000000e489feb375b43104: (length 17)
[19:24:56][D][ble_adv:062]: - 149c00000000000000e489feb375b43104: (length 17)
[19:24:56][D][ble_adv:062]: - 149e00000000000000e489feb375b43104: (length 17)
This confirms research on other Hörmann openers, this is double the percentage open of the door, between 0–C8.
[19:25:02][D][ble_adv:062]: - 02026d200000: (length 6)
[19:25:03][D][ble_adv:062]: - 02022d200000: (length 6)
In the other message, the third byte flips from 0x2 to 0x6 when in operation. With that, we can write the following[^mfr_advert] in ESPhome:
sensor:
- platform: template
name: Garage door percentage
entity_category: diagnostic
id: door_percent
accuracy_decimals: 0
unit_of_measurement: '%'
filters:
- or:
- throttle: 60s
- delta: 1.0
binary_sensor:
- platform: template
id: door_moving
name: Garage door moving
publish_initial_state: true
device_class: moving
esp32_ble_tracker:
on_ble_advertise:
- mac_address: E5:64:xx:xx:xx:xx
then:
- lambda: |-
auto mfrs = x.get_manufacturer_datas();
if (mfrs.size() == 2) {
bool moving = mfrs[0].data[2] & 0x40;
int percent = mfrs[1].data[1] / 2;
id(door_percent).publish_state(percent);
id(door_moving).publish_state(moving);
}
And then in Home Assistant, a helper can convert the door percentage open to a binary sensor:
{{ states('sensor.garage_door_percentage') | int > 0 }}
This could obviously be done directly by ESPhome, and the only reason it isn’t is because I wanted to test the decoding. I don’t use the percentage or the moving variable, although the latter is tempting for some automation in the summer…
Notes
There is a on_ble_manufacturer_data_advertise
Trigger in ESPhome, but I either used it wrongly or it doesn’t expect two identical mfr IDs in the same beacon, as I only saw the first message.
The generic BLE advert lambda argument is just as easy to work with.
There’s a filter on the door percentage filter as this advert is sent at 5Hz! That’s quite a lot of data to tell us very little! ESPhome supports generic filtering of sensors, and this combo is straight from the docs “Update once a minute or when it changes”.