我有一个蓝牙设备,其用户友好名称为“Sensor1”。该设备使用 SPP 配置文件。为了要求设备通过蓝牙开始数据流,我必须在与该设备对应的COM端口上写入'10111011',如下所示:
ser = serial.Serial('COM5')
ser.write('10111011')
问题是我不知道哪个 COM 端口对应于“Sensor1”。因此,我读取 Windows 注册表来获取设备名称:
import _winreg as reg
from itertools import count
key = reg.OpenKey(reg.HKEY_LOCAL_MACHINE, 'HARDWARE\\DEVICEMAP\\SERIALCOMM')
for i in count():
device, port = reg.EnumValue(key, i)[:2]
print "Device name \"%s\" found at %s" % (device, port)
我得到的只是:
Device name \Device\Serial0 found at COM3
Device name \Device\BthModem16 found at COM4
Device name \Device\BthModem17 found at COM5
如何获取设备名称,如下所示:
service = bluetooth.find_service()
print service["name"]
import bluetooth
decices = bluetooth.discover_devices()
使用以下库:https://pypi.python.org/pypi/PyBluez/
以下是一些很好的用法示例:https://people.csail.mit.edu/albert/bluez-intro/c212.html
如果您对使用其他库不感兴趣,您可以随时尝试提取与 Windows 相关的发现功能,可在此处找到:https://github.com/karulis/pybluez/blob/2a22e61fb21c27b47898c2674662de65162b485f/bluetooth/widcomm。 py#L109
我建议您先找到MAC地址,然后通过MAC地址找到COM端口。 但我不确定这是否是最好的方法。我在 Windows 10 和 Python 3.5 中测试了这段代码。
要从友好名称查找 MAC 地址,请使用此功能:
import bluetooth
def find_bt_address_by_target_name(name):
# sometimes bluetooth.discover_devices() failed to find all the devices
MAX_COUNT = 3
count = 0
while True:
nearby_devices = bluetooth.discover_devices()
for btaddr in nearby_devices:
if name == bluetooth.lookup_name( btaddr ):
return btaddr
count += 1
if count > MAX_COUNT:
return None
print("Try one more time to find target device..")
然后通过MAC地址找到COM端口。假设您已经与目标设备配对并启用了 SPP 端口:
import winreg
import serial
import time
class BluetoothSpp:
key_bthenum = r"SYSTEM\CurrentControlSet\Enum\BTHENUM"
# IMPORTANT!!
# you need to change this by searching the registry
DEBUG_PORT = 'C00000001'
def get_spp_com_port(self, bt_mac_addr):
print(bt_mac_addr)
bt_mac_addr = bt_mac_addr.replace(':', '').upper()
for i in self.gen_enum_key('', 'LOCALMFG'):
print(i)
for j in self.gen_enum_key(i, bt_mac_addr):
print(j)
if self.DEBUG_PORT in j:
subkey = self.key_bthenum+'\\'+ i+'\\'+j
port = self.get_reg_data(subkey, 'FriendlyName')
assert('Standard Serial over Bluetooth link' in port[0])
items = port[0].split()
port = items[5][1:-1]
print(port)
return port
def gen_enum_key(self, subkey, search_str):
hKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, self.key_bthenum + '\\' + subkey)
try:
i = 0
while True:
output = winreg.EnumKey(hKey, i)
if search_str in output:
yield output
i += 1
except:
pass
winreg.CloseKey(hKey)
def get_reg_data(self, subkey, name):
hKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
subkey)
output = winreg.QueryValueEx(hKey, name)
winreg.CloseKey(hKey)
return output
if __name__ == '__main__':
mac_addr = '11:22:33:44:55:66'
bt_spp = BluetoothSpp()
com_port = bt_spp.get_spp_com_port(mac_addr)
另一个对我有用的解决方案。
import serial.tools.list_ports
#Find COM port with LookFor name
lookFor = "DG-1"
nb=discover_devices(lookup_names=True)
for addr,name in list(nb):
if lookFor == name:
break
else:
name = None
addr = None
if name == lookFor:
comPorts=list(serial.tools.list_ports.comports())
addr=addr.translate(None,":")
for COM,des,hwenu in comPorts :
if addr in hwenu:
break
if name!=None:
print "COM=",COM," BTid=",name
else:
print LookFor," not found."
为了我自己的目的,我改进了 Youngmin Kim 的解决方案。因为我的 Windows 不是英文,所以解析“FriendlyName”不起作用。除了这一变化之外,他的解决方案还为我解决了问题。
import winreg
class BluetoothSpp:
key_bthenum = r"SYSTEM\CurrentControlSet\Enum\BTHENUM"
def get_spp_com_port(self, bt_mac_addr):
bt_mac_addr = bt_mac_addr.replace(':', '').upper()
for i in self.gen_enum_key('', 'LOCALMFG'):
print(i)
for j in self.gen_enum_key(i, bt_mac_addr):
print(j)
subkey = self.key_bthenum + '\\' + i + '\\' + j + '\\' + 'Device Parameters'
port = self.get_reg_data(subkey, 'PortName')
port = port[0]
return port
def gen_enum_key(self, subkey, search_str):
hKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, self.key_bthenum + '\\' + subkey)
try:
i = 0
while True:
output = winreg.EnumKey(hKey, i)
if search_str in output:
yield output
i += 1
except:
pass
winreg.CloseKey(hKey)
def get_reg_data(self, subkey, name):
hKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
subkey)
output = winreg.QueryValueEx(hKey, name)
winreg.CloseKey(hKey)
return output
if __name__ == '__main__':
mac_addr = '00:22:12:00:0A:78'
bt_spp = BluetoothSpp()
com_port = bt_spp.get_spp_com_port(mac_addr)