如何从可扩展服务器清除已注册的播发?

2024-10-03 11:23:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试运行以下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)。我正在寻找一种方法来清理注册广告,如果有一些,并得到启动我的服务器上这个英特尔爱迪生


Tags: pyhttpsgithub服务器脚本comserverexample
2条回答

{a1}为错误提供了一点解释:

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管理器APIUnregister*方法:

您可能还需要^{}创建的GLib.MainLoop

accepted answer中提到的example-gatt-server不执行此操作,但是您也可以检查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函数以cleanup调用结束

https://github.com/Jumperr-labs/python-gatt-server中的代码只是BlueZ代码的移植/重新组织版本。一个改进是修改advertisinggatt-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)

如果从github.com/edison-fw运行最新的Yocto映像,并切换到最新的python3example gatt server,则服务器运行时不会出错。Bluetoothctlshow显示在关闭gatt服务器后,心率服务会自动取消注册

相关问题 更多 >