如何从 BLE 服务器清除已注册的广告?
How to clean registered advertisements from a BLE server?
我正在尝试 运行 以下 python 脚本:https://github.com/Jumperr-labs/python-gatt-server (gatt-server-example.py) 这是一个低功耗蓝牙服务器。
它在我的电脑上工作得很好,但是当我尝试 运行 它在英特尔爱迪生上时,我收到以下错误:
Failed to register advertisement: org.bluez.Error.NotPermitted: Maximum
advertisements reached
Python-dbus 和 Bluez 已安装在此设备上 (Bluez v5.50)。我正在寻找一种方法来清除已注册的广告(如果有的话)并在这个英特尔爱迪生上启动我的服务器。
如果您 运行 来自 github.com/edison-fw 的最新 Yocto 映像并切换到最新 python3 example gatt server 服务器 运行s没有错误。 Bluetoothctl show
显示心率服务在杀死gatt服务器后自动注销
BlueZ API docs 对错误提供了一些解释:
Methods RegisterAdvertisement(object advertisement, dict options)
Registers an advertisement object to be sent over the LE
Advertising channel. The service must be exported
under interface LEAdvertisement1.
...
If the maximum number of advertisement instances is
reached it will result in NotPermitted error.
因此,错误来自 RegisterAdvertisement
调用:
ad_manager.RegisterAdvertisement(test_advertisement.get_path(), {},
reply_handler=register_ad_cb,
error_handler=functools.partial(register_ad_error_cb, mainloop))
“brute-force”清除以前注册的广告的方法是始终在 运行 您的 BLE 服务器之前重新启动蓝牙服务。
# Restart bluetooth
$ systemctl restart bluetooth
$ systemctl status bluetooth
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset
Active: active (running) since Thu 2020-08-20 18:07:55 JST; 4s ago
...
# Start BLE server
$ python3 gatt-server.py
一种更“优雅”的方法是尝试确保您的 BLE 服务器实现具有正确关闭或清理的处理能力。尝试在服务器进程 ends/quits:
时调用 BlueZ 广告管理器和 GATT 管理器 API Unregister*
方法
UnregisterAdvertisement
- https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/advertising-api.txt#n178
-
This unregisters an advertisement that has been previously registered. The object path parameter must match the same value that has been used on registration.
UnregisterApplication
- https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/gatt-api.txt#n477
-
This unregisters the services that has been previously registered. The object path parameter must match the same value that has been used on registration.
您可能还需要 quit
创建的 GLib.MainLoop
。
example-gatt-server mentioned in the does not do this, but you can also check example-advertisement 代码(也来自 BlueZ) 这样做:
def shutdown(timeout):
print('Advertising for {} seconds...'.format(timeout))
time.sleep(timeout)
mainloop.quit()
def main(timeout=0):
...
mainloop = GObject.MainLoop()
ad_manager.RegisterAdvertisement(test_advertisement.get_path(), {},
reply_handler=register_ad_cb,
error_handler=register_ad_error_cb)
if timeout > 0:
threading.Thread(target=shutdown, args=(timeout,)).start()
else:
print('Advertising forever...')
mainloop.run() # blocks until mainloop.quit() is called
ad_manager.UnregisterAdvertisement(test_advertisement)
print('Advertisement unregistered')
dbus.service.Object.remove_from_connection(test_advertisement)
请注意,当 mainloop
退出时,main
函数以清理调用结束。
https://github.com/Jumperr-labs/python-gatt-server 中的代码只是 BlueZ 代码的 ported/re-organized 版本。一项改进是修改 advertising
和 gatt-server
模块以添加适当的清理。
一种方法是使用 SIGTERM 信号优雅地终止 BLE 服务器进程,然后 catching that SIGTERM within the app。
# ----------------------------------------------------------------------
def terminate(signum, frame):
adv_manager.UnregisterAdvertisement(...)
gatt_manager.UnregisterApplication(...)
main_loop.quit()
return True
# ----------------------------------------------------------------------
signal.signal(signal.SIGTERM, terminate)
我正在尝试 运行 以下 python 脚本:https://github.com/Jumperr-labs/python-gatt-server (gatt-server-example.py) 这是一个低功耗蓝牙服务器。
它在我的电脑上工作得很好,但是当我尝试 运行 它在英特尔爱迪生上时,我收到以下错误:
Failed to register advertisement: org.bluez.Error.NotPermitted: Maximum
advertisements reached
Python-dbus 和 Bluez 已安装在此设备上 (Bluez v5.50)。我正在寻找一种方法来清除已注册的广告(如果有的话)并在这个英特尔爱迪生上启动我的服务器。
如果您 运行 来自 github.com/edison-fw 的最新 Yocto 映像并切换到最新 python3 example gatt server 服务器 运行s没有错误。 Bluetoothctl show
显示心率服务在杀死gatt服务器后自动注销
BlueZ API docs 对错误提供了一些解释:
Methods RegisterAdvertisement(object advertisement, dict options)
Registers an advertisement object to be sent over the LE
Advertising channel. The service must be exported
under interface LEAdvertisement1.
...
If the maximum number of advertisement instances is
reached it will result in NotPermitted error.
因此,错误来自 RegisterAdvertisement
调用:
ad_manager.RegisterAdvertisement(test_advertisement.get_path(), {},
reply_handler=register_ad_cb,
error_handler=functools.partial(register_ad_error_cb, mainloop))
“brute-force”清除以前注册的广告的方法是始终在 运行 您的 BLE 服务器之前重新启动蓝牙服务。
# Restart bluetooth
$ systemctl restart bluetooth
$ systemctl status bluetooth
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset
Active: active (running) since Thu 2020-08-20 18:07:55 JST; 4s ago
...
# Start BLE server
$ python3 gatt-server.py
一种更“优雅”的方法是尝试确保您的 BLE 服务器实现具有正确关闭或清理的处理能力。尝试在服务器进程 ends/quits:
时调用 BlueZ 广告管理器和 GATT 管理器 APIUnregister*
方法
UnregisterAdvertisement
- https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/advertising-api.txt#n178
-
This unregisters an advertisement that has been previously registered. The object path parameter must match the same value that has been used on registration.
UnregisterApplication
- https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/gatt-api.txt#n477
-
This unregisters the services that has been previously registered. The object path parameter must match the same value that has been used on registration.
您可能还需要 quit
创建的 GLib.MainLoop
。
example-gatt-server mentioned in the
def shutdown(timeout):
print('Advertising for {} seconds...'.format(timeout))
time.sleep(timeout)
mainloop.quit()
def main(timeout=0):
...
mainloop = GObject.MainLoop()
ad_manager.RegisterAdvertisement(test_advertisement.get_path(), {},
reply_handler=register_ad_cb,
error_handler=register_ad_error_cb)
if timeout > 0:
threading.Thread(target=shutdown, args=(timeout,)).start()
else:
print('Advertising forever...')
mainloop.run() # blocks until mainloop.quit() is called
ad_manager.UnregisterAdvertisement(test_advertisement)
print('Advertisement unregistered')
dbus.service.Object.remove_from_connection(test_advertisement)
请注意,当 mainloop
退出时,main
函数以清理调用结束。
https://github.com/Jumperr-labs/python-gatt-server 中的代码只是 BlueZ 代码的 ported/re-organized 版本。一项改进是修改 advertising
和 gatt-server
模块以添加适当的清理。
一种方法是使用 SIGTERM 信号优雅地终止 BLE 服务器进程,然后 catching that SIGTERM within the app。
# ----------------------------------------------------------------------
def terminate(signum, frame):
adv_manager.UnregisterAdvertisement(...)
gatt_manager.UnregisterApplication(...)
main_loop.quit()
return True
# ----------------------------------------------------------------------
signal.signal(signal.SIGTERM, terminate)