admin管理员组文章数量:1642347
接下来关于基于Python的Bluez-BLE基础开发,主要由3篇文章构成,包含以下三点,循序渐进的完成本系列内容的讲解.
- 基于Python创建一个BLE设备,能够通过nRF Connect发现其设备和广播包数据
- 基于Python创建一个BLE设备,并完成一个自定义BLE Service的注册,实现数据的简单收发
- 基于Python创建一个BLE设备,在实现数据收发的基础上,增加BLE 连接等状态的上报
背景知识的掌握
Bluez的了解
- 之前的关于Bluez的讲解博客: 基于Bluez的Bluetoothctl BLE开发
- Bluez官网
dbus-python
- dbus-python 是python提供的与dbus-daemon的通信库,和我们提到的C语言使用的Glib提供的dbus library是类似的作用
- dbus-python 官网链接
- dbus官网链接
开发环境准备
软件 | 版本 |
---|---|
操作系统 | VM虚拟机+Ubuntu 20.04 |
系统已安装的bluez | 5.50+ |
Bluez源码 | 5.50+ |
我这里使用的版本,
➜ test bluetoothctl --version
bluetoothctl: 5.53
➜ test uname -a
Linux t 5.8.0-50-generic #56~20.04.1-Ubuntu SMP Mon Apr 12 21:46:35 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
bluez 源码: bluez-5.50
建议是和我这边保持一样的版本.
创建一个BLE设备-仅支持BLE广播
获取dbus
在对dbus和bluez有了一定了解后,就能知道我们首先获取与dbus-ddaemon的通信入口.
# 获取系统的dbus
bus = dbus.SystemBus()
在获取到System的dbus后,我们就可以通过dbus 对bluez进行一些操作.
在进行具体的coding之前我们先通过gdbus命令来看下bluez支持的相关interface(object):
## 我这里只是截取了部分的输出,详细请在自己的机器进行测试查看
➜ bluez-5.50 gdbus introspect -y -d "org.bluez" -o "/org/bluez/hci0"
node /org/bluez/hci0 {
interface org.freedesktop.DBus.Introspectable {
methods:
Introspect(out s xml);
signals:
properties:
};
interface org.bluez.Adapter1 {
methods:
StartDiscovery();
SetDiscoveryFilter(in a{sv} properties);
StopDiscovery();
RemoveDevice(in o device);
GetDiscoveryFilters(out as filters);
signals:
properties:
readonly s Address = '00:1A:7D:DA:71:13';
readonly s AddressType = 'public';
readonly s Name = 't';
readwrite s Alias = 't';
通过gdbus相关命令可以看到bluez(BLE)主要实现了如下interface:
- interface org.bluez.Adapter1
- org.freedesktop.DBus.Properties
- org.bluez.GattManager1
- org.bluez.LEAdvertisingManager1
查找Bluez BLE adapter
def find_adapter(bus):
remote_om = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, '/'),
DBUS_OM_IFACE)
objects = remote_om.GetManagedObjects()
for o, props in objects.items():
if LE_ADVERTISING_MANAGER_IFACE in props:
return o
return None
def main():
global mainloop
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
adapter = find_adapter(bus)
if not adapter:
print('LEAdvertisingManager1 interface not found')
return
如上面贴出的Python代码,定义的find_adapter函数,主要是获取到Bluez BLE的adapter, 用于接下来对于以下interface的操作
- interface org.bluez.Adapter1
- org.freedesktop.DBus.Properties
- org.bluez.LEAdvertisingManager1
find_adapter在main中被调用,需要传递bus参数.
在获取到adapter后,需要打开该adapter, 做如下操作:
- 获取interface org.freedesktop.DBus.Properties ,调用其提供的Set 方法
- 调用Set方法,将org.bluez.Adapter1 interface 中的properties:Powered 设置为true.
相关代码如下:
adapter_props = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, adapter),
"org.freedesktop.DBus.Properties");
adapter_props.Set("org.bluez.Adapter1", "Powered", dbus.Boolean(1))
初始化广播包数据并使能
初始化广播包数据:
class TestAdvertisement(Advertisement):
def __init__(self, bus, index):
Advertisement.__init__(self, bus, index, 'peripheral')
self.add_service_uuid('180D')
self.add_service_uuid('180F')
self.add_manufacturer_data(0xffff, [0x00, 0x01, 0x02, 0x03, 0x04])
self.add_service_data('9999', [0x00, 0x01, 0x02, 0x03, 0x04])
self.add_local_name('Tracy')
self.include_tx_power = True
self.add_data(0x26, [0x06])
具体请参考bluez源码提供的提供的官方文档关于广播包数据的描述, bluez-5.50/doc/advertising-api.txt
主要是对org.bluez.LEAdvertisement1 中Properties的操作.
广播包数据注册并使能
ad_manager = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, adapter),
LE_ADVERTISING_MANAGER_IFACE)
test_advertisement = TestAdvertisement(bus, 0)
mainloop = GObject.MainLoop()
ad_manager.RegisterAdvertisement(test_advertisement.get_path(), {},
reply_handler=register_ad_cb,
error_handler=register_ad_error_cb)
-
在main函数下,调用dbus.Interface获取LE_ADVERTISING_MANAGER_IFACE的interface.
-
在main函数下,调用TestAdvertisement完成BLE广播包数据的设置
-
最后调用interface org.bluez.LEAdvertisingManager1下的RegisterAdvertisement进行广播包的注册和使能
具体请参考bluez源码提供的提供的官方文档关于广播包数据的描述, bluez-5.50/doc/advertising-api.txt
GLib Loop
在完成Bluez相关的操作后,不要忽略:
mainloop = GObject.MainLoop()
mainloop.run()
Mainloop起到了系统调度的作用,这一点在后续的文章中会详细说明.
运行example-advertisement
➜ test python3.8 example-advertisement
example-advertisement:201: PyGIDeprecationWarning: GObject.MainLoop is deprecated; use GLib.MainLoop instead
mainloop = GObject.MainLoop()
GetAll
returning props
Advertisement registered
在完成Python代码的编写后,通过python解析器运行该python脚本,运行结果如上.
然后通过nRF Connect 在Android手机上进行BLE设备的搜索、发现,如下图在nRF Connect发现了名称为"Tracy"设备,并确认广播包数据和我们代码中定义的是一致的.
总结
对于Bluez的开发,一个重要的点是需要掌握dbus中相关interface的操作!!
另外需要详细的阅读Bluez源码下面doc目录的相关doc.
版权声明:本文标题:【蓝牙】一文入门Bluez的BLE基础开发 - BLE广播 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1729328737a1196104.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论