Appearance
数据结构
本文档定义蓝牙协议 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; // 遥控器
}| 值 | 标识 | 说明 |
|---|---|---|
| 0 | KEY | 电子钥匙,APP/小程序蓝牙开门 |
| 1 | PASSWORD | 自定义密码,存储在锁内 |
| 2 | OFFLINE_PASSWORD | 离线密码,算法生成,无需联网验证 |
| 3 | CARD | IC卡/NFC卡 |
| 4 | FINGERPRINT | 指纹 |
| 5 | FACE | 3D人脸 |
| 6 | PALM_VEIN | 掌静脉 |
| 7 | REMOTE | 蓝牙遥控器 |
凭证归属规则
规则:添加凭证时必须指定归属用户,若不指定则自动创建新用户。
场景示例:
| 场景 | 操作 | 结果 |
|---|---|---|
| APP 为自己添加指纹 | 指定 user_id = 当前用户 | 指纹归属当前用户 |
| APP 为家人添加指纹 | 指定 user_id = 家人用户ID | 指纹归属家人用户 |
| 门锁屏幕添加访客指纹 | 不指定用户 | 自动创建新用户,指纹归属新用户 |
| APP 添加临时密码 | 不指定用户 | 自动创建新用户,密码归属新用户 |
自动创建用户
当通过门锁屏幕或其他方式添加凭证且未指定用户时,门锁会自动创建一个新的普通用户(角色为 USER),并将凭证归属于该用户。创建者 created_by 字段记录执行此操作的用户ID。
胁迫凭证
胁迫凭证是一种安全机制:当用户被胁迫开门时,使用胁迫凭证可以正常开锁,同时静默触发报警通知紧急联系人或安保系统。
is_duress = true:该凭证为胁迫凭证- 协议层面所有凭证类型都支持胁迫标记
- 业务层面可根据实际情况限制(如人脸通常不设为胁迫凭证)
胁迫凭证使用场景
典型场景:用户录入两个指纹,食指为正常开锁,小指为胁迫指纹。被歹徒胁迫时使用小指开锁,门正常打开,但后台静默报警。
密码类型
密码凭证分为两种类型:
| 类型 | 标识 | 说明 |
|---|---|---|
| 自定义密码 | PASSWORD | 用户设置的固定密码,存储在锁内 |
| 离线密码 | OFFLINE_PASSWORD | 服务端算法生成,无需联网即可验证 |
自定义密码
- 由用户或管理员设置
- 存储在门锁内
- 支持有效期和使用次数限制
- 适用于家庭成员、长期租户
离线密码
离线密码是通过算法生成的一串数字,密码本身编码了类型和有效期信息,门锁无需联网即可验证。
离线密码子类型:
| 子类型 | 有效期 | 使用次数 | 典型场景 |
|---|---|---|---|
| 临时密码 | 10分钟 | 1次 | 看房、临时访客 |
| 次数密码 | 2小时 | 最多32次 | 清洁员、维修工 |
| 限时密码 | 最多5天 | 不限 | 短租、民宿 |
| 时间段密码 | 自定义起止日期 | 不限 | 长租公寓 |
有效期 (ValidityPeriod)
有效期定义凭证的生效时间范围,支持以下维度:
- 时间范围:指定生效和失效的时间点
- 周期性时间表:指定每周哪几天、每天哪个时段生效
示例场景
| 场景 | 配置 |
|---|---|
| 永久有效 | valid_from=0, valid_until=0 |
| 2025年全年有效 | valid_from=2025-01-01, valid_until=2025-12-31 |
| 仅工作日 9:00-18:00 | week_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等),是业务层面的概念。
什么是产品与规格?
如果你不熟悉产品/规格的概念和划分原则,请参考 产品与规格。
产品
产品代表一类功能相同的设备,不区分具体规格(如颜色、材质)。
| 字段 | 类型 | 说明 |
|---|---|---|
productId | uint32 | 产品ID,平台统一分配,最多支持4096种产品 |
productName | string | 产品名称,如"智能门锁X100" |
brand | string | 品牌名称,如"鹿客" |
广播中的 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 是硬件类型的精准定位符,用于协议对接时确定设备类型。
| 字段 | 类型 | 说明 |
|---|---|---|
model | string | 型号标识,如"X100-BK" |
model 值的来源:
| 场景 | 来源 | 说明 |
|---|---|---|
| 有产品管理后台 | 产品的具体规格 | model 与后台配置的规格关联 |
| 无产品管理后台 | 设备端固定值 | 由固件定义唯一的型号标识 |
model 的用途
- 协议对接:根据 model 确定设备支持的指令集和功能
- 固件升级:根据 model 匹配对应的固件包
- 售后服务:根据 model 定位硬件版本
model 与产品规格的关系
model 可以与产品管理后台的规格关联,也可以独立使用。协议层面只关心 model 值本身,不依赖产品管理后台。
序列号
设备使用两级序列号体系进行标识:
| 字段 | 名称 | 写入方 | 说明 |
|---|---|---|---|
serial_num_0 | 电路板序列号 | 电路板厂商 | 设备唯一标识,终身不变 |
serial_num_1 | 经销商序列号 | 成品设备厂商 | 可选,未写入时为空字符串 |
序列号格式约束:
- 长度:8-16个字符
- 字符集:
a-z、A-Z、0-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; // 已反锁
}| 值 | 标识 | 说明 |
|---|---|---|
| 0 | UNKNOWN | 状态未知 |
| 1 | UNLOCKED | 门已开锁(可推门) |
| 2 | LOCKED | 门已上锁(正常锁定) |
| 3 | DEADLOCKED | 门已反锁(室内反锁,室外无法开启) |
状态未知
当设备未配备闭门检测传感器时,此字段返回 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_id | uint64 | 事件唯一ID |
type | EventType | 事件类型枚举 |
timestamp | uint64 | 发生时间(UNIX毫秒时间戳) |
user_id | uint32 | 关联用户ID,系统事件为 0 |
credential_id | uint32 | 关联凭证ID,无关联凭证为 0 |
credential_type | CredentialType | 凭证类型 |
detail | string | 事件详情,JSON 格式字符串 |
事件类型
| 类型 | 说明 |
|---|---|
| 开锁/上锁 | 锁状态变化 |
| 用户增删 | 用户管理操作 |
| 凭证增删 | 凭证管理操作 |
| 设置变更 | 门锁参数修改 |
| 报警 | 包括胁迫报警、防撬报警等 |
| 系统事件 | 低电量、固件升级等 |
事件归因
每个事件都会记录:
- 操作用户:执行操作的用户(通过凭证开锁时,记录凭证归属的用户)
- 使用凭证:使用的凭证ID和类型
- 事件详情:额外的上下文信息
事件类型枚举和每种事件的详情格式,参见 事件类型。
通用响应 (Response)
所有响应消息都包含以下公共字段:
protobuf
message Response {
uint32 code = 1; // 状态码(0=成功)
string message = 2; // 状态消息
// ... 其他业务字段
}| 字段 | 类型 | 说明 |
|---|---|---|
code | uint32 | 0 表示成功,非 0 表示错误 |
message | string | 人类可读的状态消息 |
详见 错误处理。
核心规则总结
- 凭证必须归属用户:不存在独立凭证
- 自动创建用户:添加凭证时不指定用户,则自动创建新用户
- 级联删除:删除用户时,其所有凭证一并删除
- 完整追溯:事件记录用户和凭证信息,便于审计
- 电子钥匙是凭证:电子钥匙与密码、指纹等地位相同,用户使用蓝牙开锁需拥有电子钥匙凭证
