Skip to content

Latest commit

 

History

History
179 lines (124 loc) · 5.1 KB

File metadata and controls

179 lines (124 loc) · 5.1 KB

Michael Lock — Frontend Integration Guide

Integration guide for frontends communicating with the michael-lock device (ESP32 smart lock).

Overview

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 in src/main.cppWebServer server(1212)).
  • Content-Type: application/json
  • Auth token (default dev): michael-secret-token — sent in the body, not as a header.

Finding the Device IP

The device can run in two modes:

  1. 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.
  2. Access Point (AP) — SSID michael-lock, password michael1234. 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 at http://192.168.4.1:1212.

Endpoints

GET /

Device info. No auth required. Useful for health-check / ping.

Response 200

{
  "name": "michael-lock",
  "ip": "192.168.1.23",
  "uptime_ms": 123456
}

POST /lock

Lock the device. Requires auth.

Request

{ "token": "michael-secret-token" }

Response 200

{ "state": "locked" }

Response 401

{ "error": "unauthorized" }

POST /unlock

Unlock the device. Requires auth.

Request

{ "token": "michael-secret-token" }

Response 200

{ "state": "unlocked" }

POST /status

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".

Auth

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 localStorage in 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.

Client Examples

Fetch (browser / React Native)

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');

cURL (debug)

# 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"}'

Error Handling

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 /status if the user needs visual confirmation.
  • Polling status: if real-time is needed, poll /status every 2–5 seconds. There is no push / websocket.

Security & Limitations

  • 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 LOCKED in setup().

Integration Checklist

  • UI for entering the device IP and token during setup.
  • Store the token in secure storage.
  • Implement lock, unlock, and status per 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).