添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
风流倜傥的黄豆  ·  请问android sdk ...·  3 月前    · 
逃跑的椰子  ·  js date日期格式化_js ...·  1 年前    · 
Bluez 源码编译与安装
  1. 第三方依赖库安装
 sudo apt install libdbus-1-dev libudev-dev libical-dev libreadline-dev
  1. 打开一个终端,进入bluez-5.58的顶层目录,执行./configure 进行Makefile文件的生成以及环境变量配置(在本文章的例程中按照默认进行配置)
➜  bluez-5.58 ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
....
  1. 在./configure 执行成功后,会在bluez-5.58 的顶层目录下生成Makefile文件. 运行make命令进行bluez源码的编译.
➜  bluez-5.58 make
  GEN      ell/shared
make --no-print-directory all-am
  GEN      src/bluetooth.service
  CCLD     src/bluetoothd
  1. 在bluez-5.58编译成功后,通过执行sudo make install 进行相关文件的安装.
➜  bluez-5.58 sudo make install
[sudo] password for apollo: 
make --no-print-directory install-am
 /bin/mkdir -p '/usr/local/bin'
  /bin/bash ./libtool   --mode=install /usr/bin/install -c client/bluetoothctl monitor/btmon tools/rctest tools/l2test tools/l2ping tools/bluemoon tools/hex2hcd tools/mpris-proxy tools/btattach '/usr/local/bin'
libtool: install: /usr/bin/install -c client/bluetoothctl /usr/local/bin/bluetoothctl
libtool: install: /usr/bin/install -c monitor/btmon /usr/local/bin/btmon
libtool: install: /usr/bin/install -c tools/rctest /usr/local/bin/rctest
libtool: install: /usr/bin/install -c tools/l2test /usr/local/bin/l2test
libtool: install: /usr/bin/install -c tools/l2ping /usr/local/bin/l2ping
libtool: install: /usr/bin/install -c tools/bluemoon /usr/local/bin/bluemoon
  1. 在bluez 相关的可执行程序和配置文件更新后,进行bluetooth服务的重启
➜  bluez-5.58 systemctl daemon-reload  
➜  bluez-5.58 service bluetooth restart

bluez-5.58源码基本介绍

bluez-5.58目录结构
➜  bluez-5.58 tree -L 1 --dirsfirst 
├── android
├── attrib
├── btio
├── client
├── completion
├── doc
├── ell
├── emulator
├── gdbus
├── gobex
├── lib
├── mesh
├── monitor
├── obexd
├── PaxHeaders.21757
├── peripheral
├── plugins
├── profiles
├── src
├── test
├── tools
├── unit
bluez-5.58提供的工具
  1. bluetoothctl
➜  client tree
├── advertising.c
├── advertising.h
├── advertising.o
├── adv_monitor.c
├── adv_monitor.h
├── adv_monitor.o
├── agent.c
├── agent.h
├── agent.o
├── bluetoothctl
├── display.c
├── display.h
├── display.o
├── gatt.c
├── gatt.h
├── gatt.o
├── main.c
├── main.o

如上图所示,bluetoothctl实质上是由bluez源码下的client目录的相关文件编译生成的可执行程序(命令). 从文件构成也可以看出来bluetoothctl 主要是bluez官方提供的一个命令行交互的一个客户端,用于和bluetoothd的通信进行BLE广播包的设置、BLE相关配置、创建服务、特征等. 具体的功能请打开终端,运行bluetoothctl 进行查看.

➜  client bluetoothctl
Agent registered
[CHG] Controller BC:83:85:05:80:91 Pairable: yes
[bluetooth]# help
Menu main:
Available commands:
-------------------
advertise                                         Advertise Options Submenu
monitor                                           Advertisement Monitor Options Submenu
scan                                              Scan Options Submenu
gatt                                              Generic Attribute Submenu
list                                              List available controllers
show [ctrl]                                       Controller information
select <ctrl>         
  1. hcidump
    需要注意的是,在编译bluez源码时,在bluez5.58 这一版本中hcidump默认已经被废弃不会编译生成. 需要用的话需要在运行./configure 时增加参数- --enable-deprecated
➜  bluez-5.58 ./configure  --enable-deprecated

对于蓝牙有一些了解的同学都应该了解,蓝牙协议栈和Controler的通信是基于HCI Interface的,简单来说hcidump就是负责解析Controler 上来的数据和协议栈写入到Controler的数据,简单来说就是能输出Controler(控制器)和上层应该的数据通信.

在运行hcidump之前,先要确认我们需要dump的hci设备, 执行hciconfig -a

➜  bluez-5.58 hciconfig -a
hci1:	Type: Primary  Bus: USB
	BD Address: 00:1A:7D:DA:71:13  ACL MTU: 310:10  SCO MTU: 64:8
	DOWN RUNNING 
	RX bytes:574 acl:0 sco:0 events:30 errors:0
	TX bytes:368 acl:0 sco:0 commands:30 errors:0
	Features: 0xff 0xff 0x8f 0xfe 0xdb 0xff 0x5b 0x87
	Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 
	Link policy: RSWITCH HOLD SNIFF PARK 
	Link mode: SLAVE ACCEPT 
hci0:	Type: Primary  Bus: USB
	BD Address: BC:83:85:05:80:91  ACL MTU: 8192:128  SCO MTU: 64:128
	RX bytes:503 acl:0 sco:0 events:22 errors:0
	TX bytes:336 acl:0 sco:0 commands:22 errors:0
	Features: 0xff 0xff 0x8f 0xfe 0x83 0xe1 0x08 0x80
	Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 
	Link policy: RSWITCH HOLD SNIFF PARK 
	Link mode: SLAVE ACCEPT 

然后选择需要dump的hci设备,在这里我需要调试的是hci1

➜  tools sudo ./hcidump -i hci1
[sudo] password for apollo: 
HCI sniffer - Bluetooth packet analyzer ver 5.58
device: hci1 snap_len: 1500 filter: 0xffffffffffffffff

需要注意的是: hcidump 默认的hci device是hci0,所以当系统有多个hci device时,一定要注意通过hciconfig来查看需要调试的hci device.

doc 下ble相关文件简单讲解

如下图所示,bluez-5.58 doc下的文件,是我们主要需要关注的BLE相关文档. 文档都是英文描述,部分的语句为了更好表达我就没有进行翻译,请有需要的同学自己进行翻译的后学习.

➜  doc tree
├── adapter-api.txt
├── advertising-api.txt
├── device-api.txt
├── gatt-api.txt
├── health-api.txt

Bluez Doc下文档学习 - advertising.txt

Advertising packets are structured data which is broadcast on the LE Advertising channels and available for all devices in range. Because of the limited space available in LE Advertising packets (31 bytes), each packet’s contents must be carefully controlled.

这里需要注意的是: 31bytes的广播包 指的是开发中可以修改的,不是完整的数据包,还有数据头等.

Bluez advertising,

Service org.bluez
Interface org.bluez.LEAdvertisement1
Object path freely definable

Interface下面只有一个Methods

Methods void Release() [noreply] //主要是remove advertisement时会被调用

Properties //主要是广播包数据的填充

    dict ManufacturerData  //产商自定义的数据, 需要掌握dict的使用
    array{string} ServiceUUIDs // 将Service UUIDs提前通过广播包进行广播

The Advertising Manager allows external applications to register Advertisement Data which should be broadcast to devices. Advertisement Data elements must follow the API for LE Advertisement Data described above.

Service org.bluez
Interface org.bluez.LEAdvertisingManager1
Object path /org/bluez/{hci0,hci1,…}

主要是提供了Methods RegisterAdvertisement进行广播包的注册

bluez下文档学习 - adapter-api.txt

BlueZ D-Bus Adapter API description

Service org.bluez
Interface org.bluez.Adapter1
Object path [variable prefix]/{hci0,hci1,…}

Methods void StartDiscovery() // 从Methods来看, Adapter是对本设备的操作,和device是不同的,device主要是连接上的设备(Remote device)

Bluez下文档学习 - device-api.txt

Device hierarchy 主要是对设备的操作, Methods: Connect、Disconnect、Pair等, Properties部分主要是存储连接上的设备相关属性以及对远程设备属性的改写.

Bluez下文档学习 - gatt-api.txt(重点)

BlueZ D-Bus GATT API description

GATT local and remote services share the same high-level D-Bus API. Local refers to GATT based service exported by a BlueZ plugin or an external application. Remote refers to GATT services exported by the peer.

BlueZ acts as a proxy, translating ATT operations to D-Bus method calls and Properties (or the opposite). Support for D-Bus Object Manager is mandatory for external services to allow seamless GATT declarations (Service, Characteristic and Descriptors) discovery. Each GATT service tree is required to export a D-Bus Object Manager at its root that is solely responsible for the objects that belong to that service.

Releasing a registered GATT service is not defined yet. Any API extension
should avoid breaking the defined API, and if possible keep an unified GATT remote and local services representation.

以上3段话,最有价值的是标红的内容.

Each GATT service tree is required to export a D-Bus Object Manager at its root that is solely responsible for the objects that belong to that service.

也就是对用Bluez提供的示例代码example-gatt-server 中

@dbus.service.method(GATT_CHRC_IFACE, in_signature='aya{sv}')
def WriteValue(self, value, options):
print('Default WriteValue called, returning error')
raise NotSupportedException()

External applications implementing local services must register the services using GattManager1 registration method and must implement the methods and properties defined in GattService1 interface.

这里描述解释了官方例子中的关于@dbus.service.method的使用.

Characteristic 的相关操作

ervice org.bluez
Interface org.bluez.GattCharacteristic1
Object path [variable prefix]/{hci0,hci1,…}/dev_XX_XX_XX_XX_XX_XX/serviceXX/charYYYY

Methods         void StartNotify()
                void StopNotify()

重点讲下StartNotify和StopNotify,

当Char的属性设置为notifications或者indications时,在手机上的nRF Connect连接上设备时,会看到相关的Char中有一个Enable/Disable Notify的按钮,而StartNotify 和 StopNotify 就是由它触发.

array{byte} Value [read-only, optional]

	The cached value of the characteristic. This property
	gets updated only after a successful read request and
	when a notification or indication is received, upon
	which a PropertiesChanged signal will be emitted.

需要特别注意的是:

The cached value of the characteristic. This property gets updated only after a successful read request and when a notification or indication is received, upon which a PropertiesChanged signal will be emitted.

也就是Value通常情况是只读的,只有在以上描述的条件下才具备其它属性. 另外org.bluez.GattCharacteristic1

         ---> Properties
               ---->Value
     中的Value用于Write、Read、Notify、Indicate 等的存储空间

基于bluez-5.58 下的python实例讲解BLE的数据收发

BLE 广播包创建

Bluez 如何基于Python创建BLE广播
关于Bluez BLE广播的创建请直接学习上述的博客链接.

服务注册,数据收发

在这里是直接使用的bluez-5.58 顶层目test目录下的 example-gatt-server.py 进行服务的注册和收发测试.
详细的代码请下载bluez-5.58源码后进行查看,本文主要重点介绍下 example-gatt-server.py 中关于BLE 的数据收发部分代码.

  1. 以例程example-gatt-server.py 中HeartRateService的HeartRateMeasurementChrc为例子,讲解下notify(BLE设备发数据到连接到BLE设备手机BLE client)
class HeartRateMeasurementChrc(Characteristic):
    HR_MSRMT_UUID = '00002a37-0000-1000-8000-00805f9b34fb'
    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.HR_MSRMT_UUID,
                ['notify'],
                service)
        self.notifying = False
        self.hr_ee_count = 0
	def hr_msrmt_cb(self):
        value = []
        ...
		...
        self.PropertiesChanged(GATT_CHRC_IFACE, { 'Value': value }, [])
        return self.notifying
	def StartNotify(self):
        if self.notifying:
            print('Already notifying, nothing to do')
            return
        self.notifying = True
        self._update_hr_msrmt_simulation()
    def StopNotify(self):
        if not self.notifying:
            print('Not notifying, nothing to do')
            return
        self.notifying = False
        self._update_hr_msrmt_simulation()

1)首先在__init__中将Characteristic定义为notify属性,也就是当手机端中的BLE Client App(本文接下来都已nRF Connect为例子)连接上该BLE 设备后,在App enable该Characteristic 的notify后,BLE 设备可以通过该Characteristic主动发送数据.

2)def StartNotify(self) 是重写于Characteristic类的方法,在Characteristic类中已通过@dbus.service.method(GATT_CHRC_IFACE) 对该方法进行修饰,在App enable该Characteristic 的notify后,def StartNotify(self) 会被调用
与之对应def StopNotify(self),在App disable该Characteristic 的notify后会被调用

  1. 在def StartNotify(self) 被触发后,就可以调用self.PropertiesChanged(GATT_CHRC_IFACE, { ‘Value’: value }, []) 进行数据(填充value字段)的发送

对于Bluez BLE感兴趣的同学欢迎留言交流,后续会持续输出关于Bluez BLE的学习经验,特别是关于Bluez的源码分析.

面向Bluez的需求-简化BLE BLESSED-for-Bluez是适用于Bluez 5.50及更高版本的蓝牙低功耗(BLE)库,这使得使用Bluez进行BLE的工作非常容易。 它完全隐藏了使用Bluez所需的DBus消息传递,并提供类似于CoreBluetooth的面向对象的接口。 该库使用和来与DBusBluez功能进行通信。 该库包含3个核心类和2个回调抽象类: BluetoothCentralManager ,它与抽象类BluetoothCentralManagerCallback BluetoothPeripheral ,以及它的伴随抽象类BluetoothPeriphe 非交互模式: gatttool -b 54:6C:0E:83:82:76 --char-write-req -a 0x0020 -n AA0307546C0E838276FFFC --listen 交互模式: ./gatttool -b 80:EA:CA:01:00:56 –I 在linux上,如果你正在考虑用bluez开发蓝牙相关功能,应该很快就会查到官方推荐用dbus开发。假如你对dbus不熟悉的话,估计很容易就会两眼发黑,发现网上基本找不到例子,似乎让人很难弄下去。这里我提供个入门方法应该可以方便很多人开发bluez。(另外bluez似乎能编译出一个hci动态库,但由于官方推荐使用dbus,这里不做考虑) async def get_bluetoothlist(): global bluetoothlist devices = await BleakScanner.discover() for d in devices: bluetoothlist BlueZLinux官方蓝牙协议栈。它是一个基于GNU General Public License (GPL)发布的开源项目,从Linux2.4.6开始便成为Linux 内核的一部分。 BlueZ支持蓝牙核心层和协议,它灵活、高效,以模块化方式实现,具有以下特点: 完整的模块化实现 均衡的多处理安全 支持多线程数据处理 支持多个蓝牙设备 向所有层提供标准socket接口 提供设备和服务级安全保证 BlueZ包含多个相互独立的模块: Linux内核蓝牙子系统核心 L2CAP 和 SCO 音频内核层 RFCOMM, BNEP, CMTP 和 HIDP内核实现 HCI UART, USB, PCMCIA 和虚拟设备驱动 通用蓝牙和SDP库和守候进程 配置和测试小工具 协议解码和分析工具 BlueZ内核模块,程序开发库和小工具能在支持Linux的多种硬件架构系统上运行,既支持单核也支持多核处理器。BlueZ主要支持以下系统平台: Intel and AMD x86 AMD64 and EM64T (x86-64) SUN SPARC 32/64bit PowerPC 32/64bit Intel StrongARM and XScale Hitachi/Renesas SH processors Motorola DragonBall 现在市面上的很多Linux发行版都支持BlueZ,基本上任何一个Linux系统都兼容BlueZ,如: Debian GNU/Linux Ubuntu Linux Fedora Core / Red Hat Linux OpenSuSE / SuSE Linux Mandrake Linux 基于Python创建一个BLE设备,能够通过nRF Connect发现其设备和广播包数据 基于Python创建一个BLE设备,并完成一个自定义BLE Service的注册,实现数据的简单收发 基于Python创建一个BLE设备,在实现数据收发基础上,增加BLE 连接等状态的上报 背景知识的掌握 Bluez的了解 之前的关于Bluez的讲解博客: 基于Bluez的Blueto. 为了封装更多的逻辑那么我们就要使用编程语言来调用Bluez协议栈,此处给出大神开发的工具包,bluepy。现在bluepy已经更新到0.9.11,目前开发者还在持续跟进该项目,还是有存活概率的,可以放心使用。hciconfig:配置到无线电的HCI接口。gatttool:连接设备、控制GATT。hcitool:hci工具。BlueZ 基本命令。 Houdini是由intel开发的一个闭源arm指令翻译引擎,其目的是为了在x86平台上运行Android App。外界关于houdini的公开资料几乎为0,intel官方也鲜有提及。唯一一个公开研究是Black Hat USA 2021上的一个议题(Sleight of ARM: Demystifying Intel Houdini),但其分析粒度仍然较粗,并且也存在一些错误。笔者从完全黑盒的角度,对houdini进行了逆向,同时也发现了一些新的安全问题,本次将披露houdini底层的指令翻译细节, ================================================================================= shared_sources = src/...