Door lock vs. ESPHome (DIY)

So here’s how I partly automated my main door lock with ESPHome. I’ve wanted for a while to be able to ditch the keys and then I had a couchsurfer visiting from South Korea who told me she hadn’t used physical keys since childhood, that’s when I realized Europe is behind the times on this.

What it does / doesn’t do

  • unlatches the self-latching door from HA and/or automations,
  • …but only if not locked with the key,
  • senses door open/closed state,
  • senses whether locked with key, in fact it tells HA the number of key turns because it knows how far the security bolts are extended,
  • senses door angle from 0° (closed) up to some 45°, great precision near 0° but fades as the angle increases,
  • no outside visible modifications, everything is inside the wall / door frame.
  • mains powered, no need to monitor battery but will fail if power is out…
  • silly part count/cost

So basically I went for the design where the latch/bolt is pushed out of the strike and into the door by a servo-like mechanism. Maybe it’s a fragile design but it’s been working for 8 months now. I couldn’t modify the lock itself because it’s inside the door and kind of complicated. I didn’t want the type where an electromagnet unlocks the strike plate like the typical intercom operated gate because that’s less secure and visible. A battery-operated smart lock that attaches onto the door and rotates the key – that would have worked but can be expensive, visible and probably can’t sense the door state.

The build

So the mechanism is actually simple. An ESP32 board running ESPHome sits in an electrical box behind the light switch closest to the door. The board has only three extra elements soldered to it:

  • an L298n DC-motor driver / H-bridge,
  • a 0.6 Ohm resistor for current sensing,
  • a 470uF cap to accommodate current spikes.

The light switch box is close enough from the door frame and the strike (the empty space where the bolts enter) that I was able to drill a hole connecting that empty space in the frame to the light switch box, using a long 5mm drill bit. If you don’t have a light switch close enough to the door, the doorbell push button box might work.

Right behind where the latch enters into the frame I drilled away some wood to make extra space for this tiny 6V DC-motor with a gear reduction that turns a screw. A small wood block with M4 nuts pressed into it slides in or out on the screw and presses on the latch when the ESP32 so decides.

Below the latch strike / hole is the space for the security bolts to slide into. There was enough extra space there to place this flat GY-85 sensor board, specifically for its HMC5883L magnetometer. (There are newer and better sensor boards now.)

So mechanics and eletronics-wise that’s it, there are no more components as in my case the 5V power comes through the electrical conduits from another ESPHome node with 3 Amp power supply. The electrical setup is the following:

The ESP32 + the H-bridge in the light switch box have these 6 pins broken out to pin headers: GND, 3.3V, I2C SDA & SCL and the 2 motor driver poles. From there a 6-wire cable goes to the door frame space. On the door frame side two wires go directly to the motor poles and the other 4 wires to the sensor board. No extra electrical components.

Two tricks that make this work

  1. Since there’s little space for end-stop switches or extra connections, I use the current measurements to know when the wooden pusher block is at either end of its run. Normally the block sits all the way inside the door frame and doesn’t interfere with the latch. If I command Home-Assistant to unlock the door, the ESP32 has a Cover component representing the latch, that receives the command to OPEN. The component controls two ESP32 GPIOs that go the L298n. One output goes high and the L298n makes the motor turn in one directing, pushing the wooden block against the door latch. When the latch is fully retracted into the door (door is now unlocked), the motor meets resistance and the current passing through it goes up, and so does the voltage drop on the current-sensing resistor. The resistor is connected on the L298n’s low side, i.e. between the power supply’s (plus 470uF cap’s) ground and the L298n’s negative input. That negative input is also connected to an analog input of the ESP32. When no current is consumed by the motor or its L298n driver that input is at 0V and goes up linearly with the current going up. At 0.5 Amp it should be at 0.3V and that’s when the ESP32 knows to stop driving the motor. Conveniently, if the motor was shorted, the L298n’s negative voltage rises closer or above the 3.3V output from ESP32 GPIOs and the L298n hypothetically should pause because it would see a logical 0 instead of 1.
    There’s also a 5 second time limit for this movement. It will also stop if it detects the door opening. Once there it automatically starts pulling the wooden block back in until it meets resistance again. All this takes a bit of scripting in the ESPHome .yaml config but isn’t too complicated.
    The operation takes ~2 seconds and produces an annoying RC servo-like noise. You could drive the L298n’s with PWM to modulate the speed or in fact play audio tones while operating the lock like the people who played music on floppy drives :wink:

  2. The door and bolt position is sensed using the magnetometer and a magnet attached to one of the security bolts. I drilled a 2mm deep recess at the top of the bolt and put a tiny neodymium magnet in it (wanted to glue it in but there was no need). I had to note down the X, Y and Z of the magnetic field vector at each door position (every ~10 deg) and at 1, 2, 3 and 4 key turns when the door is locked with key. A piece of C++ code in the .yaml config interpolates between these hardcoded vectors to find the specific door angle or the nearest deadbolt position.

You could argue that an attacker could use a bigger magnet to interfere with the measurement and skew the readings. When the door is closed my magnet is very close to the magnetometer and the magnetic field is very strong so it would take a lot ot interfere with it, but yes, no important decisions are taken in ESPHome or HA based on this reading. It’s still useful for turning lights on or off when I enter or leave the house or to see if the door has been opened after a doorbell ring to skip HA notifications.

You could also argue that this will need recalibration after some time as the different “soft-iron” and “hard-iron” distortions change with time and perhaps it will but the sensing has been accurate for 8 months so far.


Wow what a cool idea and nice execution. Nice to see all the comments in your yaml file.

wouldnt this be a fire hazard if the esp stop working?

The esp mechanism doesn’t replace the door handle on the inside and the key access, it’s just an extra way to unlock the door (and monitor it)

1 Like

Thank you for sharing your well-thought-out door locking solution. Your explanation is excellent, and your ESPHome config lamdas are an inspiration. Thank you.

I get the following bits of information in HA through this node:

  • Whether the door is fully closed
  • If yes then whether it is locked with the key and how many turns of the key
  • If not then I get the rough angle the door is open

Combined with other sensors, I also get information such as:

  • Whether somebody has arrived or left, thanks to a motion sensor in the hall (hall motion before door opened —> somebody likely left; motion after door opened and not before —> somebody arrived)
  • Whether doorbell ringing has been “handled” or responded to, i.e. if door was opened after a doorbell then somebody “handled” the matter, nothing to do. Otherwise send notification.