Skip to content

数据结构

本文档定义蓝牙协议 V2 中的核心实体及其关系,是理解后续协议文档的基础。

实体关系

用户 (User)

用户是门锁的核心实体,代表一个可以操作门锁的身份。

  • 每个用户拥有唯一的 user_id(锁内分配)
  • 用户可以拥有多种凭证(电子钥匙、密码、指纹等)
  • 用户也可以没有任何凭证(例如刚创建的用户)
protobuf
message User {
  uint32 user_id = 1;           // 用户ID(锁内唯一)
  bytes user_secret = 2;        // 用户密钥(16字节)
  UserRole role = 3;            // 用户角色
  uint32 created_by = 4;        // 创建者用户ID(拥有者此字段为0)
  uint64 created_at = 5;        // 创建时间(UNIX毫秒时间戳)
  string nickname = 6;          // 用户昵称(用于APP/门锁屏幕显示)
}

userSecret

user_secret 是用户的身份凭证,用于蓝牙指令通信时的身份验证。

属性说明
长度16字节
生成方门锁
获取时机创建用户时返回
存储位置APP本地 + 云端同步

安全提示

  • user_secret 是用户操作门锁的唯一凭证,泄露将导致他人可冒充该用户
  • APP应使用系统密钥库安全存储
  • 云端同步时应使用端到端加密

UserRole

用户角色枚举:

protobuf
enum UserRole {
  USER = 0;                     // 普通用户
  ADMIN = 1;                    // 管理员
  OWNER = 2;                    // 拥有者
}

详细的角色说明和权限矩阵参见 用户管理

凭证 (Credential)

凭证是用户开锁的"钥匙",每个凭证必须归属于一个用户。

  • 凭证是开锁的凭据,如密码、卡片、指纹等
  • 每个凭证必须归属于一个用户,不存在"独立凭证"
  • 添加凭证时如果不指定用户,则自动创建新用户
protobuf
message Credential {
  uint32 credential_id = 1;     // 凭证ID(锁内唯一)
  CredentialType type = 2;      // 凭证类型
  uint32 user_id = 3;           // 归属用户ID(可为空,例如在门锁面板离线添加)
  uint32 created_by = 4;        // 创建者用户ID
  uint64 created_at = 5;        // 创建时间(UNIX毫秒时间戳)
  ValidityPeriod validity = 6;  // 有效期
  uint32 use_count_limit = 7;   // 使用次数限制(0=不限)
  uint32 use_count = 8;         // 已使用次数
  string label = 9;             // 凭证标签(如"右手拇指")未设置为空字符串,APP可渲染为空或"未命名"
  bool is_duress = 10;          // 是否胁迫凭证
}

CredentialType

protobuf
enum CredentialType {
  KEY = 0;                      // 电子钥匙
  PASSWORD = 1;                 // 密码(自定义密码)
  OFFLINE_PASSWORD = 2;         // 离线密码(算法生成)
  CARD = 3;                     // 卡片
  FINGERPRINT = 4;              // 指纹
  FACE = 5;                     // 人脸
  PALM_VEIN = 6;                // 掌静脉
  REMOTE = 7;                   // 遥控器
}
标识说明
0KEY电子钥匙,APP/小程序蓝牙开门
1PASSWORD自定义密码,存储在锁内
2OFFLINE_PASSWORD离线密码,算法生成,无需联网验证
3CARDIC卡/NFC卡
4FINGERPRINT指纹
5FACE3D人脸
6PALM_VEIN掌静脉
7REMOTE蓝牙遥控器

凭证归属规则

规则:添加凭证时必须指定归属用户,若不指定则自动创建新用户。

场景示例:

场景操作结果
APP 为自己添加指纹指定 user_id = 当前用户指纹归属当前用户
APP 为家人添加指纹指定 user_id = 家人用户ID指纹归属家人用户
门锁屏幕添加访客指纹不指定用户自动创建新用户,指纹归属新用户
APP 添加临时密码不指定用户自动创建新用户,密码归属新用户

自动创建用户

当通过门锁屏幕或其他方式添加凭证且未指定用户时,门锁会自动创建一个新的普通用户(角色为 USER),并将凭证归属于该用户。创建者 created_by 字段记录执行此操作的用户ID。

胁迫凭证

胁迫凭证是一种安全机制:当用户被胁迫开门时,使用胁迫凭证可以正常开锁,同时静默触发报警通知紧急联系人或安保系统。

  • is_duress = true:该凭证为胁迫凭证
  • 协议层面所有凭证类型都支持胁迫标记
  • 业务层面可根据实际情况限制(如人脸通常不设为胁迫凭证)

胁迫凭证使用场景

典型场景:用户录入两个指纹,食指为正常开锁,小指为胁迫指纹。被歹徒胁迫时使用小指开锁,门正常打开,但后台静默报警。

密码类型

密码凭证分为两种类型:

类型标识说明
自定义密码PASSWORD用户设置的固定密码,存储在锁内
离线密码OFFLINE_PASSWORD服务端算法生成,无需联网即可验证

自定义密码

  • 由用户或管理员设置
  • 存储在门锁内
  • 支持有效期和使用次数限制
  • 适用于家庭成员、长期租户

离线密码

离线密码是通过算法生成的一串数字,密码本身编码了类型和有效期信息,门锁无需联网即可验证。

离线密码子类型:

子类型有效期使用次数典型场景
临时密码10分钟1次看房、临时访客
次数密码2小时最多32次清洁员、维修工
限时密码最多5天不限短租、民宿
时间段密码自定义起止日期不限长租公寓

离线密码原理

离线密码由服务端根据门锁密钥和当前时间生成。密码数字中编码了类型(2bit)和有效期信息,门锁收到密码后通过相同算法解密验证,无需网络通信。

详细算法参见 离线密码

有效期 (ValidityPeriod)

有效期定义凭证的生效时间范围,支持以下维度:

  • 时间范围:指定生效和失效的时间点
  • 周期性时间表:指定每周哪几天、每天哪个时段生效

示例场景

场景配置
永久有效valid_from=0, valid_until=0
2025年全年有效valid_from=2025-01-01, valid_until=2025-12-31
仅工作日 9:00-18:00week_days=周一至周五, start=09:00, end=18:00
周末全天week_days=周六周日

时间表位掩码

week_days 使用位掩码表示星期:

  • 周日 = 1, 周一 = 2, 周二 = 4, 周三 = 8, 周四 = 16, 周五 = 32, 周六 = 64
  • 工作日 = 2+4+8+16+32 = 62
  • 周末 = 1+64 = 65

产品与规格

产品与规格用于企业产品管理和APP显示(名称、Logo等),是业务层面的概念。

什么是产品与规格?

如果你不熟悉产品/规格的概念和划分原则,请参考 产品与规格

产品

产品代表一类功能相同的设备,不区分具体规格(如颜色、材质)。

字段类型说明
productIduint32产品ID,平台统一分配,最多支持4096种产品
productNamestring产品名称,如"智能门锁X100"
brandstring品牌名称,如"鹿客"

广播中的 deviceProductId

BLE广播中的 deviceProductId 即产品ID。同一产品下的不同规格功能一致,APP可据此展示对应的图标和名称。

设备 (Device)

设备是承载用户和凭证的物理实体,包含设备标识、型号、固件版本、当前状态等信息。

protobuf
message Device {
  string serial_num_0 = 1;      // 序列号0(电路板序列号,设备唯一标识)
  string serial_num_1 = 2;      // 序列号1(经销商序列号,可选)
  string model = 3;             // 型号(硬件类型标识)
  string firmware_version = 4;  // 固件版本
  uint32 protocol_version = 5;  // 协议版本
  DeviceStatus status = 6;      // 设备状态
  uint32 battery_level = 7;     // 电池电量(0-100)
  uint64 current_time = 8;      // 设备当前时间(UNIX毫秒时间戳)
}

型号 (model)

model 是硬件类型的精准定位符,用于协议对接时确定设备类型。

字段类型说明
modelstring型号标识,如"X100-BK"

model 值的来源:

场景来源说明
有产品管理后台产品的具体规格model 与后台配置的规格关联
无产品管理后台设备端固定值由固件定义唯一的型号标识

model 的用途

  • 协议对接:根据 model 确定设备支持的指令集和功能
  • 固件升级:根据 model 匹配对应的固件包
  • 售后服务:根据 model 定位硬件版本

model 与产品规格的关系

model 可以与产品管理后台的规格关联,也可以独立使用。协议层面只关心 model 值本身,不依赖产品管理后台。

序列号

设备使用两级序列号体系进行标识:

字段名称写入方说明
serial_num_0电路板序列号电路板厂商设备唯一标识,终身不变
serial_num_1经销商序列号成品设备厂商可选,未写入时为空字符串

序列号格式约束:

  • 长度:8-16个字符
  • 字符集:a-zA-Z0-9-_
  • serial_num_0 在同一产品下唯一,不可重复

serial_num_0 的重要性

serial_num_0 是设备的唯一标识,用于:

  • 设备发现(BLE广播、二维码、NFC)
  • 云端设备注册和管理
  • 生成其他唯一ID

应始终使用 serial_num_0 而非MAC地址作为设备标识,因为设备不一定具有蓝牙或WiFi模块。

不可变性

serial_num_0 由固件生成或电路板生产线写入,跟随设备终身,恢复出厂设置也不会改变。

DeviceStatus

门锁类设备的状态定义:

protobuf
enum DeviceStatus {
  UNKNOWN = 0;                  // 状态未知
  UNLOCKED = 1;                 // 已开锁
  LOCKED = 2;                   // 已上锁
  DEADLOCKED = 3;               // 已反锁
}
标识说明
0UNKNOWN状态未知
1UNLOCKED门已开锁(可推门)
2LOCKED门已上锁(正常锁定)
3DEADLOCKED门已反锁(室内反锁,室外无法开启)

状态未知

当设备未配备闭门检测传感器时,此字段返回 UNKNOWN

事件 (Event)

事件记录门锁上发生的操作,用于审计和追溯。

protobuf
message Event {
  uint64 event_id = 1;          // 事件ID
  EventType type = 2;           // 事件类型
  uint64 timestamp = 3;         // 发生时间(UNIX毫秒时间戳)
  uint32 user_id = 4;           // 关联用户ID(0=系统事件)
  uint32 credential_id = 5;     // 关联凭证ID(0=无关联凭证)
  CredentialType credential_type = 6; // 凭证类型
  string detail = 7;            // 事件详情(JSON格式)
}
字段类型说明
event_iduint64事件唯一ID
typeEventType事件类型枚举
timestampuint64发生时间(UNIX毫秒时间戳)
user_iduint32关联用户ID,系统事件为 0
credential_iduint32关联凭证ID,无关联凭证为 0
credential_typeCredentialType凭证类型
detailstring事件详情,JSON 格式字符串

事件类型

类型说明
开锁/上锁锁状态变化
用户增删用户管理操作
凭证增删凭证管理操作
设置变更门锁参数修改
报警包括胁迫报警、防撬报警等
系统事件低电量、固件升级等

事件归因

每个事件都会记录:

  • 操作用户:执行操作的用户(通过凭证开锁时,记录凭证归属的用户)
  • 使用凭证:使用的凭证ID和类型
  • 事件详情:额外的上下文信息

事件类型枚举和每种事件的详情格式,参见 事件类型

通用响应 (Response)

所有响应消息都包含以下公共字段:

protobuf
message Response {
  uint32 code = 1;              // 状态码(0=成功)
  string message = 2;           // 状态消息
  // ... 其他业务字段
}
字段类型说明
codeuint320 表示成功,非 0 表示错误
messagestring人类可读的状态消息

详见 错误处理

核心规则总结

  1. 凭证必须归属用户:不存在独立凭证
  2. 自动创建用户:添加凭证时不指定用户,则自动创建新用户
  3. 级联删除:删除用户时,其所有凭证一并删除
  4. 完整追溯:事件记录用户和凭证信息,便于审计
  5. 电子钥匙是凭证:电子钥匙与密码、指纹等地位相同,用户使用蓝牙开锁需拥有电子钥匙凭证

物联网设备通信协议文档