Skip to content

GATT配网协议

本文档定义基于GATT的设备配网协议规范,适用于APP端开发者、设备端固件开发者和服务端开发者。通过标准BLE GATT服务实现设备的WiFi和MQTT配置。

协议流程

核心优势

相比传统的BluFi等配网协议,本协议具有以下优势:

  • 简洁性:无BluFi等协议的复杂帧格式和序列号管理,直接GATT读写JSON数据
  • 无需特殊SDK:APP端使用标准GATT API即可,避免依赖特定厂商SDK
  • 调试友好:明文JSON数据传输,易于调试和问题排查
  • 兼容性好:基于标准BLE GATT协议,跨平台一致性强
  • 可靠性高:避免BluFi序列号错误等协议层问题

设备发现与连接

设备广播格式及APP扫描过滤规则请参考设备广播规范

设备作为GATT Server,手机作为GATT Client进行连接。

GATT服务定义

服务UUID

0000FFFF-0000-1000-8000-00805F9B34FB

特征定义

特征用途UUID属性描述
配置写入0000FF01-...Write/WriteNRAPP写入JSON配置或命令
状态通知0000FF02-...Read/Notify设备通知状态更新

完整UUID格式:0000FF0x-0000-1000-8000-00805F9B34FB

连接步骤

  1. 连接GATT设备
  2. 发现Service 0xFFFF
  3. 发现Characteristic 0xFF010xFF02
  4. 订阅0xFF02通知(写入CCC描述符0x0001
  5. 可选:请求更大MTU(建议247字节)

数据协议

数据格式规范

所有数据传输采用魔数+长度前缀格式

┌──────────────────┬──────────────────────┬─────────────────────┐
│  魔数 (2字节)     │  长度 (2字节, 小端序)  │   JSON数据 (UTF-8)   │
│  0x46 0x44       │                      │                     │
└──────────────────┴──────────────────────┴─────────────────────┘
字段长度类型说明
魔数2字节固定值固定为 0x46 0x44("FD"的ASCII码),用于识别协议
JSON长度2字节uint16_t小端序,表示后续JSON数据的字节长度(最大65535字节)
JSON数据可变UTF-8字符串JSON格式的配置或状态数据,不包含null终止符

分包处理

当"魔数+长度+JSON数据"总长度超过MTU时,需要应用层实现分包发送和接收重组。由于BLE GATT保证数据有序传输,应用层只需:

  1. 发送端:将数据按MTU大小切分,依次发送
  2. 接收端:
    • 先读取2字节魔数,验证是否为 0x46 0x44,不匹配则拒绝接收
    • 再读取2字节长度,验证长度是否合理(建议最大10KB)
    • 根据长度持续接收后续数据包,直到接收完整长度后再进行JSON数据解析

配网状态检查

在开始配网前,APP应先查询设备当前状态,避免重复配网或配网冲突。

超时时间:5秒(设备应在5秒内响应,否则APP视为设备异常)

查询请求(APP → 设备)

字段类型必填说明
action字符串固定为check_status

JSON示例:

json
{
  "action": "check_status"
}

查询响应(设备 → APP)

字段类型必填说明
action字符串固定为check_status_result
configured布尔值设备是否已配网
network_connected布尔值网络是否连接
device_info对象设备信息
device_info.bluetooth_mac字符串蓝牙MAC地址
device_info.firmware_version字符串固件版本号
device_info.model字符串设备型号
device_info.serial_number字符串厂商序列号
device_info.network_mac字符串网络MAC地址

JSON示例:

json
{
  "action": "check_status_result",
  "configured": false,
  "network_connected": true,
  "device_info": {
    "bluetooth_mac": "3c:84:27:c1:5d:00",
    "firmware_version": "1.0.0",
    "model": "XHJ-Gateway",
    "serial_number": "GW01_c39eae",
    "network_mac": "aa:bb:cc:dd:ee:ff"
  }
}

扩展说明

device_info 说明: 对象必须包含 bluetooth_macfirmware_versionmodelserial_numbernetwork_mac 五个基础字段,业务可根据需求扩展其他字段。

bluetooth_mac 说明: 蓝牙接口的物理地址,用于蓝牙通信时的设备标识。

network_mac 说明: 联网接口的物理地址。指局域网通信中与业务 IP 绑定的真实 MAC 地址(即通过 ARP 协议获取的地址)。

serial_number 说明: 每台设备的序列号唯一且固定不变,设备上电、重置等操作不会改变序列号。

WiFi扫描(可选)

此功能为可选实现,允许APP先获取设备周围的WiFi列表,然后让用户选择要连接的WiFi网络。

超时时间:15秒(设备扫描WiFi需要4-6秒,加上处理和传输时间)

设计原因

手机扫描需要授权相关复杂操作对用户不友好,且手机可扫描到的WiFi网络,设备不一定支持。例如:

  • 5GHz WiFi网络(部分设备仅支持2.4GHz)
  • 特定加密方式(如WPA3,部分单片机不支持)
  • 企业级认证(如802.1X)

通过设备端扫描,仅展示设备实际可连接的WiFi网络,可显著提升配网成功率和稳定性。

扫描请求(APP → 设备)

字段类型必填说明
action字符串固定为scan_wifi

JSON示例:

json
{
  "action": "scan_wifi"
}

扫描结果(设备 → APP)

字段类型必填说明
action字符串固定为scan_wifi_result
status整型0=成功,0xFF=失败
networks数组WiFi网络列表
networks[].ssid字符串WiFi名称
networks[].rssi整型信号强度(dBm)

JSON示例:

json
{
  "action": "scan_wifi_result",
  "status": 0,
  "networks": [
    {
      "ssid": "MyWiFi-5G",
      "rssi": -40
    },
    {
      "ssid": "Office-Network",
      "rssi": -65
    }
  ]
}

实现建议

  • 设备收到扫描请求后,建议扫描时长为4-6秒
  • RSSI值为负数,数值越大信号越强(如-40优于-65)
  • 建议按信号强度降序排列网络列表
  • 重复的SSID应去重,保留信号最强的

配网数据传输

配网请求(APP → 设备)

字段类型必填说明
action字符串固定为provision
timestamp整型当前时间戳(秒),用于设备端设置时间
wifi对象WiFi配置,若设备已配网则无需传输
wifi.ssid字符串WiFi网络名称
wifi.password字符串WiFi密码,开放网络传空字符串
mqtt对象MQTT配置
mqtt.broker字符串MQTT服务器地址,格式:mqtt://host:port
mqtt.client_id字符串MQTT客户端ID
mqtt.username字符串MQTT用户名
mqtt.password字符串MQTT密码
mqtt.topic_prefix字符串主题前缀,默认nodes
config对象业务配置

JSON示例:

json
{
  "action": "provision",
  "timestamp": 1710000000,
  "wifi": {
    "ssid": "YourWiFiName",
    "password": "YourWiFiPassword"
  },
  "mqtt": {
    "broker": "mqtt://192.168.1.100:1883",
    "client_id": "esp32-gateway-001",
    "username": "mqtt_user",
    "password": "mqtt_pass",
    "topic_prefix": "nodes"
  },
  "config": {}
}

config 扩展说明

config 对象用于传递业务相关配置,设备端需持久化存储。字段内容由业务层自定义,协议不做强制要求,如无业务需求config需传空对象({})不可省略。

配网响应(设备 → APP)

设备会在配网过程中多次发送状态更新:

字段类型必填说明
action字符串固定为provision_status
status字符串状态码,见状态码表
error字符串错误描述(status为error时必填)
credential对象设备凭证,拥有该凭证即拥有设备的完全控制权(配网完成时返回)
credential.secret字符串设备凭证密钥,由设备端生成的UUID v4格式

JSON示例(配置接收):

json
{
  "action": "provision_status",
  "status": "config_received"
}

JSON示例(配网完成):

json
{
  "action": "provision_status",
  "status": "completed",
  "credential": {
    "secret": "550e8400-e29b-41d4-a716-446655440000"
  }
}

credential 扩展说明

  • secret 由设备端随机生成,格式为标准UUID v4
  • 业务可根据需求扩展其他凭证相关字段

JSON示例(配网失败):

json
{
  "action": "provision_status",
  "status": "error",
  "error": "WiFi连接超时"
}

error 说明

APP收到status: "error",应将error 字符串显示出来,例如“初始化设备失败: WiFi连接超时”

状态码说明

配网状态码

协议定义以下基础状态码,业务可根据需求扩展更多中间状态:

状态码说明超时时间
config_received配置已接收5秒(收到配网请求后)
wifi_connectedWiFi已连接10秒(从config_received起)
mqtt_connectedMQTT已连接5秒(从wifi_connected起)
completed配网完成5秒(从mqtt_connected起)
error配网失败-

超时处理

  • APP端应按上述超时时间监控状态转换,超时未收到下一状态则视为配网失败
  • 设备端应在超时前完成状态转换或返回error状态
  • 整个配网流程总超时建议为30秒

状态扩展示例

业务可根据需要添加更多中间状态,例如:

  • device_authenticated - 设备认证成功
  • server_registering - 服务器注册中
  • firmware_checking - 固件版本检查中

设备行为规范

配网成功

配网成功后,设备应:

  1. 持久化存储以下数据:
    • WiFi配置(ssid、password)
    • MQTT配置(broker、client_id、username、password、topic_prefix)
    • 业务配置(config对象)
    • 设备凭证(credential.secret)
  2. 停止BLE广播
  3. 断开GATT连接
  4. 通过MQTT开始正常业务运行

配网失败

配网失败后,设备应:

  1. 清除本次接收的所有配置数据,恢复到待配网状态
  2. 继续BLE广播,等待下一次配网请求
  3. 不保留任何残留状态

连接断开处理

正常断开(配网完成后):

  • 设备发送completed状态后,双方均可主动断开连接
  • BLE传输层保证数据送达,无需等待APP确认

异常断开(配网过程中):

  • 如果APP在收到completed前断开连接,设备发送响应会失败
  • 设备应检测到发送失败后,清除配置并恢复到待配网状态,而不应该认为配网成功
  • 继续BLE广播,等待重新配网

物联网设备通信协议文档