hsrakri / sparky · home-lab side quest

The lock is Bluetooth-only.
The bridge is $10.

A gen-2 August smart lock wants you to buy its Wi-Fi bridge and a subscription for remote control. We built the bridge ourselves: an ESP32-C6 Bluetooth proxy + Home Assistant, talking to the lock directly over BLE. No hub. No cloud in the control path. No monthly fee.

$0
hardware cost
$0/mo
subscription
0
locks controlled
100%
local BLE control
▾
The problem

A smart lock you can only
control from the doormat.

Gen-2 August locks are BLE-only — there's no radio in them that reaches past your porch. The vendor's answer is the August Connect bridge (extra hardware) plus a cloud subscription for the good features. Meanwhile the lock itself speaks a well-understood BLE protocol, and the credential needed to drive it — a 32-byte offline key — is already provisioned to your account.

GOAL

Remote control without the vendor bridge

What we wanted: lock and unlock from Home Assistant — from anywhere HA is reachable — and eventually automate it: lock when the last phone leaves Wi-Fi, unlock when it comes back.

What we refused: buying a single-purpose hub, routing every actuation through a vendor cloud, and paying rent for a radio relay.

constraints
lock radioBLE only, ~10 m range
vendor remote optionbridge + subscription
our budgetone $10 dev board
control pathmust be 100% local
cloud allowedonce, to fetch the key
Solution architecture

HA speaks BLE
through a $10 antenna.

The trick is that Home Assistant doesn't need the vendor bridge — it needs a BLE radio near the lock and the lock's offline key. ESPHome's bluetooth_proxy turns any ESP32 into a remote radio for HA; the august integration fetches the key from the vendor cloud once; the yalexs_ble integration then drives the lock directly.

Brain

Home Assistant

yalexs_ble integration holds the 32-byte offline key + slot
lock entitiesautomationsAPI
Bridge

ESP32-C6 “door-proxy”

ESPHome bluetooth_proxy (active) + BLE tracker, on Wi-Fi
$10esp-idfstatic IP
Actuator

August gen-2 locks ×2

BLE-only; authenticated with the offline key, no cloud
mud roomoutside door
The one-time cloud step: HA's august integration logs into the vendor account and pulls each lock's 32-byte offline key + key slot — the same credential the phone app uses to open the door with no internet. After that handoff to yalexs_ble, the vendor cloud is out of the loop: every lock/unlock is HA → encrypted ESPHome API → C6 → BLE → lock, entirely inside the house.
Bill of materials

The whole shopping list.

Assuming you already run Home Assistant somewhere (a Pi, a NUC, a VM — anything on the LAN).

ItemRoleCost
ESP32-C6-DevKitC-1Bluetooth proxy — the entire “bridge”~$10
USB-C cable + any 5 V supplyPower, parked within ~5 m of the lock(s)~$0
ESPHomeFirmware framework (bluetooth_proxy component)free
Home Assistant + august + yalexs_bleKey retrieval, BLE lock control, automationsfree
August gen-2 lockAlready on the doorowned
Total new spendvs. vendor bridge + subscription, forever~$10
Step-by-step build

Three steps,
one evening.

Values below are illustrative (documentation IPs, placeholder names) — substitute your own network. Never publish real LAN addresses, SSIDs, or keys.

STEP 1

Write the ESPHome config

One gotcha decides everything downstream: the C6 needs the esp-idf framework — the Arduino core doesn't support it. active: true on the proxy is what allows HA to make outbound GATT connections (actually driving the lock), not just sniff advertisements. A static IP keeps the bridge findable across reboots.

door-proxy.yaml (anonymized)
esphome:
  name: door-proxy

esp32:
  board: esp32-c6-devkitc-1
  variant: esp32c6
  framework:
    type: esp-idf   # Arduino core has no C6 support

wifi:
  ssid: "ssid-home"
  password: !secret wifi_password
  manual_ip:
    static_ip: 192.0.2.68
    gateway: 192.0.2.1
    subnet: 255.255.255.0
    dns1: 8.8.8.8
    dns2: 1.1.1.1

api:
  encryption:
    key: !secret api_noise_psk   # noise PSK — HA↔C6 link is encrypted

esp32_ble_tracker:
  scan_parameters:
    active: true

bluetooth_proxy:
  active: true   # outbound GATT — required to actuate the lock
STEP 2

Build and flash

Compiled with ESPHome (PlatformIO underneath) on the workstation, then flashed over USB with esptool. For a factory-fresh C6, flash the combined firmware.factory.bin image at offset 0 — it bundles bootloader, partition table, and app in one write.

flash
esphome compile door-proxy.yaml
esptool.py --chip esp32c6 --port /dev/ttyACM0 write_flash 0x0 \
  .esphome/build/door-proxy/.pioenvs/door-proxy/firmware.factory.bin

On boot it joined Wi-Fi at its static IP and started advertising the ESPHome API on port 6053.

STEP 3

Wire up Home Assistant

Three integrations, in order:

1 · ESPHome — add the proxy by IP + noise PSK (a config_entries flow; no HA restart needed). HA immediately gains a BLE radio at the front door and starts seeing the locks' advertisements.

2 · august — authenticate once with the vendor account (email works; avoid tying it to a phone number). This fetches each lock's 32-byte offline key and key slot from the cloud.

3 · yalexs_ble — HA offers to set it up automatically once it has both the key and BLE visibility. Each lock becomes a first-class lock.* entity driven purely over BLE.

result
esphome devicedoor-proxy · online, encrypted
lock.mud_roomyalexs_ble · via proxy
lock.outside_dooryalexs_ble · via proxy
vendor cloud in control pathnone
First lock test

Two API calls,
two deadbolts thrown.

The moment of truth: calling lock.lock through the HA API and listening for the motor.

WHAT HAPPENED

Both locks actuated on the first try

We called the HA REST API for each entity. Both locks went locking → locked: HA encrypted the command to the C6 over the ESPHome API, the C6 opened a GATT connection to the lock, and yalexs-ble authenticated with the offline key and drove the bolt. The deadbolts moved. The vendor cloud saw none of it.

That state transition is the proof of the whole chain — the offline key is valid, the key slot is right, the proxy's active mode works, and the BLE session survives the full transaction.

Unlock uses the exact same authenticated session (the state machine supports it identically); we deliberately tested lock-only first — the failure mode of a test that locks a door is much friendlier than one that unlocks it.

ha api · first actuation
POST /api/services/lock/lock
{"entity_id": "lock.mud_room"}

# state: locking → locked ✓

POST /api/services/lock/lock
{"entity_id": "lock.outside_door"}

# state: locking → locked ✓
Results

What you get,
and where it goes next.

Two BLE-only deadbolts, fully controllable from Home Assistant — dashboards, voice, scripts, or plain REST — for the price of a sandwich.

HOW TO USE IT

It's just a lock entity now

Tap it on any HA dashboard, call lock.lock / lock.unlock from scripts and automations, or hit the REST API remotely (through however you already expose HA — VPN, Nabu Casa, reverse proxy).

Next up: presence automation — lock when the last tracked phone leaves Wi-Fi, unlock on return. The BLE tracker on the same C6 can double as a presence sensor, so the one board both senses and actuates.

scorecard
remote lock/unlock✓ via HA
vendor bridge purchasedno
subscription$0/mo forever
control path100% local BLE
works if vendor cloud diesyes (key already local)
locks on one proxy2

Security notes: the HA↔proxy link is noise-encrypted; the lock↔HA BLE session is authenticated with the per-lock offline key, exactly like the official app. Treat the offline key like a house key — it lives only in HA's storage. And keep your real SSIDs, LAN addresses, and device serials out of any writeup, like this one does.