我正在尝试运行以下python脚本:https://github.com/Jumperr-labs/python-gatt-server(gatt-server-example.py),它是蓝牙低功耗服务器。
它在我的计算机上可以正常运行,但是当我尝试在intel-edison上运行它时,出现以下错误:
Failed to register advertisement: org.bluez.Error.NotPermitted: Maximum
advertisements reached
Python-dbus和bluez已安装在此设备上(Bluez v5.50)。我正在寻找一种方法来清除注册的广告(如果有的话)并可以在此ined-edison上启动服务器。
答案 0 :(得分:2)
如果您从github.com/edison-fw运行最新的Yocto映像并切换到最新的python3 example gatt server,则服务器将运行而不会出现错误。 Bluetoothctl type 'a stream = Eos | StrCons of 'a*(unit -> 'a stream)
(*integers from n onwards*)
let rec nums_from n =
StrCons(n,fun () -> nums_from (n+1))
let rec filterStr (test : 'a -> bool) (s: 'a stream) =
match s with
|Eos -> Eos
|StrCons(q,w) -> if test q then StrCons(q,fun ()-> filterStr test (w ()))
else filterStr test (w ())
(*Remove all numbers mod p*)
let sift p =
filterStr (fun x -> x mod p <> 0)
(*Sieves*)
let rec sieves s =
match s with
|Eos ->Eos
|StrCons(x,g) -> StrCons(x, fun ()-> sieves (sift x (g ())))
(*primes*)
let allprimes = sieves (nums_from 2)
let rec listify s n=
if n =0 then [] else
match s with
|Eos -> []
|StrCons(q,w) -> q::(listify (w ()) (n-1))
let twodigitsprimes = filterStr (fun x -> x > 10&& x<100) allprimes
let twodigitsprimeslist= listify twodigitsprimes 21
显示,杀死gatt服务器后,心率服务会自动注销。
答案 1 :(得分:1)
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))
清除以前注册的广告的“强力”方法是始终在运行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服务器实现具有正确关闭或清理的处理。尝试在服务器进程结束/退出时调用BlueZ广告管理器和GATT管理器API Unregister*
方法:
UnregisterAdvertisement
这将取消注册先前已注册的广告。对象路径参数必须与注册时使用的值相同。
UnregisterApplication
这将取消注册先前已注册的服务。对象路径参数必须与注册时使用的值相同。
您可能还需要quit
创建的GLib.MainLoop
。
example-gatt-server中提到的accepted answer不能执行此操作,但是您也可以检查可以执行的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代码的移植/重新组织的版本。一种改进是修改advertising
和gatt-server
模块以添加适当的清除。
一种方法是通过使用SIGTERM信号(然后是catching that SIGTERM within the app)优雅地杀死BLE服务器进程。
# ----------------------------------------------------------------------
def terminate(signum, frame):
adv_manager.UnregisterAdvertisement(...)
gatt_manager.UnregisterApplication(...)
main_loop.quit()
return True
# ----------------------------------------------------------------------
signal.signal(signal.SIGTERM, terminate)