Big thanks to previous work done by: @MariusSchiffer, @tc-maxx, @lumokitho and the original creator @oyooyo
Need to use esp-idf framework due to flash limitations
esp32:
# ...
framework:
type: esp-idf
# Uncomment below for ESP32-C3 if you have unexpected reboots when encrypting data
# sdkconfig_options:
# CONFIG_BOOTLOADER_WDT_TIME_MS: "60000"
Using webserver to set parameters from UI
web_server:
include_internal: true
# needs to be false due to a bug: https://github.com/esphome/issues/issues/5188
local: false
port: 80
We use on_connect and on_disconnect to start/stop BLE scan and set the current parameters
wifi:
# ...
# We only start BLE scan after WiFi connected, see https://github.com/esphome/issues/issues/2941#issuecomment-1842369092
on_connect:
- esp32_ble_tracker.start_scan:
continuous: true
# Use below to apply saved input parameters
- eqiva_key_ble.connect:
mac_address: !lambda 'return id(mac_address).state;'
user_id: !lambda 'return id(user_id).state;'
user_key: !lambda 'return id(user_key).state;'
on_disconnect:
- esp32_ble_tracker.stop_scan:
We use buttons and inputs to be able to control from UI
# button, number and text input for pairing and setting mac/user_id/user-key via UI
button:
- platform: template
id: ble_settings
name: BLE Settings _Save_
icon: "mdi:content-save"
on_press:
- eqiva_key_ble.connect:
mac_address: !lambda 'return id(mac_address).state;'
user_id: !lambda 'return id(user_id).state;'
user_key: !lambda 'return id(user_key).state;'
- platform: template
id: ble_disconnect
name: BLE Settings _Disconnect_
icon: "mdi:clear"
on_press:
- eqiva_key_ble.disconnect:
- platform: template
id: ble_pair
name: BLE Pair _Start_
icon: "mdi:check-underline"
on_press:
- eqiva_key_ble.pair:
card_key: !lambda 'return id(card_key).state;'
- platform: template
id: lock_settings
name: Lock Settings _Apply_
icon: "mdi:check-underline"
on_press:
- eqiva_key_ble.settings:
turn_left: !lambda 'return id(direction).state == "Left";'
key_horizontal: !lambda 'return id(position).state == "Horizontal";'
lock_turns: !lambda 'return atoi(id(turns).state.c_str());'
number:
- platform: template
mode: box
name: BLE Settings User ID
id: user_id
max_value: 7
min_value: 0
step: 1
optimistic: true
restore_value: true
text:
- platform: template
mode: text
name: BLE Settings Mac Address
id: mac_address
optimistic: true
restore_value: true
- platform: template
mode: text
name: BLE Settings User Key
id: user_key
optimistic: true
restore_value: true
- platform: template
mode: text
name: BLE Pair Card Key
id: card_key
optimistic: true
select:
- platform: template
name: Lock Settings Close Direction
id: direction
options:
- "Left"
- "Right"
optimistic: true
- platform: template
name: Lock Settings Key Position
id: position
options:
- "Vertical"
- "Horizontal"
optimistic: true
- platform: template
name: Lock Settings Turns
id: turns
options:
- "1"
- "2"
- "3"
- "4"
optimistic: true
Add this external component so you can use it
external_components:
source: github://digaus/esphome-components-eqiva
# use refresh when you do not get latest version
# refresh: 0s
eqiva_key_ble:
id: key_ble
esp32_ble_tracker:
scan_parameters:
window: 300ms
# We do not start scan initialy, see https://github.com/esphome/issues/issues/2941#issuecomment-1842369092
continuous: false
# used for discovering the lock and get the mac_address, check logger for it
eqiva_ble:
text_sensor:
- platform: eqiva_key_ble
mac_address:
name: "Mac Address"
lock_status:
id: lock_status
name: "Lock Status"
low_battery:
name: "Low Battery"
lock_ble_state:
name: "Lock BLE State"
user_id:
name: "User ID"
user_key:
name: "User Key"
Call status every 4 minutes because lock seems to disconnect after 5 minutes of inactivity. Need to watch battery consumption, could also do some other time or present based approaches.
time:
- platform: sntp
on_time:
# Every 4 minutes
- seconds: 0
minutes: /4
then:
- eqiva_key_ble.status:
# Lock component for HA, can also create two locks and use connect service to connect/control two different locks
# One ESP per lock is still recommended
lock:
- platform: template
name: "Lock 1"
lambda: |-
if (id(lock_status).state == "LOCKED") {
return LOCK_STATE_LOCKED;
} else if (id(lock_status).state == "UNLOCKED" || id(lock_status).state == "OPENED") {
return LOCK_STATE_UNLOCKED;
} else if(id(lock_status).state == "MOVING") {
return {};
} else if (id(lock_status).state == "UNKNOWN") {
return LOCK_STATE_JAMMED;
}
return LOCK_STATE_LOCKED;
lock_action:
- eqiva_key_ble.lock:
unlock_action:
- eqiva_key_ble.unlock:
open_action:
- eqiva_key_ble.open:
Please do previous steps first!
For connecting and controlling a lock we need the mac_address (see # Discover new lock), the user_id and the user_key The user_id and user_key can only be retrieved while pairing for which we need the card_key.
- Get the mac_address
- Enter mac_address via UI and press save
- Wait for ESP to connect to lock
- Start pairing on the lock (hold open button for 5 seconds)
- Enter card_key (need to scan QR code of the card and copy the result) in the input
- Press Pair Button on UI
- ESP should pair and display the user_key and user_id via UI
- Copy the values to the inputs and press Save Button