BLE Mesh蓝牙组网技术详细解析之Access Layer访问层(六)

news2024/12/27 10:46:42

目录

一、什么是BLE Mesh Access Layer访问层?

二、Access payload

2.1 Opcode

三、Access layer behavior

3.1 Access layer发送消息的流程

3.2 Access layer接收消息的流程

3.3 Unacknowledged and acknowledged messages

3.3.1 Unacknowledged message

3.3.2 Acknowledged message

3.4 Example message sequence charts

3.4.1 Acknowledged Get

3.4.2 Acknowledged Set

3.4.3 Unacknowledged Set

3.4.4 Acknowledged set with periodic publishing

四、资料获取


一、什么是BLE Mesh Access Layer访问层?

BLE Mesh Access Layer是蓝牙Mesh协议栈的一部分,它主要负责以下几个方面的功能

  • 定义应用数据的格式,例如Opcode和参数字段。
  • 定义并控制在上层传输层中执行的应用数据的加密和解密,使用AppKey或DeviceKey作为密钥。
  • 在将数据上传到模型层之前,对来自上层传输层的数据进行验证,判断其是否适用于该网络和应用,例如检查地址和AppKey是否匹配。
  • 在将数据下发到上层传输层之前,根据模型层的指令,填充源地址、目的地址、TTL等字段,以及设置重传参数。

二、Access payload

Field Name

Size (octets)

Notes

Opcode

1, 2, or 3

Operation Code

Parameters

0 to 379

Application Parameters

  • Opcode:1字节、2字节或3字节的操作码,用于标识消息的类型和含义。
  • Parameters:一个可变长度的参数字段,用于携带消息的具体内容。参数字段的长度由Opcode和上层传输层的PDU的长度共同决定,最大为379字节,取决于Opcode的长度

一个access payload最多可以发送32个片段,每个片段12字节。这意味着最大值 包括TransMIC在内的字节数是384

对于4字节的TransMIC,access payload最大大小是380字节,因此对于单个字节的操作码,参数字段最多可以达到379字节。对于2字节的操作码,参数字段最多可以有378个字节。对于一个3字节的操作码,parameters字段最多可以有377个字节。

传输层可以将消息分割成多段PDU,以便在网络层上传输。下表显示了根据包的数量和TransMIC的大小而定的最大有用的应用包大小。

Number of Packets

Maximum useful access payload size (octets)

32 bit TransMIC

64 bit TransMIC

1

11 (unsegmented)

n/a

1

8 (segmented)

4 (segmented)

2

20

16

3

32

28

n

(n×12)-4

(n×12)-8

32

380

376

2.1 Opcode

  • 1字节操作码:由SIG定义,用于标准的模型消息,例如Generic OnOff Set,Generic Level Get等。1字节操作码的第一位为0,剩下的7位表示具体的操作码值。
  • 2字节操作码:由SIG定义,用于扩展的模型消息,例如Scene Store,Scene Delete等。2字节操作码的第一位为1,第二位为0,剩下的14位表示具体的操作码值。
  • 3字节操作码:由供应商定义,用于自定义的模型消息,例如Vendor Model Status,Vendor Model Indication等。3字节操作码的第一位为1,第二位为1。其中的2个字节被指定为厂商ID(CID),该部分在表中以“z”表示。在整个mesh网络中,每个厂商ID最多支持64个厂商操作码。用户可用的只有6位(xxxxxx),因此总共是64个操作码。

Opcode Format

Notes

0xxxxxxx (excluding 01111111)

1-octet Opcodes

01111111

Reserved for Future Use

10xxxxxx xxxxxxxx

2-octet Opcodes

11xxxxxx zzzzzzzz zzzzzzzz

3-octet Opcodes

三、Access layer behavior

3.1 Access layer发送消息的流程

  • 首先,访问层接收到来自模型层的消息,消息包含操作码(Opcode)和有效载荷(Payload)。操作码是用于标识消息的类型和含义的一个字节或多个字节的值,有效载荷是消息的主要内容,包含了模型的状态值、参数、属性等信息。
  • 然后,访问层根据下发来的模型ID找到对应的存储信息,包括源地址(SRC)、目的地址(DST)、应用密钥(AppKey)等。源地址是该模型对应的元素的单播地址,目的地址是该模型设置的发布地址,应用密钥是该模型绑定的用于加密和解密的密钥。
  • 接着,访问层将消息和存储信息一起传递给上层传输层,上层传输层会根据应用密钥对消息进行加密和认证,生成一个传输层数据单元(Upper Transport PDU),并为每个消息分配一个序列号(SEQ)用于防护中继/重放攻击。
  • 然后,上层传输层将传输层数据单元和其他信息传递给下层传输层,下层传输层会根据消息的长度决定是否需要对消息进行分段,如果需要分段,会生成多个分段的传输层数据单元(Segmented Upper Transport PDU),并为每个分段分配一个分段索引(SEG)用于重组消息。
  • 接着,下层传输层将分段的传输层数据单元和其他信息传递给网络层,网络层会根据网络密钥(NetKey)对分段的传输层数据单元进行加密和混淆,生成一个网络层数据单元(Network PDU),并为每个网络层数据单元分配一个网络标识符(IVI)用于识别网络。
  • 然后,网络层将网络层数据单元和其他信息传递给承载层,承载层会根据承载类型(Advertising Bearer或GATT Bearer)对网络层数据单元进行封装,生成一个承载层数据单元(Bearer PDU),并通过底层的BLE协议栈将承载层数据单元发送出去。
  • 最后,承载层会根据消息的类型(Acknowledged Message或Unacknowledged Message)决定是否需要对消息进行重传,如果需要重传,会根据重传参数(重传次数、重传间隔等)进行重传,直到收到应答消息或达到重传次数上限为止。
/*源自开源协议栈NimBLE*/
static int model_send(struct bt_mesh_model *model,
		      struct bt_mesh_net_tx *tx, bool implicit_bind,
		      struct os_mbuf *msg,
		      const struct bt_mesh_send_cb *cb, void *cb_data)
{
	BT_DBG("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->ctx->net_idx,
	       tx->ctx->app_idx, tx->ctx->addr);
	BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len));

	if (!bt_mesh_is_provisioned()) {
		BT_ERR("Local node is not yet provisioned");
		return -EAGAIN;
	}

	if (net_buf_simple_tailroom(msg) < 4) {
		BT_ERR("Not enough tailroom for TransMIC");
		return -EINVAL;
	}

	if (msg->om_len > BT_MESH_TX_SDU_MAX - 4) {
		BT_ERR("Too big message");
		return -EMSGSIZE;
	}

	if (!implicit_bind && !model_has_key(model, tx->ctx->app_idx)) {
		BT_ERR("Model not bound to AppKey 0x%04x", tx->ctx->app_idx);
		return -EINVAL;
	}

	return bt_mesh_trans_send(tx, msg, cb, cb_data);
}

int bt_mesh_model_send(struct bt_mesh_model *model,
		       struct bt_mesh_msg_ctx *ctx,
		       struct os_mbuf *msg,
		       const struct bt_mesh_send_cb *cb, void *cb_data)
{
	struct bt_mesh_net_tx tx = {
		.sub = bt_mesh_subnet_get(ctx->net_idx),
		.ctx = ctx,
		.src = bt_mesh_model_elem(model)->addr,
		.xmit = bt_mesh_net_transmit_get(),
		.friend_cred = 0,
	};

	return model_send(model, &tx, false, msg, cb, cb_data);
}

3.2 Access layer接收消息的流程

  • 首先,访问层从承载层接收到来自底层低功耗蓝牙协议栈的消息,消息包含操作码(Opcode)和有效载荷(Payload)。操作码是用于标识消息的类型和含义的一个字节或多个字节的值,有效载荷是消息的主要内容,包含了模型的状态值、参数、属性等信息。
  • 然后,访问层根据消息中的网络密钥索引(NetKeyIndex)和应用密钥索引(AppKeyIndex)找到对应的网络密钥(NetKey)和应用密钥(AppKey),并将消息传递给上层传输层。上层传输层会根据网络密钥和应用密钥对消息进行解密和认证,还原出原始的操作码和有效载荷。
  • 接着,访问层根据消息的目的地址(DST)字段,找到当前节点中订阅了该地址或者元素地址为该地址的所有模型,再判断该消息与该模型是否绑定了同一个应用密钥,满足了要求再上报至模型层,模型再进行操作码和有效载荷的检查。
/*BLE Mesh访问层接收数据子函数*/
/*源自开源协议栈NimBLE*/
void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf)
{
	struct bt_mesh_model *models, *model;
	const struct bt_mesh_model_op *op;
	u32_t opcode;
	u8_t count;
	int i;

	BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx,
	       rx->ctx.addr, rx->ctx.recv_dst);
	BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len));

	if (get_opcode(buf, &opcode) < 0) {
		BT_WARN("Unable to decode OpCode");
		return;
	}

	BT_DBG("OpCode 0x%08x", (unsigned) opcode);

	for (i = 0; i < dev_comp->elem_count; i++) {
		struct bt_mesh_elem *elem = &dev_comp->elem[i];
		struct net_buf_simple_state state;

		/* SIG models cannot contain 3-byte (vendor) OpCodes, and
		 * vendor models cannot contain SIG (1- or 2-byte) OpCodes, so
		 * we only need to do the lookup in one of the model lists.
		 */
		if (BT_MESH_MODEL_OP_LEN(opcode) < 3) {
			models = elem->models;
			count = elem->model_count;
		} else {
			models = elem->vnd_models;
			count = elem->vnd_model_count;
		}

		op = find_op(models, count, opcode, &model);
		if (!op) {
			BT_DBG("No OpCode 0x%08x for elem %d", opcode, i);
			continue;
		}

		if (!model_has_key(model, rx->ctx.app_idx)) {
				continue;
			}

		if (!model_has_dst(model, rx->ctx.recv_dst)) {
			continue;
		}

		if (buf->om_len < op->min_len) {
			BT_ERR("Too short message for OpCode 0x%08x", opcode);
			continue;
		}

		/* The callback will likely parse the buffer, so
		 * store the parsing state in case multiple models
		 * receive the message.
		 */
		net_buf_simple_save(buf, &state);
		op->func(model, &rx->ctx, buf);
		net_buf_simple_restore(buf, &state);
	}
}

3.3 Unacknowledged and acknowledged messages

  • 消息的类型:消息可以分为需要应答的消息(Acknowledged Message)和不需要应答的消息(Unacknowledged Message)。需要应答的消息要求接收端回复一个状态消息作为应答,不需要应答的消息则不需要回复。
  • 消息的目标地址:消息可以发送到单播地址(Unicast Address)、组播地址(Group Address)或虚拟地址(Virtual Address)。目标地址决定了消息的发布和订阅方式,以及消息的中继和重传机制。
  • 消息的操作码(Opcode):操作码是用于标识消息的类型和含义的一个字节或多个字节的值。操作码的长度和值由消息的第一位和第二位决定,操作码的值可以是预定义的或者厂商自定义的。
  • 消息的有效载荷(Payload):有效载荷是消息的主要内容,包含了模型的状态值、参数、属性等信息。有效载荷的长度和格式由操作码和模型定义决定。

3.3.1 Unacknowledged message

unAcknowledged Message是一种不需要接收端回复应答的消息。它的定义如下

  • unAcknowledged Message的操作码(Opcode)的第一位(bit 7)必须为0,表示操作码的长度为一个字节。
  • unAcknowledged Message的有效载荷(Payload)的长度和格式由操作码和模型定义决定,通常包含了目标状态(Target State)或查询参数(Query Parameters)等信息。
  • unAcknowledged Message的发送端(Client Model)会在发送消息后不等待接收端(Server Model)的应答消息(Status Message),而是直接结束消息发送过程。

3.3.2 Acknowledged message

Acknowledged Message是一种需要接收端回复一个状态消息作为应答的消息。它的定义如下

  • Acknowledged Message的操作码(Opcode)的第一位(bit 7)必须为0,表示操作码的长度为一个字节。
  • Acknowledged Message的有效载荷(Payload)的长度和格式由操作码和模型定义决定,通常包含了目标状态(Target State)或查询参数(Query Parameters)等信息。
  • Acknowledged Message的发送端(Client Model)会在发送消息后等待一段时间(Acknowledged Message Timeout),如果在这段时间内没有收到接收端(Server Model)的应答消息(Status Message),则会重发消息,直到收到应答消息或达到重发次数上限(Acknowledged Message Retransmissions)为止。

3.4 Example message sequence charts

3.4.1 Acknowledged Get

Acknowledged Get是一种用于从服务器端请求状态信息的消息类型。它属于Acknowledged MSG的一种,也就是说,当服务器端收到这个消息后,需要回复一个对应的Status消息,告诉客户端当前的状态值。这样可以保证客户端和服务器端的状态同步,也可以避免消息丢失或重复的问题。

例如,如果客户端想要知道一个灯的亮度,它可以发送一个Generic Level Get消息,这是一种Acknowledged Get消息,它的Opcode是0x8205。服务器端收到这个消息后,会回复一个Generic Level Status消息,它的Opcode是0x8206,它的Payload包含了当前的亮度值。

 

3.4.2 Acknowledged Set

Acknowledged Set是一种用于向服务器端发送状态设置请求的消息类型。它也属于Acknowledged MSG的一种,也就是说,当服务器端收到这个消息后,需要回复一个对应的Status消息,告诉客户端状态是否设置成功。这样可以保证客户端和服务器端的状态同步,也可以避免消息丢失或重复的问题。

例如,如果客户端想要设置一个灯的亮度,它可以发送一个Generic Level Set消息,这是一种Acknowledged Set消息,它的Opcode是0x8207。它的Payload包含了要设置的亮度值和一个可选的Transition Time和Delay参数,用于控制灯的渐变效果。服务器端收到这个消息后,会回复一个Generic Level Status消息,它的Opcode是0x8206,它的Payload包含了当前的亮度值。

 

3.4.3 Unacknowledged Set

Unacknowledged Set是一种用于向服务器端发送状态设置请求的消息类型。它不属于Acknowledged MSG,也就是说,当服务器端收到这个消息后,不需要回复一个对应的Status消息,也不会把当前状态的改变后的结果通过Publish地址向四周广播。这样可以减少网络层的负载,提高传输效率,但也可能导致客户端和服务器端的状态不同步,或者消息丢失或重复的问题。

例如,如果客户端想要设置一个灯的亮度,它可以发送一个Generic Level Set Unacknowledged消息,这是一种Unacknowledged Set消息,它的Opcode是0x8208。它的Payload包含了要设置的亮度值和一个可选的Transition Time和Delay参数,用于控制灯的渐变效果。服务器端收到这个消息后,不会回复任何消息,也不会广播当前的亮度值。

 

3.4.4 Acknowledged set with periodic publishing

Acknowledged set with periodic publishing是一种用于向服务器端发送状态设置请求并启用周期性状态发布的消息类型。它属于Acknowledged MSG的一种,也就是说,当服务器端收到这个消息后,需要回复一个对应的Status消息,告诉客户端状态是否设置成功,并且按照设定的时间间隔和发布地址,定期广播当前的状态值。这样可以保证客户端和服务器端的状态同步,也可以让其他订阅了发布地址的节点获取服务器端的状态信息。

例如,如果客户端想要设置一个灯的亮度,并且让灯每隔5秒钟发布一次当前的亮度值,它可以发送一个Generic Level Set消息,这是一种Acknowledged Set消息,它的Opcode是0x8207。它的Payload包含了要设置的亮度值和一个可选的Transition Time和Delay参数,用于控制灯的渐变效果。它还需要配置灯的发布地址和发布周期,比如发布地址为0xC000(所有节点的组播地址),发布周期为5秒。服务器端收到这个消息后,会回复一个Generic Level Status消息,它的Opcode是0x8206,它的Payload包含了当前的亮度值。同时,服务器端会每隔5秒钟向0xC000地址发送一个Generic Level Status消息,让其他节点知道当前的亮度值

 

四、资料获取

通过点击以下链接,您可以获取BLE Mesh模块原理图、源代码以及开发资料。链接地址将为您提供详细的文件资料,以供您进行参考和使用。

如果您在使用过程中遇到任何问题或疑虑,欢迎加我QQ ,一起探讨技术问题,我的QQ号是986571840,加的时候请注明CSDN。

BLE Mesh蓝牙组网模块 - 硬创社 (jlc.com)icon-default.png?t=N7T8https://x.jlc.com/platform/detail/001d23cba7b64b0d9df5b9b69720fadb

感谢各位用户点赞、分享、在看,这些行为让知识得以更加广泛地传播,从而让更多人受益。

请在转载作品时注明出处,严禁抄袭行为。
 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1353013.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

轻松上手:Postman Interceptor 插件使用指南

什么是 Postman&#xff1f; Postman 是一种用于测试和开发 API 的工具&#xff0c;让开发者可以轻松地构建、发送、调试 HTTP 请求&#xff0c;并检查响应结果。通过Postman&#xff0c;开发者可以在不编写代码的情况下快速测试 API 的正确性和可靠性。Postman 还支持协作和自…

ubuntu18.04安装MySQL

1.安装mysql服务器端 sudo apt-get -y install mysql-server&#xff08;18.04/20.04不会提示输入密码&#xff0c;默认是没有密码&#xff09; 2.安装mysql客户端 sudo apt-get -y install mysql-client3.安装mysql模块 sudo apt-get -y install libmysqlclient-dev4.验证是…

融资项目——全局统一日志说明

通过日志可以查看程序的运行信息和异常信息等&#xff0c;便于维护。日志级别分为TRACE、DEBUG、INFO、WARN、ERROR级别&#xff0c;越往后打印的日志信息越少&#xff0c;如ERROR 级别只会在程序运行出错时才会打印日志。可在application.properties中设置日志级别。 logging…

Python+OpenGL绘制3D模型(七)制作3dsmax导出插件

系列文章 一、逆向工程 Sketchup 逆向工程&#xff08;一&#xff09;破解.skp文件数据结构 Sketchup 逆向工程&#xff08;二&#xff09;分析三维模型数据结构 Sketchup 逆向工程&#xff08;三&#xff09;软件逆向工程从何处入手 Sketchup 逆向工程&#xff08;四&#xf…

最新Tomcat下载安装详细教程

Tomcat下载安装教程 Tomcat简介Tomcat下载tomcat安装验证安装是否成功 Tomcat简介 Tomcat是什么&#xff1f; Tomcat是web容器。你在做web项目时&#xff0c;多数需要http协议&#xff0c;也就是基于请求和响应&#xff0c;比如你在百度输入一行内容搜索&#xff0c;那么百度服…

一文讲清数据资产入表实操

《中共中央 国务院关于构建数据基础制度更好发挥数据要素作用的意见》已发布一年&#xff0c;数据资产化和入表已成为2023年的热门话题&#xff0c;随着2023年底国家数据局吹风《"数据要素x"三年行动计划&#xff08;2024-2026年&#xff09;》即将发布&#xff0c;这…

Java_IO流(字节流)

一、IO流&#xff08;字节流&#xff09; 1.1 IO流概述 在前面已经学习过File类。知道File只能操作文件&#xff0c;但是不能操作文件中的内容。我们也学习了字符集&#xff0c;不同的字符集存字符数据的原理是不一样的。有了前面两个知识的基础&#xff0c;接下来我们再学习…

Git(3):Git环境常用命令

1 获取本地仓库 要使用Git对我们的代码进行版本控制&#xff0c;首先需要获得本地仓库 &#xff08;1&#xff09;在电脑的任意位置创建一个空目录&#xff08;例如test&#xff09;作为我们的本地Git仓库 &#xff08;2&#xff09;进入这个目录中&#xff0c;点击右键打开…

NSSCTF sql

开启环境: ?wllm1 回显正常,试试?wllm1 出现报错;加上%23正常 ?wllm-1or 11%23出现过滤 测试,空格用**替代, 等号用like替代 测试长度 ?wlmm1order/**/by/**/3%23正常 ?wlmm1order/**/by/**/4%23报错 长度为3,测试回显位置: ?wlmm-1union/**/select/**/1,2,3%23 …

c++ / day06

1. 利用模板类完成顺序表(两天时间&#xff0c;今天至少写出大致框架) 代码 //implement template in sqlist #include <iostream> #include <cstring>#define MAXSIZE 100using namespace std;template <typename T> class Sqlist {unsigned int len 0;T…

【普中开发板】基于51单片机音乐盒LCD1602显示( proteus仿真+程序+设计报告+讲解视频)

【普中开发板】基于51单片机音乐盒LCD1602显示( proteus仿真程序设计报告讲解视频&#xff09; 仿真图proteus7.8及以上 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;P08 1. 主要功能&#xff1a; 基于51单片机AT89C51/52&#…

环境准备-VMware安装

照顾到很多人不是很会环境搭建,我这里会将搭建的步骤讲的细致点 第一步,VMware下载。目的是通过VMware搭建Linux服务器,因为大家大部分还是Windows的电脑,我们先下载虚拟机搭建一个Linux系统的服务器 下载完成之后,点击安装,如下: 点击“下一步” 勾选“我接受许可协议…

app store里面的构建版本在线上传

开发苹果ios应用&#xff0c;无论是用原生开发、用hbuilderx开发还是用其他h5框架开发的app&#xff0c;都需要将打包好的ipa文件上传到app store。 在上架app store的过程中&#xff0c;我们会遇到下图的这样一个问题&#xff1a; 就是它要求我们上传一个构建版本&#xff0c…

IDEA断点调试

IDEA断点调试 断点调试是一种在程序执行过程中暂停执行并逐步检查代码状态的方法。它允许开发者在程序运行到特定位置时暂停执行&#xff0c;查看变量的值、执行过程和调用栈等信息&#xff0c;从而更好地理解代码的运行情况和解决问题。可以帮助我们查看java底层源代码的执行…

分布微服软件体系快速云端架构

1 概述 分布微服软件体系云端架构平台&#xff0c;以主流的NACOS服务器作为注册配置中心&#xff0c;采用主流的Gradle框架&#xff0c;内嵌Tomcat10以上版本&#xff0c;用于快速构造各类基于JDK17以上的信息应用系统的分布式微服务软件体系架构&#xff0c;可以适用关系型SQ…

图像识别原理

图像识别是计算机视觉领域中的一个重要任务&#xff0c;其目标是使计算机系统能够理解和解释图像中的信息。以下是图像识别的基本原理&#xff1a; 1. 数据采集&#xff1a;首先&#xff0c;需要获取图像数据。这可以通过摄像头、传感器、扫描仪等设备来实现。图像可以是静态的…

在Linux中以后台静默运行Java应用程序

在Linux系统上运行Java应用程序时&#xff0c;有时我们希望将其设置为后台运行&#xff0c;而关闭终端窗口时不会影响进程的执行。在本文中&#xff0c;我们将介绍几种实现这一目标的方法。 1. 使用nohup命令 nohup是一个用于在后台运行进程的命令&#xff0c;而且关闭终端窗…

8868体育助力赫塔菲 格林伍德渐入佳境

西甲赫塔菲俱乐部是8868体育合作球队之一。近日&#xff0c;赫塔费在西甲联赛3-3战平马竞&#xff0c;赛后赫塔费主帅博达拉斯称赞了格林伍德。格林伍德在本场比赛中虽然没有收获进球或助攻&#xff0c;但他表现出色&#xff0c;赛后获得8分评价。 在比赛中&#xff0c;格林伍德…

依赖注入实现原理

依赖注入实现原理 一、Autowire 流程图&#xff1a; Autowire的后置处理器类是AutowiredAnnotationBeanPostProcessor&#xff0c;在启动时会执行这里面的方法 步骤一&#xff1a;寻找注入点 在创建一个Bean的过程中&#xff0c;Spring会利用AutowiredAnnotationBeanPostPro…