┌─ Device Pi (DSLR agent) ──────────────────────┐
│ │
│ [1] BOOT │
│ - Generate UUID (machine-id hoặc random) │
│ - Generate claimCode = random 6-char │
│ - POST /v1/devices/claim │
│ { uuid, name, serialNo, claimCode } │
│ - Display claimCode + UUID on terminal │
│ - Poll /v1/devices/claim/:code/status │
│ │
│ [2] APPROVED? │
│ - /claim/:code/status → { status, apiKey }│
│ - Save apiKey to /boot/timelapse/agent.key│
│ - chmod 600 (owner read/write only) │
│ │
│ [3] HEARTBEAT LOOP │
│ - POST /v1/devices/:id/heartbeat │
│ X-API-Key: <key from agent.key> │
│ - gphoto2 capture loop │
│ - Poll /v1/devices/:id/commands │
└───────────────────────────────────────────────┘
HTTPS (TLS) HTTPS (TLS)
↓ ↑
┌─ Server (NestJS) ────────────────────────────────────────────┐
│ │
│ POST /v1/devices/claim → claimCode + device info │
│ GET /v1/devices/claim/:code → polling status │
│ GET /v1/devices/pending → dashboard list │
│ POST /v1/devices/pending/:id/approve │
│ POST /v1/devices/pending/:id/reject │
│ POST /v1/devices/:id/heartbeat ← X-API-Key auth │
│ GET /v1/devices/:id/commands → pending commands queue │
└────────────────────────────────────────────────────────────┘
device_claims (schema)CREATE TABLE device_claims (
id TEXT PRIMARY KEY, -- nanoid
claim_code TEXT UNIQUE NOT NULL, -- 6-char, uppercase
device_uuid TEXT UNIQUE NOT NULL, -- device unique id
device_name TEXT NOT NULL,
serial_no TEXT,
status TEXT DEFAULT 'pending', -- pending | approved | rejected | expired
api_key_hash TEXT, -- bcrypt hash of API key
expires_at TIMESTAMP NOT NULL, -- 24h from creation
approved_by TEXT,
approved_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
/boot/timelapse/agent.key (chmod 600) on deviceDevice gửi thông tin để đăng ký.
Request:
{
"deviceUuid": "pi-abc123",
"deviceName": "Pi-Camera-01",
"serialNo": "RPI-0001"
}
Response (201):
{
"claimCode": "XK7M2P",
"status": "pending",
"expiresAt": "2025-01-01T12:00:00Z"
}
Device polling để kiểm tra approval.
Response:
{
"status": "pending" | "approved" | "rejected" | "expired",
"apiKey": "..." // chỉ khi approved
"deviceId": "DEMO-001" // chỉ khi approved
}
Dashboard list pending devices (admin only).
Admin approve → sinh API key → lưu hash → trả cho device qua polling.
Admin reject → xóa claim record.