Integration guide for frontends communicating with the michael-lock device (ESP32 smart lock).
The device exposes an HTTP JSON API on the local network. All endpoints except the root require an authentication token sent in the request body.
- Base URL:
http://<device-ip>:<port> - Port:
1212(configured insrc/main.cpp—WebServer server(1212)). - Content-Type:
application/json - Auth token (default dev):
michael-secret-token— sent in the body, not as a header.
The device can run in two modes:
-
Station (STA) — connects to a home Wi-Fi network (
banyurama). IP is assigned by DHCP and printed to Serial (STA IP: ...). The frontend can obtain the IP via:- Manual user input (safest).
- mDNS / discovery (not yet implemented in firmware).
GET /endpoint to verify the IP is live.
-
Access Point (AP) — SSID
michael-lock, passwordmichael1234. Default ESP32 AP IP:192.168.4.1. The device automatically falls back to AP mode if it cannot connect to the configured Wi-Fi within 15 seconds. Connect your phone/laptop to this SSID and reach the API athttp://192.168.4.1:1212.
Device info. No auth required. Useful for health-check / ping.
Response 200
{
"name": "michael-lock",
"ip": "192.168.1.23",
"uptime_ms": 123456
}Lock the device. Requires auth.
Request
{ "token": "michael-secret-token" }Response 200
{ "state": "locked" }Response 401
{ "error": "unauthorized" }Unlock the device. Requires auth.
Request
{ "token": "michael-secret-token" }Response 200
{ "state": "unlocked" }Get the current lock state. Requires auth. (Uses POST because the body carries the token.)
Request
{ "token": "michael-secret-token" }Response 200
{ "state": "locked" }state is either "locked" or "unlocked".
The /lock, /unlock, and /status endpoints validate the JSON body. If the body is not valid JSON or the token does not match, the device replies with 401 { "error": "unauthorized" }.
The token is currently hard-coded in firmware. The frontend should:
- Store the token in secure storage (Keychain / EncryptedSharedPreferences); do not put it in plain
localStoragein production. - Provide a UI for the user to enter the token on first-time setup.
- Never log the token to the console or any crash reporter.
const BASE_URL = 'http://192.168.1.23:1212';
const TOKEN = 'michael-secret-token';
async function call(path) {
const res = await fetch(`${BASE_URL}${path}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: TOKEN }),
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err.error || `HTTP ${res.status}`);
}
return res.json();
}
export const lock = () => call('/lock');
export const unlock = () => call('/unlock');
export const status = () => call('/status');# Ping
curl http://192.168.1.23:1212/
# Lock
curl -X POST http://192.168.1.23:1212/lock \
-H 'Content-Type: application/json' \
-d '{"token":"michael-secret-token"}'
# Status
curl -X POST http://192.168.1.23:1212/status \
-H 'Content-Type: application/json' \
-d '{"token":"michael-secret-token"}'| Condition | Status | Body |
|---|---|---|
| Success | 200 | { "state": "locked" | "unlocked" } |
| Wrong token / body is not JSON | 401 | { "error": "unauthorized" } |
| Device unreachable | — | network error (timeout / DNS) |
UX recommendations:
- Timeout: 3–5 seconds; LAN devices typically respond in <200 ms.
- Retry once for network errors; do not retry on 401.
- Feedback after an action: confirm with
/statusif the user needs visual confirmation. - Polling status: if real-time is needed, poll
/statusevery 2–5 seconds. There is no push / websocket.
- Plain HTTP — no TLS. Anyone on the same LAN can sniff the token. Limit usage to trusted Wi-Fi networks.
- No rate limit in firmware — the frontend must debounce lock/unlock buttons.
- Single auth token — all users share the same token; there is no per-user audit trail.
- State is not persisted — after a restart, the pin is set to
LOCKEDinsetup().
- UI for entering the device IP and token during setup.
- Store the token in secure storage.
- Implement
lock,unlock, andstatusper the examples. - Handle 401 by redirecting to the token re-entry screen.
- Handle network errors with retry and a user-friendly message.
- Debounce action buttons (≥ 500 ms).