这是我迄今为止使用 bleak 包连接到多个蓝牙设备并从中获取数据/通知的代码。这些设备是秤,如果上面没有重物,它们会在一段时间后自动关闭。一旦对它们施加重量,它们就会打开并开始发出通知。该代码不断扫描正在运行的设备,以记录其中的数据。关闭时,将调用disconnect_callback()函数。
我有一个名为connected_devices 的全局集,用于跟踪打开的设备。连接设备后,其 MAC 地址将添加到该组中。当设备断开连接时,其Mac地址将从集合中删除(在disconnect_callback()函数中)。
我有当前注释掉的锁定代码,以便同步从connected_device集中添加/删除MAC地址,但我不确定是否有必要,因为所有内容都在scan_and_connect()协程中运行。
import asyncio
import functools
from bleak import BleakClient, BleakScanner
#lock = asyncio.Lock()
connected_devices = set()
notify_uuid = "00002A37-0000-1000-8000-00805F9B34FB"
def callback(client, characteristic, data):
print(client.address, characteristic, data)
def disconnected_callback(client):
#with lock:
connected_devices.remove(client.address)
print("disconnect from", device.address)
def match_device(device, adv_data):
#with lock:
return adv_data.local_name.startswith('BLE') and device.address not in connected_devices
async def scan_and_connect():
while True:
device = await BleakScanner.find_device_by_filter(match_device)
if device is None:
continue
client = BleakClient(device, disconnected_callback=disconnected_callback)
try:
await client.connect()
print("connected to", device.address)
await client.start_notify(functools.partial(callback, client))
#with lock:
connected_devices.add(device.address)
except BleakError:
# if failed to connect, this is a no-op, if failed to start notifications, it will disconnect
await client.disconnect()
if __name__ == "__main__":
asyncio.run(scan_and_connect())
有人可以建议在这种情况下是否需要锁吗? 谢谢
来自文档 BleakClient 类
disconnected_callback – 将在事件中安排的回调 当客户端断开连接时循环。
asyncio 保证在等待的调用之间不会运行使用相同事件循环的其他协程。所以你不用担心你的设置操作会被中断而没有理由加锁。
如果这个集合在事件循环之外被改变,那是一个不同的故事。但除非使用该集合的所有内容都使用相同的锁,否则锁仍然没有用。
这段代码的危险之处在于,它假设暗淡回调和被跟踪的地址之间始终存在一对一的关系。您确实应该将
connected_devices.remove(client.address)
包装在异常处理程序中,以防万一。