I recently acquired a Switchbot Meter Plus and successfully got it working on an ESP32 with a ble_tracker
using this lambda.
With that confident boost I figured that I could combine that lambda with the relevant packet parsing from the SwitchBot-MQTT-BLE-ESP32 project in order to get a Switchbot Contact working.
I quickly ran into memory issues using both the Meter and Contact on a single ESP32 and learned that including a safe_mode switch is very very very important when your device no longer OTA’s.
Breaking out a Huzzah32 from the ESP32 drawer, I have the button, motion and contact working. Except it isn’t exactly ‘realtime’ state reporting.
Playing with the different scan_parameters:
(interval/window) has improved it a little, but there is still lag. Enough that the motion/contact sensor would be of diminished value as automation triggers in my eyes.
Since I am rather new to ble_tracking, I am hoping for a little insight/experience that others might have to offer in getting this working without a second or more lag in device action to reported state change and often outright missing changes.
Pinging @myhomeiot
esphome:
name: huzzah32-ble
esp32:
framework:
type: arduino
board: featheresp32
# Enable logging
logger:
logs:
esp32_ble_tracker: INFO
# Enable Home Assistant API
api:
reboot_timeout: 4h
ota:
password: !secret more_secrets
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot in case wifi connection fails
ap:
ssid: "huzzah32-ble Fallback Hotspot"
password: !secret more_secrets
mdns:
disabled: true
substitutions:
device_name: huzzah32-ble
web_server:
port: 80
version: 2
include_internal: true
ota: false
auth:
username: admin
password: !secret web_server_password
button:
- platform: restart
name: Restart $device_name
- platform: template
name: "Switchbot Button Pressed"
id: switchbot_contact_button_pressed
on_press:
- logger.log: Contact Button Pressed
- homeassistant.event:
event: esphome.contact_button_pressed
data:
message: Contact button was pressed
switch:
- platform: safe_mode
internal: true
name: use_safe_mode
sensor:
- platform: template
name: "Contact Battery"
id: switchbot_contact_battery
unit_of_measurement: '%'
device_class: battery
accuracy_decimals: 0
icon: "mdi:battery"
update_interval: 180s
- platform: template
name: "Contact Button"
id: switchbot_contact_button
unit_of_measurement: '#'
internal: true
binary_sensor:
- platform: template
name: "Contact Motion"
id: switchbot_contact_motion
device_class: motion
- platform: template
name: "Contact contact"
id: switchbot_contact_contact
device_class: door
esp32_ble_tracker:
scan_parameters:
interval: 320ms
window: 320ms
on_ble_advertise:
- mac_address: !secret MAC
then:
- lambda: |-
for (auto data : x.get_service_datas()) {
if(data.data.size() == 9) {
bool aMotion = false;
bool contact = false;
bool contactA = false;
bool contactB = false;
int8_t battLevel = 0;
// door
contactA = data.data[3] & 0b00000100;
contactB = data.data[3] & 0b00000010;
if (!contactA && !contactB) {
contact = false;
}
else if (!contactA && contactB) {
contact = true;
}
id(switchbot_contact_contact).publish_state(contact);
// motion & battery
aMotion = data.data[1] & 0b01000000;
battLevel = data.data[2] & 0b01111111;
id(switchbot_contact_motion).publish_state(aMotion);
id(switchbot_contact_battery).publish_state(battLevel);
// button
int buttonCountA = (data.data[8] & 0b00001000) ? 8 : 0;
int buttonCountB = (data.data[8] & 0b00000100) ? 4 : 0;
int buttonCountC = (data.data[8] & 0b00000010) ? 2 : 0;
int buttonCountD = (data.data[8] & 0b00000001) ? 1 : 0;
int buttonCount = buttonCountA + buttonCountB + buttonCountC + buttonCountD;
if ( buttonCount != id(switchbot_contact_button).state) {
id(switchbot_contact_button_pressed).press();
}
id(switchbot_contact_button).publish_state(buttonCount);
}
}
```