搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
小丑西瓜9
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
【微信小程序】canvas开发笔记_微信小程序 canvastotempfilepath不成功
2
Ardupilot代码学习笔记
3
详解二分查找算法_二分搜索技术算法分析
4
数据集XML标签转YOLO标签_xml转yolo
5
《爆肝整理》保姆级系列教程-玩转Charles抓包神器教程(6)-Charles安卓手机抓包大揭秘_charles抓取手机端的包
6
判断OBject对象为空(包括null ,““)的方法_判断object为空
7
【面经】米哈游数据开发一面面经
8
git 克隆到指定分支_git clone 指定branch
9
1129_Windows Server 2016系统的Docker容器初体验_为什么我c:\users\admini~1\appdata\local\temp\dockermsf
10
C#数据之DataTable
当前位置:
article
> 正文
基于BlueZ的C语言蓝牙编程_c语言实现ble蓝牙通信
作者:小丑西瓜9 | 2024-04-25 06:30:31
赞
踩
c语言实现ble蓝牙通信
基于BlueZ的C语言蓝牙编程
原文出处:
[url=http://people.csail.mit.edu/albert/bluez-intro/c401.html][color=#0000ff]http://people.csail.mit.edu/albert/bluez-intro/c401.html[/color][/url]
第四章 基于BlueZ的C语言蓝牙编程
有很多理由促使我们选用C替代其他高级语言来例如Python来开发蓝牙应用程序。Python环境可能并不适合于嵌入式系统。因为嵌入式系统对程序的大 小,运行速度,和占用的存储空间有严格的限制,这些都使得像Python之类的解释性语言无法在嵌入式系统上应用。程序员需要对本地的蓝牙适配器进行更好 的控制,或者需要建立一套动态链接库以便于其他应用程序的链接以取代单一的应用程序。就像上述描述的这些,BlueZ是一款强大的蓝牙通信协议栈,它扩展 的API使得用户方便操纵大量的蓝牙资源。但是BlueZ没有官方的描述文档,甚至非官方的文档也寥寥无几。初学者在BlueZ的官方邮件列表上请求相关 的文档,通常的得到的回复是被告知请通过仔细阅读源代码来了解API的功能。阅读BlueZ的源代码对于初学者来说是一项相当费时的
[url=javascript:;][u][b][color=#0000ff]工作[/color][/b][/u][/url]
,在短期内取得的进展是相当有限的,很可能成为很多蓝牙编程初学者的拦路虎。
本章简要叙述了基于BlueZ的C语言蓝牙编程的方法。本章为C程序员进一步阐述了第二章中涉及的知识点。
4.1 选择一个通信的对象
Example 4-1是一个查找周边蓝牙设备的简单应用程序。程序首先获取系统的蓝牙设备号,扫描周边的蓝牙设备,然后查找每一个被搜索到的蓝牙设备的名称。后边有对数据结构和函数的详细描述。
Example 4-1. simplescan.c
#include stdio.h>
#include stdlib.h>
#include unistd.h>
#include sys/socket.h>
#include bluetooth/bluetooth.h>
#include bluetooth/hci.h>
#include bluetooth/hci_lib.h>
int main(int argc, char **argv)
{
inquiry_info *ii = NULL;
int max_rsp, num_rsp;
int dev_id, sock, len, flags;
int i;
char addr[19] = { 0 };
char name[248] = { 0 };
dev_id = hci_get_route(NULL);
sock = hci_open_dev( dev_id );
if (dev_id 0 || sock 0) {
perror("opening socket");
exit(1);
}
len = 8;
max_rsp = 255;
flags = IREQ_CACHE_FLUSH;
ii = (inquiry_info*)malloc(max_rsp * sizeof(inquiry_info));
num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii, flags);
if( num_rsp 0 ) perror("hci_inquiry");
for (i = 0; i num_rsp; i++) {
ba2str(&(ii+i)->bdaddr, addr);
memset(name, 0, sizeof(name));
if (hci_read_remote_name(sock, &(ii+i)->bdaddr, sizeof(name),
name, 0) 0)
strcpy(name, "[unknown]");
printf("%s %s/n", addr, name);
}
free( ii );
close( sock );
return 0;
}
4.1.1 编译
编译需要使用gcc链接libbluetooth这个库。
gcc -o simplescan simplescan.c -lbluetooth
4.1.2. 解释
typedef struct {
uint8_t b[6];
} __attribute__((packed)) bdaddr_t;
蓝牙设备的地址采用结构体bdaddr_t来描述,BlueZ中队蓝牙地址的存储和操纵都使用bdaddr_t结构体,BlueZ提供两个函数来进行字符串到蓝牙地址的转换。
int str2ba( const char *str, bdaddr_t *ba );
int ba2str( const bdaddr_t *ba, char *str );
str2ba把形如XX:XX:XX:XX:XX:XX(XX标识48位蓝牙地址的16进制的一个字节)的字符串转化6字节的bdaddr_t结构, ba2str完成相反的功能。
本地蓝牙适配器被分配一个从0开始的识别号码。程序在分配系统资源时必须指定使用那一个蓝牙适配器,通常的话系统只有一个蓝牙适配器,把参数NULL传给hci_get_route可以获得第一个有效的蓝牙适配器识别号。
int hci_get_route( bdaddr_t *bdaddr );
int hci_open_dev( int dev_id );
[note]将适配器的设备号指定为0是不恰当的,因为它并不总代表第一个可用的蓝牙适配器。例如系统有两个蓝牙适配器,第一个被disable掉了,那么第一个有效的设备号就是2。
如果存在多个蓝牙适配器,选择"01:23:45:67:89:AB"作为蓝牙适配器的地址, 将指示这个地址的指针char *representation传给hci_devid函数,用这个函数替代hci_get_route。
很多蓝牙操作都需要打开一个套接口, hci_open_dev函数可以打开特定资源号的一个套接口,确切的说hci_open_dev打开的套接字建立了一条和本地蓝牙适配器控制器的连接, 而不是和远端蓝牙设备的连接。使用这个套接口发送命令到蓝牙控制器可以实现底层的蓝牙操作,这部分在4.5中有详细的讨论。
选择好本地蓝牙适配器并进行系统资源分配后,程序就可以开始扫描周边的蓝牙设备了,在这个例程中,hci_inquiry函数完成对蓝牙设备的搜寻,并将返回的设备信息数据记录在变量ii中。遇到错误时,它将返回-1并设置errno变量。
int hci_inquiry(int dev_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **ii, long flags);
hci_inquiry 的参数需要使用设备资源号而非套接口,所以我们使用hci_get_route函数的返回值dev_id传递给它。查询时间最长持续1.28 * len秒。max_rsp个设别返回的信息都被存储在变量ii中,这个变量必须有足够的空间来存储max_rsp返回的结果。我们推荐max_rsp取值 255来完成标准10.24秒的查询工作。
如果标志位flag设置为IREQ_CACHE_FLUSH,那么在进行查询操作时会把先前一次查询记录的cache刷新,否则flag设置为0的话,即便先前查询的设备已经不处于有效范围内,先前查询的记录也将被返回。
inquiry_info结构体定义如下
typedef struct {
bdaddr_t bdaddr;
uint8_t pscan_rep_mode;
uint8_t pscan_period_mode;
uint8_t pscan_mode;
uint8_t dev_class[3];
uint16_t clock_offset;
} __attribute__ ((packed)) inquiry_info;
在大多数场合,我们仅用到成员bdaddr,它标识了设备的蓝牙地址。有些场合我们也会用到成员dev_class, 它标识了被检测到的蓝牙设备的一些信息(例如,识别这个设备是打印设备,电话,个人电脑等),详细地对应关系可以参见蓝牙设备分配号[3]。其余的成员在 用于底层通信,一般情况并不常用。感兴趣的读者可以阅读蓝牙内核规范[4]获取更多的信息。一旦周围的蓝牙设备和其蓝牙地址被检测到,程序可以将此设备的 名称提供给用户,hci_read_remote_name函数可以完成这个功能。
int hci_read_remote_name(int sock, const bdaddr_t *ba, int len,
char *name, int timeout)
hci_read_remote_name函数在规定的超时时间内使用套接口通过蓝牙地址ba去获取蓝牙设备的名称,成功返回0,并将获取的蓝牙设备名称存入name中;失败时返回-1并设置相应的errno。
Notes
[1]
[url=http://www.bluez.org/lists.html][color=#0000ff]http://www.bluez.org/lists.html[/color][/url]
[2] for the curious, it makes a call to socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI), followed by a call to bind with the specified resource number.
[3]
[url=https://www.bluetooth.org/foundry/assignnumb/document/baseband][color=#0000ff]https://www.bluetooth.org/foundry/assignnumb/document/baseband[/color][/url]
[4]
[url=http://www.bluetooth.org/spec][color=#0000ff]http://www.bluetooth.org/spec[/color][/url]
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/小丑西瓜9/article/detail/483745
推荐阅读
article
布隆
过滤器
:揭秘
数据结构
的
魔法与应用...
一般判断用户是否在缓存中,如果存在则直接返回结果,不存在则查询数据库,如果来一波冷数据,会导致缓存大量击穿,造成雪崩效应...
赞
踩
article
Hadoop
压缩配置_
hadoop
压缩配置
csdn
...
下载LZO支持包解压maven编译将编译好后的
hadoop
-lzo-0.4.20.jar 放入
hadoop
-2.7.2/...
赞
踩
article
Welcome to
MySQL
Workbench
:
MySQL
导出
数据
_
mysql
导出
语句wo...
MySQL
中你可以使用SELECT…INTO OUTFILE语句来简单的
导出
数据
到文本文件上。另外,如果你需要将
数据
导入...
赞
踩
article
Oracle
VM
VirtualBox
报错的一种可能情况及处理办法。_the
virtual
m...
Oracle
VM
VirtualBox
报错的一种可能情况及处理办法。//刚开始学习嵌入式Linux,兴致勃勃的下载了...
赞
踩
article
高管级
运营
总监
求职
简历
范本...
一份高质量的求职
简历
,是
运营
总监
展示自己丰富经验、专业能力和领导魅力的关键,以下是小编精心整理的
运营
总监
简历
案例,同时,...
赞
踩
article
SpringBoot3
整合SpringSecurity_
springboot3
整合springse...
SpringBoot3
整合SpringSecurity_
springboot3
整合
springsecurity
spri...
赞
踩
article
flink
集成
hive
中遇到
的
问题以及
解决方案
_
flink
连接
hive
依赖
冲突
怎么办
...
版本:1)hadoop:2.7.22)
hive
:2.3.43)
flink
:1.11.24)os:centos 7.51....
赞
踩
article
git
pull
时 配置适合自己的
合并
策略
git
config
pull
.
rebase
...
hint:
git
config
pull
.
rebase
false # merge (the default stra...
赞
踩
article
探索密码学的未来:
SM1
、
SM2
、
SM3
、
SM4
、同态加密、密态
计算
、隐私
计算
和
安全
多方
计算
_sm1...
密码
算法
在现代通信与信息
安全
中发挥着至关重要的作用,
SM1
、
SM2
、
SM3
、
SM4
、同态加密、密态
计算
、隐私
计算
和
安全
多...
赞
踩
article
关于
could
not f
in
d a
writer
for the
specified
extens...
将原图片"C:\1.jpg"写入到"C:\cat_and_dog\dog_r"时出现如下的错误:cv2.error: O...
赞
踩
article
文本
匹配
模型汇总...
文本
匹配
模型汇总1 DSSMhttps://posenhuang.github.io/papers/cikm2013_D...
赞
踩
article
基于
FPGA
的
OFDM
基带
发射机
的设计与实现_
ofdm
fpga
...
本系统是参照了《基于Xilinx
FPGA
的
OFDM
通信系统
基带
设计》,结合了自己的理解,在Xilinx的zynq 70...
赞
踩
article
MySQL
-
成本
与
统计数据
学习_
成本
分析与
数据库
...
MySQL
执行一个查询可以有不同的执行方案,它会选择其中
成本
最低,或者说代价最低的那种方案去真正的执行查询基于
成本
的优化...
赞
踩
article
一文搞懂域
泛化
、域适应、few-
shot
、zero-
shot
、
open
-
world
、
open
-voc...
域
泛化
是一种机器学习任务,旨在让模型在不同于训练数据的新领域(或域)中进行
泛化
。这意味着模型在未见过的领域中也能表现良好...
赞
踩
article
k8s使用
harbor
私有
仓库
镜像
——
筑梦之路
...
官方文档:ImagePullSecrets的设置是kubernetes机制的另一亮点,习惯于直接使用Docker Pul...
赞
踩
article
ssh
配置
讲解大全...
最近在研究open
ssh
的源代码,不得不折服它代码的精炼和彪悍,即便搞清楚了其架构和思路之后,愣是到头来愣是发现,其实这...
赞
踩
article
llinux使用opecv保存视频无法在浏览器播放怎么办(mp4v ->
avc1
)
_
global
c...
修改``cv2.VideoCapture(0) 为 cv2.VideoCapture(0, cv2.CAP
_
V4L2)解...
赞
踩
article
国产商用
密码
与国际
密码
对照
_
sha
-
1
对应
的
国标
标识...
1
、SM
1
是一种分组加密算法对称加密算法中
的
分组加密算法,其分组长度、秘钥长度都是
1
28bit,算法安全保密强度跟 AE...
赞
踩
article
李沐
45
_
SSD
实现
——自学笔记...
使用L1范数损失,即预测值和真实值之差的绝对值。掩码变量bbox
_
masks令负类锚框和填充锚框不参与损失的计算。最后,...
赞
踩
article
np
.
zeros
...
np
.
zeros
各个参数及如何直接得到整数或其他类型元素的数组_
np
.
zeros
np
.
zeros
...
赞
踩
相关标签
哈希算法
散列表
算法
hadoop
mysql
数据库
sql
linux
求职招聘
spring boot
flink
git
密码学
同态加密
安全
opencv
深度学习
tensorflow
人工智能
fpga
机器学习
kubernetes
容器
云原生