【蓝牙精品系列文档】【04_blemesh model】01_访问层

发布时间:2026/7/15 5:02:10

【蓝牙精品系列文档】【04_blemesh model】01_访问层 Access Layer 访问层章节定位Week3 已覆盖Bearer 承载层 → Network 网络层 → Lower Transport 底层传输层 → Upper Transport 上层传输层(应用安全层)。本章从Access Layer开始,向上衔接 Foundation Model 与业务 Model。Access 层是传输层与模型层之间的中间层:不负责加解密(Upper Transport 已解密),也不执行业务逻辑(Model 层负责),核心工作是解析 Access PDU、按地址与 Opcode 路由到正确的 Model 实例。┌─────────────────────────────────────────────────────────┐ │ Model Layer 业务模型层(OnOff、Lightness…) │ ├─────────────────────────────────────────────────────────┤ │ Foundation Model 基础模型层(Config、Health…) │ ├─────────────────────────────────────────────────────────┤ │ Access Layer ◀──── 本章:Opcode 解析、Element/Model 路由│ ├─────────────────────────────────────────────────────────┤ │ Upper Transport AppKey/DevKey 加密、TransMIC │ ├─────────────────────────────────────────────────────────┤ │ Lower Transport 分段重组、Segment ACK │ ├─────────────────────────────────────────────────────────┤ │ Network Layer NetKey、Relay、IV Index │ ├─────────────────────────────────────────────────────────┤ │ Bearer Layer ADV / GATT │ └─────────────────────────────────────────────────────────┘Access 层一句话Upper Transport 解密后得到明文 Access PDU;Access 层按DST 地址 + Opcode查Element → Model表,把消息交给对应 Model 的 handler 处理。一、Access PDU 格式Access PDU 是 Upper Transport 解密后的应用层可见明文,结构固定:Access PDU ┌─────────────┬──────────────────────────────────┐ │ Opcode │ Parameters(可选) │ │ 1 ~ 3 字节 │ 0 ~ 多字节,由消息定义决定 │ └─────────────┴──────────────────────────────────┘字段作用Opcode消息类型 ID;Access 层据此匹配 Model 的 handlerParameters载荷;Set 写入 State,Get 通常为空,Status 从 State 读出Opcode 编码规则长度取值范围归属进 Access 层?1 字节0x00~0x7F由 Network PDU 的 CTL 位决定归属:CTL=1 → Transport Control;CTL=0 → Foundation 层 Access 消息CTL=1不进;CTL=0进2 字节0x8000~0xBFFFAccess 层 SIG 消息(业务 Model 全部 + Foundation 大部分),CTL=0进3 字节0xC0xxxxAccess 层厂商自定义:0xC0+ Vendor Opcode + Company ID,CTL=0进(查vnd_models[])关键区分:区分 Control vs Access 的不是 Opcode 长度,是 Network PDU 的 CTL 位。1 字节 Opcode 既可能是 Transport Control(CTL=1,Transport 层自处理),也可能是 Foundation 层 Access 消息(CTL=0,进 Access 层查 Model handler)。Access 层会收到 1/2/3 字节 Opcode 都可能——只有 CTL=1 的 Control 消息才不进 Access。1 字节 Opcode 的两种归属1 字节 Opcode 空间(0x00~0x7F)被 SIG分给两类完全不同的消息,靠 CTL 位区分:第一类:Transport Control(CTL=1)—— 不进 Access 层源码transport.h:23:#define TRANS_CTL_OP_ACK 0x00 #define TRANS_CTL_OP_FRIEND_POLL 0x01 #define TRANS_CTL_OP_FRIEND_UPDATE 0x02 #define TRANS_CTL_OP_FRIEND_REQ 0x03 #define TRANS_CTL_OP_FRIEND_OFFER 0x04 #define TRANS_CTL_OP_FRIEND_CLEAR 0x05 #define TRANS_CTL_OP_FRIEND_CLEAR_CFM 0x06 #define TRANS_CTL_OP_FRIEND_SUB_ADD 0x07 #define TRANS_CTL_OP_FRIEND_SUB_REM 0x08 #define TRANS_CTL_OP_FRIEND_SUB_CFM 0x09 #define TRANS_CTL_OP_HEARTBEAT 0x0aOpcode名称方向用途0x00Segment ACK接收方 → 发送方分段消息确认,携带 BlockAck 位图0x01Friend PollLPN → Friend低功耗节点轮询 Friend 是否有缓存消息0x02Friend UpdateFriend → LPN回复 Poll,告知是否有消息 + 当前 IV Index/Flags0x03Friend RequestLPN → 周边广播找 Friend,携带 ReceiveWindow/QueueSize 等参数0x04Friend Offer候选 Friend → LPN应答 Request,告知自身缓存能力0x05Friend Clear新 Friend → 旧 FriendLPN 换 Friend 时,新 Friend 通知旧 Friend 释放0x06Friend Clear Confirm旧 Friend → 新 Friend确认释放,握手完成0x07Friend Subscription AddLPN → FriendLPN 让 Friend 帮它监听新增的 Group/Virtual 地址0x08Friend Subscription RemoveLPN → FriendLPN 让 Friend 取消监听某些地址0x09Friend Subscription ConfirmFriend → LPN确认订阅列表已更新0x0AHeartbeat节点 → 周边周期心跳,携带 Active Relay/Proxy/Feature 等位图 + TTL第二类:Foundation 层 Access 消息(CTL=0)—— 进 Access 层源码foundation.h:12:#define OP_APP_KEY_ADD BT_MESH_MODEL_OP_1(0x00) #define OP_APP_KEY_UPDATE BT_MESH_MODEL_OP_1(0x01) #define OP_DEV_COMP_DATA_STATUS BT_MESH_MODEL_OP_1(0x02) #define OP_MOD_PUB_SET BT_MESH_MODEL_OP_1(0x03) #define OP_HEALTH_CURRENT_STATUS BT_MESH_MODEL_OP_1(0x04) #define OP_HEALTH_FAULT_STATUS BT_MESH_MODEL_OP_1(0x05) #define OP_HEARTBEAT_PUB_STATUS BT_MESH_MODEL_OP_1(0x06)Opcode名称方向类型用途0x00Config AppKey AddClient → Server命令添加 AppKey(最高频 Config 命令,故给短 Opcode)0x01Config AppKey UpdateClient → Server命令更新 AppKey(Key Refresh 用)0x02Config Composition Data StatusServer → ClientStatus回复 Composition Data Get,携带完整 Composition0x03Config Model Publication SetClient → Server命令设置 Model Publish 参数0x04Health Current StatusServer → ClientStatus上报当前 Health Fault 列表0x05Health Fault StatusServer → ClientStatus回复 Health Fault Get/Test,携带 Fault 列表0x06Config Heartbeat Publication StatusServer → ClientStatus回复 Heartbeat Pub Get/Set,携带发布配置重要观察:这 7 个 1 字节 Access Opcode全部属于 Foundation 层(Config + Health + Heartbeat),业务 Model(Generic/Lighting/Sensor 等)没有任何 1 字节 Opcode——业务消息全部用 2 字节(0x82xx 系列)Foundation 层也不是全部用 1 字节:只有这 7 个高频消息用短 Opcode,其余(Composition Data Get 0x8008、AppKey Delete 0x8000、Beacon Get 0x8009 等)仍用 2 字节1 字节空间混合了命令和 Status:0x00/0x01/0x03 是命令,0x02/0x04/0x05/0x06 是 Status三类 Opcode 归属对比(修正版)维度1 字节(CTL=1)Control1 字节(CTL=0)Foundation2 字节(CTL=0)SIG 业务3 字节(CTL=0)Vendor归属层Transport 层 ControlAccess 层 Foundation ModelAccess 层 SIG 业务 ModelAccess 层厂商 Model加密NetKey 加密即可,不加密 AppKeyAppKey/DevKey 加密 + TransMICAppKey/DevKey 加密 + TransMICAppKey/DevKey 加密 + TransMIC是否进 Access 层不进,Transport 层自己处理进,查 Config/Health Server 的op[]进,查业务 Model 的op[]进,查vnd_models[]谁定义Mesh Profile Spec §3.4.xMesh Profile Spec §5.4(Foundation)Mesh Model Spec(各 Model 章节)厂商自定义(Company ID 区分)消息类型ACK/Friendship/HeartbeatConfig/Health/Heartbeat Pub 的高频消息OnOff Set、Lightness Get 等业务厂商私有业务路由方式Transport 层按ctl_opswitch,不经 Model handlerAccess 层find_op()→ Config/Health Server handlerAccess 层find_op()→ 业务 Model handler同左,但查vnd_models[]例子0x00 ACK、0x01 Friend Poll0x00 AppKey Add、0x02 Comp Data Status0x8202 OnOff Set、0x8008 Comp Data Get0xC0xxxx 厂商私有源码证据:CTL=1 的 Control 消息在 Transport 层直接按ctl_opswitch 分发,根本不调用bt_mesh_model_recv():case TRANS_CTL_OP_ACK: /* ... 处理 Segment ACK ... */ break; /* ... */ switch (ctl_op) { case TRANS_CTL_OP_FRIEND_POLL: /* ... */ case TRANS_CTL_OP_FRIEND_REQ: /* ... */ case TRANS_CTL_OP_FRIEND_CLEAR: /* ... */ case TRANS_CTL_OP_FRIEND_CLEAR_CFM: /* ... */ case TRANS_CTL_OP_FRIEND_SUB_ADD: /* ... */ case TRANS_CTL_OP_

相关新闻