Control an eQ-3 equiva Key-BLE “Bluetooth® Smart Türschlossantrieb” lock via
wifi, serial or usb connection. It uses an ESP32 for bridging bluetooth to
serial and an ESP8266 for bridging serial to wifi.
You can use the supplied node.js client or write your own. It’s a simple
text-based protocol.

Differences to lumikitho/esp32-keyble
- Reduce operational latency and allow continuous monitoring by having a
permanent bidirectional connection.
- Operate in an untrusted wifi network by using SSL encrypted communication.
- Use WebSocket with text protocol instead of MQTT.
- Some features have been lost.
Getting started
Prerequisites
Wifi bridge setup (ESP32 + ESP8266)
- Generate a self-signed SSL certificate/key pair and obtain its SHA-1
fingerprint.
In the keyble-serial-bridge folder:
- Adapt platformio.ini
to your actual
board hardware. - Flash the ESP32 by running
pio run --target upload.
In the serial-websocket-bridge folder:
- Adapt platformio.ini
to your actual
board hardware. - Configure the bridge by editing the defines in
src/main.cpp to match your
setup. Here you need to enter the fingerprint of the self-signed SSL
certificate generated previously. - Flash the ESP8266 by running
pio run --target upload.
Solder four wires to connect the boards: 5V to 5V, GND to
GND, RX to TX and TX to RX. You can find the serial GPIO numbers in the
defines in the two main.cpp files.
In the node-client folder:
- Install the dependencies by calling
npm install. - Move the self-signed SSL certificate files into the folder and name them
websocket.crt (cert) and websocket.key (key). - Configure the example code by editing the lock constructor parameters in
example-websocket.mjs and start it by running node example-websocket.mjs. - After some seconds you should see the lock status and it should begin to move.
Serial over USB setup (ESP32)
The protocol messages get intermixed with debug messages. A prefix is used to
differentiate them.
In the keyble-serial-bridge folder:
- Comment out
#define USE_SERIAL2 in src/main.cpp. - Flash the ESP32 by running
pio run --target upload.
In the node-client folder:
- Install the dependencies by calling
npm install. - Configure the example code by editing the lock constructor parameters in
example-serial.mjs. Set hasPrefix to true. Start it by running
node example-serial.mjs. - After some seconds you should see the lock status and it should begin to move.
Serial setup (ESP32)
Connect the ESP32’s serial2 RX and TX pins to another 3.3V serial port, e.g. a
Raspberry Pi’s UART TX and RX. If you use separate power sources, connect GND,
too.
- In the
keyble-serial-bridge folder, flash the ESP32 by running
pio run --target upload.
In the node-client folder:
- Install the dependencies by calling
npm install. - Configure the example code by editing the lock constructor parameters in
example-serial.mjs. Set hasPrefix to false. Start it by running
node example-serial.mjs. - After some seconds you should see the lock status and it should begin to move.
Serial protocol
Have a look at the node-client, it’s not complicated.
The node-client’s changeState events
lock_status string
If needs_open ist true, UNKNOWN really means the position is unknown.
Otherwise it means the position is somewhere between locked and unlocked.
battery_low flag
The lock sets this flag if the voltage drops below a certain threshold. While
using a lab power supply I found out it does not get cleared if you turn the
voltage up again. You need to power cycle the lock.
needs_open flag
After the lock was without power by a battery change, the Android app only
allows you to trigger the open action. This seems to be necessary for the lock
to get into a known state. Until then, the unlock action does nothing.
Curiously, the lock action always works despite the display in the app. If you
ever only use lock and open you can ignore this flag.
Also, if the battery is low, the lock does not get out of needs_open state.
Miscellaneous
Troubleshooting
Look at the output of the ESP’s usb-serial to narrow down what’s not working by
running pio device monitor. If you connect both boards at the same time,
unsolder the GND and 5V wire to avoid loops.
The ESP32 is quite sensible to the power supply
Use a good power supply. If using the Micro-USB connector, prefer to connect to
the ESP32 board. Power issues did manifest on my setup by going into boot loop
by crashing on BLEDevice::init("");.
The bridge needs to be close to the lock
To get a reliable connection there should be no object between the bridge and
the lock. 2-3m distance should be fine, depending on the bridge encasing.
The node interface is not a drop-in replacement for oyooyo’s keyble lib
Although similar, some things are handled differently:
- Only the constructor parameters
address, user_key and user_id are the
same. - Some of the events do not exist.
- No need to request the status as it is provided automatically.
The led turns off when …
- serial-websocket-bridge: websocket is connected (secret may still be wrong).
- keyble-serial-bridge: bluetooth is connected (keyble credentials may still be
wrong).
Contrary to its name, the node client is a server
I did not find an example of setting up a SSL websocket server on the ESP8266,
so now it is the other way round.
The websocket connection uses an SHA-1 fingerprint, which is insecure
If your biggest concern is that an attacker spends some thousand dollars on GPU
time to break the encryption, please fix the websocket library to use another
hashing algorithm. In my usage scenario this is no issue.
Thanks
Thanks go to
lumokitho,
RoP09,
tc-maxx,
henfri,
MariusSchiffer and of course
oyooyo for their brilliant work!