Zephyr NRF7002 实现AppleJuice

news2024/11/19 3:42:09

BLE的基础知识

在这里插入图片描述

ble的信道和BR/EDR的信道是完全不一样的。但是范围是相同的,差不多也都是2.4Ghz的频道。可以简单理解为空中有40个信道0~39信道。两个设备在相同的信道里面可以进行相互通信。

而这些信道SIG又重新编号:

../../_images/adv_channel2.png

这个编号就是把37 38 39。 3个信道抽出来,作为广播信道,其他都是数据信道。这篇文章主要讲广播,所以基本数据信息都是围绕37 38 39这三个信道上面的通信来讲的。

我们可以看到这3个信道是分散排列的。大家可以思考下为什么。

其实看下面一张图就知道了。

../../_images/wifi_channel.png

数据广播

广播组成部分

广播分为如下几个部分:

  • 广播
  • 扫描请求
  • 扫描响应

在这里插入图片描述

广播的报文格式

在这里插入图片描述

{
    "AD1":{
        "Length":12,
        "Data":{
            "AD_Type":12,
            "AD_Data":"123123"
        }
    },
    "AD2":{
        "Length":12,
        "Data":{
            "AD_Type":12,
            "AD_Data":"123123"
        }
    }
}

记忆要点

每个元素里面有两个要素:1. 长度(length), 2. 数据(data)

  • 每个数据里面又包含两个元素:1. 类型(type), 2. 数据(data)

  • 总结一下就是一个L T V模型(length, type, data)

  • 这个length代表的是后面数据有多长,不包含length的长度。

  • 总的Len一般不超过31字节

参考:

2. BLE 广播和扫描 — bluetoothlover_wiki 0.0.1 文档 (supperthomas-wiki.readthedocs.io)

AD_Type 官方定义

抓包参考:

在这里插入图片描述

APPLE JUICE功能实现

在这里插入图片描述

1.流程梳理

主要需要实现如下功能点:

  • ble 广播开启和关闭
  • ble GAP层各种参数的设置
  • ble MAC地址动态修改

2.Zephyr 中相关接口:

功能接口:

接口名功能描述备注
bt_enable开启BLE功能
bt_le_adv_start开启BLE广播
bt_le_adv_update_data更新BLE广播内容此接口是否实时?未找到对应生效CallBack
bt_le_adv_stop关闭BLE广播
bt_id_create更新广播随机地址

注:

上述接口在执行完成后均会抛出回调:

/*
参数回调注册
*/
void bt_conn_cb_register(struct bt_conn_cb *cb);

struct bt_conn_cb {
    //已建立新连接
	void (*connected)(struct bt_conn *conn, uint8_t err);
	//连接已断开
	void (*disconnected)(struct bt_conn *conn, uint8_t reason);
    //LE 连接参数更新请求
	bool (*le_param_req)(struct bt_conn *conn,
			     struct bt_le_conn_param *param);
	//LE 连接的参数已更新
	void (*le_param_updated)(struct bt_conn *conn, uint16_t interval,
				 uint16_t latency, uint16_t timeout);
#if defined(CONFIG_BT_SMP)
	//远程身份地址通过
	void (*identity_resolved)(struct bt_conn *conn,
				  const bt_addr_le_t *rpa,
				  const bt_addr_le_t *identity);
#endif /* CONFIG_BT_SMP */
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
	//连接的安全级别已更改
	void (*security_changed)(struct bt_conn *conn, bt_security_t level,
				 enum bt_security_err err);
#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */

#if defined(CONFIG_BT_REMOTE_INFO)
	//远程信息程序已完成
	void (*remote_info_available)(struct bt_conn *conn,
				      struct bt_conn_remote_info *remote_info);
#endif /* defined(CONFIG_BT_REMOTE_INFO) */

#if defined(CONFIG_BT_USER_PHY_UPDATE)
	//连接的 PHY 已更改
	void (*le_phy_updated)(struct bt_conn *conn,
			       struct bt_conn_le_phy_info *param);
#endif /* defined(CONFIG_BT_USER_PHY_UPDATE) */

#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
	//连接的数据长度参数已更改
	void (*le_data_len_updated)(struct bt_conn *conn,
				    struct bt_conn_le_data_len_info *info);
#endif /* defined(CONFIG_BT_USER_DATA_LEN_UPDATE) */

#if defined(CONFIG_BT_DF_CONNECTION_CTE_RX)
	void (*cte_report_cb)(struct bt_conn *conn,
			      const struct bt_df_conn_iq_samples_report *iq_report);
#endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */

#if defined(CONFIG_BT_TRANSMIT_POWER_CONTROL)
	void (*tx_power_report)(struct bt_conn *conn,
				const struct bt_conn_le_tx_power_report *report);
#endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */
	struct bt_conn_cb *_next;
};

bt_data接口

Zephyr 封装好了部分gap填充接口,在编写广播数据(bt_data)数组的时候可以通过以下宏来辅助:


/**
 * @brief Construct a new bt data object
 * 
 * 	_type: GAP字段的类型
 * 	_data: GAP RAW 数据
 * 	_data_len: RAW数据长度
 */
#define BT_DATA(_type, _data, _data_len) \
	{ \
		.type = (_type), \
		.data_len = (_data_len), \
		.data = (const uint8_t *)(_data), \
	}
    
/**
 * @brief Construct a new bt data object
 * 
 * 	_type: GAP字段的类型
 * 	_bytes: GAP RAW 数据
 */    
#define BT_DATA_BYTES(_type, _bytes...) \
	BT_DATA(_type, ((uint8_t []) { _bytes }), \
		sizeof((uint8_t []) { _bytes }))

参考:

5. BLE — BL_MCU_SDK 开发指南 0.3 文档 (gitee.io)

Zephyr API文档:通用访问配置文件(GAP) (zephyrproject.org)

3. 广播数据填充

AD_Data字段:

static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA,
				  0x4c, 0x00, 0x07, 0x19, 0x07, 0x0a, 0x20,
				  0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45,
				  0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00,
				  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				  0x00)};

开启广播的时候将ad传入,即可完成广播数据设置。

4.随机地址切换

Apple对于相同MAC地址的设备仅会进行一次弹窗,因此如果想要让手机不断的弹出设备提示框就需要定期修改BLE的MAC地址,代码如下:

bt_addr_le_t local_mac_addr;
		size_t localmac_size = 1;
		static bt_addr_le_t myaddr = {
			.type = BT_ADDR_LE_RANDOM,
			/* fixed MAC addres */
			.a = {
				.val = {0x01, 0x02, 0x03, 0x04, 0x05, 0xc6},
			},
		};
		printk("bt_id_create\r\n");
		err = bt_id_create(&myaddr, NULL);
		if (err < 0)
		{
			printk("bt_id_create err!\r\n");
		}

小思考:这里思考了下苹果的设计美学,以AirPods为例。通常情况下设备为了节约电池电量并不会一直进行BLE广播,而是在每次打开电池仓时才唤醒ble芯片,关闭电池仓之后进入超低功耗模式。BLE设备的程序在每次唤醒的时候程序会从新启动,所以MAC地址发生改变。

效果演示

在这里插入图片描述

问题和解决方法

  • 问题描述:使用7002DK开发板运行时出现如下问题。
    在这里插入图片描述

  • 原因分析:默认情况下adv字段允许的最大长度为31字节, 当数据填充超出会出现上述报警。

  • 解决方法:可以开启ble的拓展广播功能来增加最大数据长度。相关配置可以参考Demo periodic_adv,相关Menuconfig修改点如下图所示:

在这里插入图片描述
在这里插入图片描述

完整代码:

/**
 * @file main.c
 * @author Argon
 * @brief  BLE Apple 
 * @version 0.1
 * @date 2024-01-20
 * 
 * @copyright Copyright (c) 2024
 * 
 */
#include <zephyr/types.h>
#include <stddef.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>


//扫描数据段
static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA,
				  0x4c, 0x00, 0x07, 0x19, 0x07, 0x0a, 0x20,
				  0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45,
				  0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00,
				  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				  0x00)};

//扫描响应数据段
static const struct bt_data sd[] = {
	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
	BT_DATA_BYTES(BT_DATA_PERIPHERAL_INT_RANGE, 0x20, 0x00, 0x40, 0x00),
	BT_DATA_BYTES(BT_DATA_TX_POWER, 0x09),
};

//设备名
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)


int main(void)
{
	int err;

	printk("BLE Starting\n");

	/* Initialize the Bluetooth Subsystem */
	err = bt_enable(NULL);
	if (err)
	{
		printk("Ble init failed (err %d)\n", err);
		return 0;
	}

	printk("Ble initialized\n");

	do
	{
		//开启广播
		printk("Ble adv start\r\n");
		err = bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad),
							  sd, ARRAY_SIZE(sd));
		if (err)
		{
			printk("Advertising failed to start (err %d)\n", err);
			return 0;
		}
		k_sleep(K_SECONDS(4));

		//广播广播
		printk("Ble adv stop\r\n");
		err = bt_le_adv_stop();
		if (err)
		{
			printk("Advertising failed to stop (err %d)\n", err);
			return 0;
		}

		//更新MAC
		bt_addr_le_t local_mac_addr;
		static bt_addr_le_t myaddr = {
			.type = BT_ADDR_LE_RANDOM,
			/* fixed MAC addres */
			.a = {
				.val = {0x01, 0x02, 0x03, 0x04, 0x05, 0xc6},
			},
		};

		printk("Ble update MAC address\r\n");
		err = bt_id_create(&myaddr, NULL);
		if (err < 0)
		{
			printk("bt_id_create err!\r\n");
		}
		k_sleep(K_SECONDS(4));
	} while (1);
	return 0;
}

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

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

相关文章

idea(2023.3.3 ) spring boot热部署,修改热部署延迟时间

1、添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional> </dependency>载入依赖 2、设置编辑器 设置两个选项 设置热部署更新延迟时…

seatunnel数据集成(一)简介与安装

seatunnel数据集成&#xff08;一&#xff09;简介与安装seatunnel数据集成&#xff08;二&#xff09;数据同步seatunnel数据集成&#xff08;三&#xff09;多表同步seatunnel数据集成&#xff08;四&#xff09;连接器使用 1、背景 About Seatunnel | Apache SeaTunnel …

构建高效直播美颜系统:美颜SDK集成与性能优化指南

如今&#xff0c;美颜技术的广泛应用成为各类直播平台的标配之一。今天&#xff0c;小编将与大家进一步讨论如何构建高效的直播美颜系统&#xff0c;重点关注美颜SDK的集成和性能优化方面。 一、美颜SDK的选择与集成 选择合适的美颜SDK是构建高效直播美颜系统的第一步。不同的…

Go语言每日一练 ——链表篇(三)

传送门 牛客面试笔试必刷101题 ---------------- 链表中的节点每k个一组翻转 题目以及解析 题目 解题代码及解析 package main import _"fmt" import . "nc_tools" /** type ListNode struct{* Val int* Next *ListNode* }*//*** 代码中的类名、方…

MongoDB从入门到实战之Docker快速安装MongoDB

前言 在上一篇文章中带领带同学们快速入门MongoDB这个文档型的NoSQL数据库&#xff0c;让大家快速的了解了MongoDB的基本概念。这一章开始我们就开始实战篇教程&#xff0c;为了快速把MongoDB使用起来我将会把MongoDB在Docker容器中安装起来作为开发环境使用。然后我这边MongoD…

MySQL学习一、库和表的基础操作

目录 一、常用数据类型 1.数值类型 2.字符串类型 3.日期类型 ​二、数据库的基础操作 三、表的基础操作 一、常用数据类型 1.数值类型 数值类型可以指定为无符号&#xff08;unsigned &#xff09;&#xff0c;但不建议取 2.字符串类型 3.日期类型 二、数据库的基础操作…

牛客“迎新春,过大年”多校程序设计竞赛A题

题目描述&#xff1a; 这里有个小trick 当时也看到数据范围的问题了 n 是 1 e 6 ∑ i 1 n a [ i ] < 5 e 7 n是1e6 \quad \sum_{i1}^na[i]<5e7 n是1e6∑i1n​a[i]<5e7 我们考虑不同的数 1 2 . . . k − 1 k 1 \quad 2 \quad ... k-1 \quad k 12...k−1k s u m …

如何在Windows系统上部署docker

上次在Windows系统上部署成功Ubuntu系统&#xff0c;这次准备在Windows上部署docker desktop应用 这个应用软件类似于虚拟机&#xff0c;可以在该应用软件上部署多个镜像容器。其最直观的表现就是可以借用Windows和Ubuntu终端来访问docker“模拟的系统”。 Docker简介 Docke…

(已解决)vue+element-ui实现个人中心,仿照原神

差一个个人中心页面&#xff0c;看到了这个博主的个人中心&#xff0c;真的很不错 地址&#xff1a;vueelement仿原神实现好看的个人中心 最终效果&#xff1a;

【论文研读】Better Together:Unifying Datalog and Equality Saturation

最近研究ReassociatePass整的头大&#xff0c;翻两篇Datalog的论文看看。 今天看的一篇是比较新的文章&#xff0c;23年4月贴到arxiv上的。 本文的主要贡献是提出了egglog,将Datalog和Eqsat结合起来&#xff0c;继承了Datalog的efficient incremental execution, cooperating a…

CISCRISC? CPU架构有哪些? x86 ARM?

编者按&#xff1a;鉴于笔者水平有限&#xff0c;文中难免有不当之处&#xff0c;还请各位读者海涵。 是为序 我猜&#xff0c;常年混迹CSDN的同学应该不会没听说过CPU吧&#xff1f; 但你真的了解CPU吗&#xff1f;那笔者问你CPU有哪些架构呢&#xff1f; 如果你对你的答案…

MC34063异常发热分析

问题描述&#xff1a; 工程现场反馈若干电源转换模块损坏&#xff0c;没有输出。拿到问题模块后&#xff0c;查看有一个MC34063周围的PCB有比较明显的高温痕迹&#xff0c;配套的电感也有明显的高温过热痕迹。 问题调查&#xff1a; MC34063的电路非常经典&#xff08;虽然自…

npm 上传一个自己的应用(3) 在项目中导入及使用自己上传到NPM的工具

上文 npm 上传一个自己的应用(2) 创建一个JavaScript函数 并发布到NPM 我们创建了一个函数 并发上了npm 最后 我们这里 我们可以看到它的安装指令 这里 我们可以打开一个vue项目 终端输入 我们的安装指令 npm i 自己的包 如下代码 npm i grtest我们在 node_modules目录 下…

《爬虫职海录》卷二 • 爬在广州

HI&#xff0c;朋友们好&#xff0c;「爬虫职海录」第二期更新啦&#xff01; 本栏目的内容方向会以爬虫相关的“岗位分析”和“职场访谈”为主&#xff0c;方便大家了解一下当下的市场行情。 本栏目持续更新&#xff0c;暂定收集国内主要城市的爬虫岗位相关招聘信息&#xf…

BUUCTF-Real-[ThinkPHP]IN SQL INJECTION

目录 漏洞描述 漏洞分析 漏洞复现 漏洞描述 漏洞发现时间&#xff1a; 2018-09-04 CVE 参考&#xff1a;CVE-2018-16385 最高严重级别&#xff1a;低风险 受影响的系统&#xff1a;ThinkPHP < 5.1.23 漏洞描述&#xff1a; ThinkPHP是一款快速、兼容、简单的轻量级国产P…

React 实现表单组件

表单是html的基础元素&#xff0c;接下来我会用React实现一个表单组件。支持包括输入状态管理&#xff0c;表单验证&#xff0c;错误信息展示&#xff0c;表单提交&#xff0c;动态表单元素等功能。 数据状态 表单元素的输入状态管理&#xff0c;可以基于react state 实现。 …

ubuntu22.04@laptop OpenCV Get Started: 000_hello_opencv

ubuntu22.04laptop OpenCV Get Started: 000_hello_opencv 1. 源由2. Hello OpenCV2.1 C应用Demo2.2 Python应用Demo 3. 参考资料 1. 源由 之前&#xff0c;通过敲门砖已经砸开了OpenCV的大门&#xff0c;接下来是体验下“Hello World&#xff01;”程序。 2. Hello OpenCV …

LeetCode:13.罗马数字转整数

13. 罗马数字转整数 - 力扣&#xff08;LeetCode&#xff09; 目录 思路&#xff1a; 官解代码&#xff1a; 作者辣眼代码: 每日表情包&#xff1a; 思路&#xff1a; 思路已经很明了了&#xff0c;题目已经给出一般规则和特殊规则&#xff08;而且题目确保给定的是正确的…

Node.js JSON Schema Ajv依赖库逐步介绍验证类型和中文错误提示

在构建应用程序时&#xff0c;数据的有效性是至关重要的。为了确保传入的数据符合预期的格式和规范&#xff0c;我们可以使用 Ajv&#xff08;Another JSON Schema Validator&#xff09;进行验证。在这篇博文中&#xff0c;我们将从头开始学习 Ajv&#xff0c;逐步介绍验证类型…

使用webstorm调试vue 2 项目

学习目标&#xff1a; 使用webstorm调试vue 2 项目 笔者环境&#xff1a; npm 6.14.12 webstorm 2023.1 vue 2 学习内容&#xff1a; 例如&#xff1a; 正常启动npm 项目 配置javaScruot dubug 配置你的项目地址就好 使用dubug运行你配置的调式页 问题 如果进入了js页无…