移动端开发进阶之蓝牙通讯(二)

移动端开发进阶之蓝牙通讯(二)

蓝牙广播是一种无线通讯技术,通过无线电波传输数据;
在蓝牙低功耗(BLE)协议中,广播通信是其重要组成部分,主要有两类使用场景:
单一方向的、无连接的数据通信,数据发送者在广播信道上广播数据,数据接收者扫描、接收数据;
连接的建立;
此外,每个设备在使用时,同一时刻,只会在一个信道进行工作,不会占用其他信道,这样可以有效地避免干扰,即使一个信道存在干扰,另外的信道也可以很好地工作;
在广播间隔上,设备每次广播时,会在3个广播信道发送相同的报文,这种设置能有效地避免干扰,因为即使一个信道存在干扰,另外的信道也可以很好地工作。
蓝牙通讯

一、广播参数

蓝牙广播的系统参数主要包括广播间隔和广播延时;
广播间隔是一个关键参数,其单位是毫秒,范围通常在20ms至10.24s之间,必须是0.625ms的整数倍;
根据不同的Advertising_Type,最小值可能会有所不同,例如,当Advertising_Type为0x02或0x03时,最小值为100ms。
另外,广播延时是在广播事件期间,链路层产生的一个0ms至10ms之间的伪随机时间量,这个延时被添加到两个广播事件之间,目的是为了防止多个设备间的干扰。

二、广播信道

任何带有信息的信号传递都要占用一定的带宽,不可能是一个单一的频率;
以BLE为例,BLE在2.4GHz频段安排了40个信道(channel),中心频率从2402MHz开始,以2MHz为间隔;
一个BLE设备在任一时刻只能选择40个信道之中一个进行发射或监听;
接收方需要在同一信道上监听才可能收到数据包,接收方还需要知道数据包长度才能进行CRC校验,包长度是包含在PDU段内;
BLE4.0和4.2时,信道37、38和39用于advertising;每次广播,会在3个广播信道上发送相同的报文;
广播信道的选择主要考虑了避免与WiFi等其他无线通信系统的干扰,通过将广播信道设置在非标准WiFi信道,可以降低广播通信受到的干扰,提高通信的可靠性和稳定性。

三、广播结构

蓝牙广播的最大长度是37个字节,其中设备地址占用了6个字节,只有31个字节是可用的,这意味着广播数据最大长度为31字节,包括广播内容类型和广播数据;
在有效广播数据长度方面,由于广播数据包的结构和组成较为复杂,实际上可用的有效广播数据长度可能会受到限制,具体有效长度取决于广播内容类型和广播数据的内容,不同的类型和内容对应不同的长度;
一般情况下蓝牙广播数据由以下部分组成:

  1. Preamble:这是一个长度为1字节的标识符,用于表示广播数据包的开始。
  2. Access Address:这是一个长度为4字节的地址,用于标识广播设备。
  3. PDU Header:这是一个长度为2字节的头部信息,包含广播数据包的长度和类型等信息。
  4. Payload Data:这是实际传输的数据,长度和内容根据具体应用而定。
  5. CRC:这是一个长度为3字节的校验码,用于检测数据传输的错误。

其中,PDU(Protocol Data Unit)是协议数据单元,用于传输数据;
PDU Header是PDU的头部信息,包含了PDU的一些基本信息,例如长度和类型等;
Payload Data是实际传输的数据内容,可以是设备名称、Mac地址、服务UUID等信息;
CRC是校验码,用于检测数据传输过程中是否出现了错误;
根据不同的需求配置,广播实际传输的数据也会有相应的不同。

#include <iostream>  
#include <bluetooth/bluetooth.h>  
#include <bluetooth/rfcomm.h>  
#include <bluetooth/sdp.h>  
  
int main() {  
    // 初始化Bluez库  
    int status = bluetooth_init(&bt_context, NULL);  
    if (status != 0) {  
        std::cerr << "Failed to initialize Bluez library." << std::endl;  
        return 1;  
    }  
  
    // 打开默认的RFCOMM通道(1)  
    int channel = 1;  
    int fd = bt_open_channel(channel);  
    if (fd < 0) {  
        std::cerr << "Failed to open RFCOMM channel." << std::endl;  
        return 1;  
    }  
  
    // 开始扫描附近的蓝牙设备  
    const int type = BLUETOOTH_DISCOV_ANY; // 扫描所有类型的设备  
    const int filter = 0; // 不使用过滤器  
    int err = bt_discovery(type, filter, NULL, NULL);  
    if (err != 0) {  
        std::cerr << "Failed to start device discovery." << std::endl;  
        return 1;  
    }  
  
    // 等待设备广播事件  
    struct sockaddr_rc addr = {0};  
    socklen_t len = sizeof(addr);  
    int events = POLLIN; // 等待数据可读的事件  
    int e = poll(&bt_event, 1, -1, &events); // -1 表示无限等待  
    if (e == -1) {  
        std::cerr << "Failed to wait for device discovery event." << std::endl;  
        return 1;  
    }  
  
    // 处理发现的设备广播事件  
    if (bt_event.revents & POLLIN) { // 数据可读事件发生时处理广播数据包  
        char buffer[256]; // 用于存储接收到的广播数据包  
        int bytes_read = recvfrom(bt_event.fd, buffer, sizeof(buffer), 0, (struct sockaddr*)&addr, &len); // 接收广播数据包  
        if (bytes_read > 0) { // 处理接收到的数据包  
            std::cout << "Received device broadcast." << std::endl;  
            // 在这里处理广播数据包,例如解析服务UUID等。你可以根据需要添加代码来识别特定的设备和服务。  
            // ...  
            // 应答广播并尝试建立连接的代码也放在这里。具体的实现取决于你希望如何应答和建立连接。你可能需要发送特定的命令或数据来响应设备,然后等待设备的响应以建立连接。这部分代码需要根据具体的设备和协议进行实现。  
        } else { // 处理接收错误的情况  
            std::cerr << "Failed to receive device broadcast." << std::endl;  
        }  
    } else if (bt_event.revents & POLLHUP) { // 处理连接断开事件(如果适用)  
        std::cerr << "RFCOMM channel disconnected." << std::endl;  
    } else if (bt_event.revents & POLLERR) { // 处理其他错误事件(如果适用)  
        std::cerr << "Error on RFCOMM channel." << std::endl;  
    } else { // 处理其他未知事件(如果适用)  
        std::cerr << "Unknown event on RFCOMM channel." << std::endl;  
    }  
  
    // 清理并关闭资源  
    close(bt_event.fd); // 关闭RFCOMM通道的文件描述符  
    bluetooth_cleanup(&bt_context); // 清理Bluez库资源  
    return 0; // 表示成功执行完毕或出现错误导致程序退出,具体取决于前面的错误处理逻辑。你可以根据需要添加更多的错误处理和资源清理逻辑。  
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT-day6

作业1&#xff1a;数据库增删查改 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);if (!db.contains("stu.db")){db QSqlDatabase::addDatabase(&q…

2024年腾讯云服务器多少钱1个月?

2024年腾讯云服务器多少钱1个月&#xff1f;5元一个月&#xff0c;62元一年&#xff0c;更多腾讯云服务器精准报价。腾讯云服务器租用优惠价格表&#xff1a;轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;…

Uibot (RPA设计软件)Mage AI智能识别(发票识别)———课前材料五

微信群发助手机器人的小项目友友们可以参考小北的课前材料二博客~ (本博客中会有部分课程ppt截屏,如有侵权请及请及时与小北我取得联系~&#xff09; 紧接着小北的前两篇博客&#xff0c;友友们我们即将开展新课的学习~RPA 培训前期准备指南——安装Uibot(RPA设计软件&#x…

搜维尔科技:【简报】元宇宙数字人赛道,《寒朵鹿》赏析!

寒朵鹿的外观是柔和无攻击性的小鹿拟人样&#xff0c;头上长有一对鹿角及鹿耳&#xff0c;虽然绝大部分雌鹿并不会长角&#xff0c;但由于寒朵鹿是AI的智能机器人&#xff0c;所以为了依照普遍大众对鹿的印象依旧帮她加上了角。 学校&#xff1a; 台北商业大学 选手&#xff1…

【翻译】在Qt Designer中创建主窗口(Main Windows)

原文地址&#xff1a;https://doc.qt.io/qt-6/designer-creating-mainwindows.html Qt Designer 可用于为不同用途创建用户界面&#xff0c;并为每个用户界面提供不同类型的模板。主窗口模板用于创建具有菜单栏、工具栏和停靠窗口部件的应用程序窗口。 通过打开文件菜单并选择…

vue3项目部署到服务器,刚打开没事,一刷新页面就404

vue3项目部署到服务器&#xff0c;刚打开没事&#xff0c;一刷新页面就404 vue3项目&#xff0c;在本地调试时各方面都没毛病&#xff0c;刷新也没毛病&#xff0c;但是&#xff0c;扔到服务器上&#xff0c;第一次打开是正常的&#xff0c;再刷新下就404了&#xff0c;不知道什…

java+vue基于Spring Boot的渔船出海及海货统计系统

该渔船出海及海货统计系统采用B/S架构、前后端分离进行设计&#xff0c;并采用java语言以及springboot框架进行开发。该系统主要设计并完成了管理过程中的用户注册登录、个人信息修改、用户信息、渔船信息、渔船航班、海货价格、渔船海货、非法举报、渔船黑名单等功能。该系统操…

含PEMFC的热电联供系统能量管理策略Simulink仿真

1.光伏发电系统 在直流微电网中&#xff0c;光伏电池系统经过升压DC/DC变换器接入直流微电网提供功率。在不同的系统运行条件下&#xff0c;光伏电池系统有三种工作模式&#xff1a;MPPT 模式、下垂模式和空闲模式。由于光伏阵列的输出特性随着环境条件影响&#xff0c;光伏电池…

docker-compose安装HertzBeat赫兹跳动监控H3C交换机

前面我们用docker方式安装了HertzBeat&#xff0c;现在我们自己写个docker-compose.yml文件、创建文件直接docker-compose up -d直接启动运行 使用docker-compose需要先安装docker和docker-compose1、输入以下两段命令 mkdir 123 && cd 123 && mkdir data &a…

Spring Cloud + Vue前后端分离-第12章 通用权限设计

源代码在GitHub - 629y/course: Spring Cloud Vue前后端分离-在线课程 Spring Cloud Vue前后端分离-第12章 通用权限设计 这一章我们不依赖第三方框架&#xff0c;我会从权限相关表的设计&#xff0c;到权限的配置&#xff0c;到权限的拦截&#xff0c;带大家一步一步的做出…

领域驱动设计——DDD领域驱动设计进阶

摘要 进阶篇主要讲解领域事件、DDD 分层架构、几种常见的微服务架构模型以及中台设计思想等内容。如何通过领域事件实现微服务解耦&#xff1f;、怎样进行微服务分层设计&#xff1f;、如何实现层与层之间的服务协作&#xff1f;、通过几种微服务架构模型的对比分析&#xff0…

【LeetCode】206. 反转链表(简单)——代码随想录算法训练营Day03

题目链接&#xff1a;206. 反转链表 题目描述 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输…

多目标优化(Python):多目标粒子群优化算法(MOPSO)求解ZDT1、ZDT2、ZDT3、ZDT4、ZDT6(提供Python代码)

一、多目标粒子群优化算法 多目标粒子群优化算法&#xff08;MOPSO&#xff09;是一种用于解决多目标优化问题的进化算法。它基于粒子群优化算法&#xff08;PSO&#xff09;&#xff0c;通过引入多个目标函数和非支配排序来处理多目标问题。 MOPSO的基本思想是将问题转化为在…

【Docker】Docker容器实战部署多个Nginx实现负载均衡和高可用

文章目录 前言下载Nginx复制出配置文件第一步&#xff1a;启动容器 修改配置nginx-lb里的nginx.conf 启动容器启动nginx1启动nginx2启动nginx-lb 演示效果 前言 Docker下部署多个Nginx进行负载均衡&#xff0c;我这次实操的思路是使用三个Nginx。其中一个Nginx起负载均衡的作用…

SQL-用户管理与用户权限

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…

运筹说 第80期 | 最小费用最大流问题

前面我们学习了图与网络分析的基础知识及经典问题&#xff0c;大家是否已经学会了呢&#xff1f;接下来小编和大家学习最后一个经典问题——最小费用最大流问题。 最小费用最大流问题是经济学和管理学中的一类典型问题。在一个网络中每段路径都有“容量”和“费用”两个限制的…

上门按摩小程序开发-类似东郊到家系统搭建-足浴养生按摩小程序定制开发完整流程+成功案例

随着现代生活节奏的加快&#xff0c;人们的生活压力越来越大&#xff0c;亚健康问题也日益突出。为了满足人们对于健康和放松的需求&#xff0c;上门按摩小程序应运而生。这种小程序通过提供预约按摩服务&#xff0c;让用户在家就能享受到专业的按摩护理&#xff0c;缓解疲劳&a…

PHP项目如何自动化测试

开发和测试 测试和开发具有同等重要的作用 从一开始&#xff0c;测试和开发就是相向而行的。测试是开发团队的一支独立的、重要的支柱力量。 测试要具备独立性 独立分析业务需求&#xff0c;独立配置测试环境&#xff0c;独立编写测试脚本&#xff0c;独立开发测试工具。没有…

高效视频剪辑:视频合并让视频焕然一新,添加背景音乐更动听

随着社交媒体和数字内容的普及&#xff0c;视频剪辑已成为一项常用的技能。除了基本的剪辑技巧外&#xff0c;添加合适的背景音乐也是提升视频质量的方法。下面来看云炫AI智剪的高效视频剪辑技巧——如何批量合并视频&#xff0c;添加动听的背景音乐。 视频合并后的效果展示&a…

JSP-概念

一、引子 很多读者可能听过JSP&#xff0c;并且知道这是一门过时的技术了。在Spring&#xff0c;SpringBoot已经成为主流的今天&#xff0c;笔者为什么还要介绍JSP的相关内容呢&#xff1f;笔者常常提到一个概念&#xff1a;理解一门技术&#xff0c;要理解这个技术为什么产生…