# 设备激活流程 v2 ## 概述 当前流程是虾哥设备认证v2版本 ## 激活流程 每个设备都有一个唯一的序列号(Serial Number)和HMAC密钥(HMAC Key),用于身份验证和安全通信。新设备首次使用时需要通过以下流程进行激活: 1. 客户端启动时,向服务器发送设备信息,包括序列号、MAC地址和客户端ID 2. 服务器检查设备是否已激活: - 如果已激活,客户端正常工作 - 如果未激活,服务器返回包含验证码和Challenge的激活请求 3. 客户端显示验证码,提示用户前往xiaozhi.me网站输入验证码 4. 客户端使用HMAC密钥对Challenge进行签名,并发送给服务器验证 5. 客户端通过轮询方式等待服务器确认验证结果: - 如果验证成功,设备激活完成 - 如果验证失败或超时,设备激活失败 ### 小智 ESP32 设备激活流程图 ``` ┌────────────────────┐ │ 设备启动 │ └──────────┬─────────┘ ↓ ┌────────────────────┐ │ 初始化各组件 │ │ 连接WiFi/网络 │ └──────────┬─────────┘ ↓ ┌────────────────────┐ │ 调用CheckVersion │ │ 访问OTA服务器 │──→ POST /xiaozhi/ota/ └──────────┬─────────┘ ↓ ┌────────────────────┐ │ 解析服务器响应 │ └──────────┬─────────┘ ↓ ┌─────┴─────┐ ↓ ↓ ┌─────────┐ ┌─────────┐ │是否有新版本│ │是否需要激活│ └─────┬───┘ └─────┬───┘ │ │ ┌─────▼───┐ └───┬─── 否 ──┐ │升级固件 │ ↓ ↓ └─────────┘ ┌─────────────┐ ┌─────────────┐ │是否有激活码 │ │初始化协议连接│ └──────┬──────┘ │MQTT/WebSocket│ │ └─────────────┘ ┌────▼───┐ │ 是 │ └────┬───┘ ↓ ┌──────────────────┐ │显示激活码给用户 │ │播放语音提示 │ └────────┬─────────┘ ↓ ┌──────────────────┐ │ 开始激活流程 │ └────────┬─────────┘ ↓ ┌────────────────────────────────┐ │ 检查设备序列号 │ └───────────────┬────────────────┘ ↓ ┌──────┴───────┐ ↓ ↓ ┌─────────┐ ┌─────────┐ │ 有序列号 │ │ 无序列号 │ └─────┬────┘ └────┬────┘ │ │ ┌─────────▼────────┐ │ │构造激活载荷JSON: │ │ │- serial_number │ │ │- challenge │ │ │- hmac签名 │ │ └─────────┬─────────┘ │ │ │ └──────┬───────┘ ↓ ┌───────────────────────┐ │发送POST请求到激活端点 │──→ POST /xiaozhi/ota/activate └────────────┬──────────┘ ↓ ┌───────────┴───────────┐ ↓ ↓ ↓ ┌─────────┐ ┌─────────┐ ┌─────────┐ │状态码200 │ │状态码202 │ │其他状态码│ │激活成功 │ │超时重试 │ │激活失败 │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ ┌────▼─────┐ │ │ │延迟后重试 │ │ │ │最多10次 │ │ │ └────┬─────┘ │ │ │ │ └───────────┼───────────┘ ↓ ┌──────────────────┐ │设置激活状态标志位 │ └────────┬─────────┘ ↓ ┌──────────────────┐ │ 继续正常运行 │ │ 连接MQTT/WS协议 │ └──────────────────┘ ``` ### 激活数据交互详细流程 ``` ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ │ │ │ │ │ 设备客户端 │ │ 服务器 │ │ 用户浏览器 │ │ │ │ │ │ │ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │ │ │ │ 请求设备状态 (MAC, ClientID, SN) │ │ │ ────────────────────────────────> │ │ │ │ │ │ 返回激活请求 (验证码, Challenge) │ │ │ <──────────────────────────────── │ │ │ │ │ │ 显示验证码 │ │ │ ┌─────────────┐ │ │ │ │请前往网站输入 │ │ │ │ │验证码: 123456│ │ │ │ └─────────────┘ │ │ │ │ │ │ │ 用户访问xiaozhi.me │ │ │ <─────────────────────────────────│ │ │ │ │ │ 输入验证码 123456 │ │ │ <─────────────────────────────────│ │ │ │ │ 计算HMAC签名 │ │ │ ┌─────────────┐ │ │ │ │ HMAC(密钥, │ │ │ │ │ Challenge) │ │ │ │ └─────────────┘ │ │ │ │ │ │ 发送激活请求 (SN, Challenge, 签名) │ │ │ ────────────────────────────────> │ │ │ │ ┌───────────────┐ │ │ │ │ 等待用户输入验证码 │ │ │ │ │ 超时返回202 │ │ │ │ └───────────────┘ │ │ │ │ │ 轮询等待 (HTTP Long Polling) │ │ │ ────────────────────────────────> │ │ │ HTTP 202 (Pending) │ │ │ <──────────────────────────────── │ │ │ │ │ │ 继续轮询... │ │ │ ────────────────────────────────> │ │ │ │ │ │ │ 验证码验证成功 │ │ │───────────────────────────────────│ │ │ │ │ 激活成功 (HTTP 200) │ │ │ <──────────────────────────────── │ │ │ │ │ │ ┌─────────────┐ │ │ │ │设备激活成功! │ │ │ │ └─────────────┘ │ │ │ │ │ ``` ## 设备与服务器通信内容详解 ### 1. 设备信息请求 (POST /xiaozhi/ota/) **请求头**: ``` Activation-Version: 2 // 表示支持序列号激活 Device-Id: AA:BB:CC:DD:EE:FF // MAC地址 Client-Id: xxxx-xxxx-xxxx-xxxx // 设备UUID User-Agent: BOARD_NAME/1.0.0 // 开发板名称和固件版本 Content-Type: application/json ``` **请求体** (POST时): ```json { "version": 2, "flash_size": 16777216, "psram_size": 8388608, "minimum_free_heap_size": 7265024, "mac_address": "你的mac地址", "uuid": "你的client_id", "chip_model_name": "esp32s3", "chip_info": { "model": 9, "cores": 2, "revision": 0, "features": 20 }, "application": { "name": "xiaozhi", "version": "1.6.0", "compile_time": "2025-04-16T12:00:00Z", "idf_version": "v5.3.2" }, "partition_table": [ { "label": "nvs", "type": 1, "subtype": 2, "address": 36864, "size": 24576 }, { "label": "otadata", "type": 1, "subtype": 0, "address": 61440, "size": 8192 }, { "label": "app0", "type": 0, "subtype": 0, "address": 65536, "size": 1966080 }, { "label": "app1", "type": 0, "subtype": 0, "address": 2031616, "size": 1966080 }, { "label": "spiffs", "type": 1, "subtype": 130, "address": 3997696, "size": 1966080 } ], "ota": { "label": "app0" }, "board": { "type": "lc-esp32-s3", "name": "立创ESP32-S3开发板", "features": ["wifi", "ble", "psram", "octal_flash"], "ip": "你的ip地址", "mac": "你的mac地址" } } ``` ### 2. 服务器响应 **响应体**: ```json { "firmware": { "version": "1.0.1", "url": "" }, "activation": { "message": "请访问xiaozhi.me输入激活码", "code": "123456", "challenge": "randomstring123456", "timeout_ms": 30000 }, "mqtt": { "endpoint": "mqtt.xiaozhi.me", "client_id": "device123", "username": "user123", "password": "pass123", "publish_topic": "" }, "websocket": { "url": "wss://api.tenclass.net/xiaozhi/v1/", "token": "test-token" } } ``` ### 3. 设备激活请求 (POST /xiaozhi/ota/activate) **请求体**: ```json { "Payload": { "algorithm": "hmac-sha256", "serial_number": "SN-5CD8467B47FB4920", "challenge": "dac852d6-4ac4-4650-ba1a-c2a5bf00a766", "hmac": "ada4775e3ed93cf9c0eb9ed00444138554ba416af41283a0e5603c77681a8022" } } ``` ### 4. 激活响应 - **成功**: 状态码 200 - **等待用户输入验证码**: 状态码 202 - **失败**: 状态码 4xx (如401表示未授权,400表示请求错误) **响应体** (失败时): ```json { "error": "错误原因描述" } ``` ## 安全机制 设备激活流程v2版本采用以下安全机制: 1. **设备唯一标识**:每个设备有一个唯一的序列号(Serial Number) 2. **HMAC签名验证**:使用HMAC-SHA256算法对Challenge进行签名,确保设备身份的真实性 3. **验证码验证**:通过要求用户在网页端输入验证码,防止自动化的激活攻击 4. **轮询等待机制**:使用HTTP Long Polling等待服务器验证结果,适应各种网络环境