在 Windows 中列出来自 CPython 的已连接 BLE 设备
Listing connected BLE devices from CPython in Windows
我正在将 Linux 上的 Python 代码 运行 移植到 Windows,并且需要实现 2 个简单的特定于平台的功能(通过 [=11 处理) =] 在 Linux 下调用):
- 列出所有当前连接的 BLE 设备
- 例如
list_connected()
→ [('F9:18:AF:E7:9D:40','HeadPhones'),('aa:93:88:1e:03','SmartWatch')]
- 强制断开连接的设备
- 例如
disconnect('F9:18:AF:E7:9D:40',timeout=2)
由于 bleak,其余 BLE 功能已经跨平台。
我只有很少的 Windows 经验,尤其是最近的 API。我环顾四周,不明白 WinRT(Windows 运行时 API)是 UWP(通用 Windows 平台)的一部分,可以从 CPython 通过 pythonnet
和 winrt
包;这是正确的实施方式吗?
感谢提示。
以下是列出和断开设备的主要代码片段(完整代码已通过电子邮件发送给 OP)。我没有包括异常处理和从异步到同步的包装,因为这是 Python 特有的,对其他人来说可能并不那么重要。
import winrt.windows.foundation as wf
import winrt.windows.devices.bluetooth as bt
import winrt.windows.devices.enumeration as denum
import asyncio # to support async / await because winrt doesn't have sync versions of BLE functions
# the naming in the Python wrapper looks a bit messy, underscores mixed up with PascalCase
# another caveat is that we have to call the specific override with the second argument `[]`
# otherwise Python winrt wrapper gets confused with multiple versions of find_all_async
dev_infos = await denum.DeviceInformation.find_all_async(bt.BluetoothLEDevice.get_device_selector(), [])
id_name_pairs = []
for dev_info in dev_infos:
# getting the device itself to access it's "connected" status
le_device = await bt.BluetoothLEDevice.from_id_async(dev_info.id);
if le_device is None: # enumerator sometimes has stale devices; this can also happen when you unplug BLE dongle
continue
# in status context, Microsoft calls it "CONNECTED", but later, when disconnecting, it needs "unpair"
# and there is no any "disconnect" function. Microsoft is messy in this regard
if le_device.connection_status == bt.BluetoothConnectionStatus.CONNECTED:
id_name_pairs.append((le_device.device_id, le_device.name));
重要 - Microsoft 通过其完整 ID 而不是 BLE 地址来识别 BLE 设备。如果我们希望稍后能够断开设备,我们必须知道 ID。如果我们不将 ID 存储在任何地方并按地址断开连接,我们将不得不再次 运行 枚举并按地址查找 ID。
从设备 ID 中轻松提取 BLE 地址:
addressed_devices = list(map(lambda dev: (dev[0][-17:], dev[1]), id_name_pairs))
要断开已知 ID 的设备:
le_device = await bt.BluetoothLEDevice.from_id_async(dev_id)
await le_device.device_information.pairing.unpair_async()
要求:Windows10,2018 年 10 月更新或更高版本,Python for Windows,版本 3.7 或更高版本,pip,版本 19 或更高版本。
使用 pip install winrt
获取 Python winrt 包装器库。
总而言之,一项乍一看似乎微不足道的任务,由于 .NET / Python 命名和覆盖差异以及 Microsoft 的 pairing/connection 导致了一些 head-scratching执行;很容易与不能使用 BLE 配对信息的经典蓝牙 BR/EDR API 混淆。
我正在将 Linux 上的 Python 代码 运行 移植到 Windows,并且需要实现 2 个简单的特定于平台的功能(通过 [=11 处理) =] 在 Linux 下调用):
- 列出所有当前连接的 BLE 设备
- 例如
list_connected()
→[('F9:18:AF:E7:9D:40','HeadPhones'),('aa:93:88:1e:03','SmartWatch')]
- 例如
- 强制断开连接的设备
- 例如
disconnect('F9:18:AF:E7:9D:40',timeout=2)
- 例如
由于 bleak,其余 BLE 功能已经跨平台。
我只有很少的 Windows 经验,尤其是最近的 API。我环顾四周,不明白 WinRT(Windows 运行时 API)是 UWP(通用 Windows 平台)的一部分,可以从 CPython 通过 pythonnet
和 winrt
包;这是正确的实施方式吗?
感谢提示。
以下是列出和断开设备的主要代码片段(完整代码已通过电子邮件发送给 OP)。我没有包括异常处理和从异步到同步的包装,因为这是 Python 特有的,对其他人来说可能并不那么重要。
import winrt.windows.foundation as wf
import winrt.windows.devices.bluetooth as bt
import winrt.windows.devices.enumeration as denum
import asyncio # to support async / await because winrt doesn't have sync versions of BLE functions
# the naming in the Python wrapper looks a bit messy, underscores mixed up with PascalCase
# another caveat is that we have to call the specific override with the second argument `[]`
# otherwise Python winrt wrapper gets confused with multiple versions of find_all_async
dev_infos = await denum.DeviceInformation.find_all_async(bt.BluetoothLEDevice.get_device_selector(), [])
id_name_pairs = []
for dev_info in dev_infos:
# getting the device itself to access it's "connected" status
le_device = await bt.BluetoothLEDevice.from_id_async(dev_info.id);
if le_device is None: # enumerator sometimes has stale devices; this can also happen when you unplug BLE dongle
continue
# in status context, Microsoft calls it "CONNECTED", but later, when disconnecting, it needs "unpair"
# and there is no any "disconnect" function. Microsoft is messy in this regard
if le_device.connection_status == bt.BluetoothConnectionStatus.CONNECTED:
id_name_pairs.append((le_device.device_id, le_device.name));
重要 - Microsoft 通过其完整 ID 而不是 BLE 地址来识别 BLE 设备。如果我们希望稍后能够断开设备,我们必须知道 ID。如果我们不将 ID 存储在任何地方并按地址断开连接,我们将不得不再次 运行 枚举并按地址查找 ID。
从设备 ID 中轻松提取 BLE 地址:
addressed_devices = list(map(lambda dev: (dev[0][-17:], dev[1]), id_name_pairs))
要断开已知 ID 的设备:
le_device = await bt.BluetoothLEDevice.from_id_async(dev_id)
await le_device.device_information.pairing.unpair_async()
要求:Windows10,2018 年 10 月更新或更高版本,Python for Windows,版本 3.7 或更高版本,pip,版本 19 或更高版本。
使用 pip install winrt
获取 Python winrt 包装器库。
总而言之,一项乍一看似乎微不足道的任务,由于 .NET / Python 命名和覆盖差异以及 Microsoft 的 pairing/connection 导致了一些 head-scratching执行;很容易与不能使用 BLE 配对信息的经典蓝牙 BR/EDR API 混淆。