如何解决GLM50C ragnefinder (Bluetooth smart 4) 无法连接 Windows
我正在尝试将 Bosch GLM 50c 与 Windows 应用程序和代码项目连接,但即使我找到了无法连接的设备。
我已经为此设备尝试了 3 个 win-apps(ArCADia CAD 软件、SiteMaster Building CAD 软件、GLM 传输软件)和 2 个项目(在 python here 和 C# here 中),但都响应一样。
所有人都可以找到该设备,但是在尝试连接时,该设备似乎已连接,一段时间后连接丢失。
但是,该设备与 Android 应用配合使用效果极佳。
有人知道吗?一个设备可以连接不同的操作系统吗?
解决方法
这里是一个简单的python连接项目。 我发布了2个代码。我已经加粗我遇到的问题。
第一个代码的粗体行,调用第二个(库)代码的def connect(self,addrport)函数,并在第二个代码的粗体行中挂起。设备似乎已连接(屏幕上出现蓝牙符号),一段时间后连接丢失并抛出异常。
我不知道 bt.connect (self._sockfd,addr,port) 做了什么以及它为什么挂起。
GLM_50c.py
import bluetooth # install pybluez before importing
import struct
import binascii
class GLMxxC(object):
device_name = ''
socket = None
port = 0x0005 # depends on model type
bluetooth_address = None
connected = False
cmds = {
'measure': b'\xC0\x40\x00\xEE','laser_on': b'\xC0\x41\x00\x96','laser_off': b'\xC0\x42\x00\x1E','backlight_on': b'\xC0\x47\x00\x20','backlight_off': b'\xC0\x48\x00\x62'
}
status = {
0: 'ok',1: 'communication timeout',3: 'checksum error',4: 'unknown command',5: 'invalid access level',8: 'hardware error',10: 'device not ready',}
#Initializing or Constructor
def __init__(self,bluetooth_address=None):
if bluetooth_address is None:
self.find_GLMxxC()
else:
self.bluetooth_address = bluetooth_address
self.connect()
#Finding the available bluetooth devices
def find_GLMxxC(self):
print('Searching for BOSCH GLMxxC ...')
nearby_devices = bluetooth.discover_devices(
duration=8,lookup_names=True,flush_cache=True,lookup_class=False)
print('0')
for index,val in enumerate(nearby_devices):
addr,name = val
if 'BOSCH GLM' in name.upper():
self.bluetooth_address = addr
print('Found ',name.upper(),' @',self.bluetooth_address)
self.device_name = name.upper()
if 'GLM50' in self.device_name:
self.port = 0x0005
return
def connect(self):
try:
self.socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
self.socket.connect((self.bluetooth_address,self.port))
self.connected = True
except:
self.socket.close()
self.conencted = False
def measure(self):
self.socket.send(self.cmds['measure'])
data = self.socket.recv(1024)
print('received:',int(binascii.hexlify((data[0]))))
if self.status[int(binascii.hexlify((data[0])))] == 'ok':
try:
# distance to object from top of device
distance = int(struct.unpack("<L",data[2:6])[0])*0.05
return distance
except:
return -1
else:
return -1
def find_bluetooth_services(self):
services = bluetooth.find_service(address=self.bluetooth_address)
if len(services) > 0:
print("found %d services on %s" % (len(services),self.bluetooth_address))
print(services)
else:
print("no services found")
if __name__ == "__main__":
# Add argparse in a future.
try:
#device = GLMxxC(bluetooth_address='00:13:43:A4:93:07')
device = GLMxxC()
except:
print('No devices GLM100C found')
print('after classes built')
# connecting can be speeded up when the mac address of the device is known,e.g.:
# device = GLM100C(bluetooth_address='54:6C:0E:29:92:2F')
try:
print("Trying to connect with "+ device.__class__.__name__)
device.connect()
except ConnectionError:
print ('Can\'t connect with ' + device.__class__.__name__)
# print('')
#device.find_bluetooth_services()
# print('')
if device.connected:
print('Connected BOSCH '+ device.__class__.__name__+'@',device.bluetooth_address)
try:
print('\ntype \'m\' to measure,\n\'lon\' or \'loff\' to turn laser on/off,\n\'bon\' or \'boff\' to turn backlight on/off,\n\'x\' to exit\n')
while True:
data = input()
if data == 'm':
distance = device.measure()
if distance > 0:
print(distance,'mm from top of device')
print(distance+40.0,'mm from tripod socket')
print(distance+110.0,'mm from back of device')
elif data == 'lon':
device.turn_laser_on()
elif data == 'loff':
device.turn_laser_off()
elif data == 'bon':
device.turn_backlight_on()
elif data == 'boff':
device.turn_backlight_off()
elif data == 'x':
device.close()
print('Connection to BOSCH ' + device.__class__.__name__ + ' closed')
break
except KeyboardInterrupt:
device.close()
print('Connection to '+ device.__class__.__name__+' closed')
else:
print('Could not connect to '+ device.__class__.__name__ )
这是来自 python39 库的 msbt.py 文件,它挂在那里的代码。
from bluetooth import *
import bluetooth._msbt as bt
bt.initwinsock ()
# ============== SDP service registration and unregistration ============
def discover_devices (duration=8,lookup_names=False,lookup_class=False,device_id=-1):
#this is order of items in C-code
btAddresIndex = 0
namesIndex = 1
classIndex = 2
try:
devices = bt.discover_devices(duration=duration,flush_cache=flush_cache)
except OSError:
return []
ret = list()
for device in devices:
item = [device[btAddresIndex],]
if lookup_names:
item.append(device[namesIndex])
if lookup_class:
item.append(device[classIndex])
if len(item) == 1: # in case of address-only we return string not tuple
ret.append(item[0])
else:
ret.append(tuple(i for i in item))
return ret
def read_local_bdaddr():
return bt.list_local()
def lookup_name (address,timeout=10):
if not is_valid_address (address):
raise ValueError ("Invalid Bluetooth address")
try:
return bt.lookup_name(address)
except OSError:
return None
class BluetoothSocket:
def __init__ (self,proto = RFCOMM,sockfd = None):
if proto not in [ RFCOMM ]:
raise ValueError ("invalid protocol")
if sockfd:
self._sockfd = sockfd
else:
self._sockfd = bt.socket (bt.SOCK_STREAM,bt.BTHPROTO_RFCOMM)
self._proto = proto
# used by advertise_service and stop_advertising
self._sdp_handle = None
self._raw_sdp_record = None
# used to track if in blocking or non-blocking mode (FIONBIO appears
# write only)
self._blocking = True
self._timeout = False
@property
def family (self):
return bt.AF_BTH
@property
def type (self):
return bt.SOCK_STREAM
@property
def proto (self):
return bt.BTHPROTO_RFCOMM
def bind (self,addrport):
if self._proto == RFCOMM:
addr,port = addrport
if port == 0: port = bt.BT_PORT_ANY
bt.bind (self._sockfd,port)
def listen (self,backlog):
bt.listen (self._sockfd,backlog)
def accept (self):
clientfd,port = bt.accept (self._sockfd)
client = BluetoothSocket (self._proto,sockfd=clientfd)
return client,(addr,port)
def connect (self,addrport):
addr,port = addrport
bt.connect (self._sockfd,port)
def send (self,data):
return bt.send (self._sockfd,data)
def recv (self,numbytes):
return bt.recv (self._sockfd,numbytes)
def close (self):
return bt.close (self._sockfd)
def getsockname (self):
return bt.getsockname (self._sockfd)
def getpeername (self):
return bt.getpeername (self._sockfd)
getpeername.__doc__ = bt.getpeername.__doc__
def setblocking (self,blocking):
bt.setblocking (self._sockfd,blocking)
self._blocking = blocking
def settimeout (self,timeout):
if timeout < 0: raise ValueError ("invalid timeout")
if timeout == 0:
self.setblocking (False)
else:
self.setblocking (True)
bt.settimeout (self._sockfd,timeout)
self._timeout = timeout
def gettimeout (self):
if self._blocking and not self._timeout: return None
return bt.gettimeout (self._sockfd)
def fileno (self):
return self._sockfd
def dup (self):
return BluetoothSocket (self._proto,sockfd=bt.dup (self._sockfd))
def makefile (self):
# TODO
raise Exception("Not yet implemented")
def advertise_service (sock,name,service_id = "",service_classes = [],\
profiles = [],provider = "",description = "",protocols = []):
if service_id != "" and not is_valid_uuid (service_id):
raise ValueError ("invalid UUID specified for service_id")
for uuid in service_classes:
if not is_valid_uuid (uuid):
raise ValueError ("invalid UUID specified in service_classes")
for uuid,version in profiles:
if not is_valid_uuid (uuid) or version < 0 or version > 0xFFFF:
raise ValueError ("Invalid Profile Descriptor")
for uuid in protocols:
if not is_valid_uuid (uuid):
raise ValueError ("invalid UUID specified in protocols")
if sock._raw_sdp_record is not None:
raise OSError("service already advertised")
avpairs = []
# service UUID
if len (service_id) > 0:
avpairs.append (("UInt16",SERVICE_ID_ATTRID))
avpairs.append (("UUID",service_id))
# service class list
if len (service_classes) > 0:
seq = [ ("UUID",svc_class) for svc_class in service_classes ]
avpairs.append (("UInt16",SERVICE_CLASS_ID_LIST_ATTRID))
avpairs.append (("ElemSeq",seq))
# set protocol and port information
assert sock._proto == RFCOMM
addr,port = sock.getsockname ()
avpairs.append (("UInt16",PROTOCOL_DESCRIPTOR_LIST_ATTRID))
l2cap_pd = ("ElemSeq",(("UUID",L2CAP_UUID),))
rfcomm_pd = ("ElemSeq",RFCOMM_UUID),("UInt8",port)))
proto_list = [ l2cap_pd,rfcomm_pd ]
for proto_uuid in protocols:
proto_list.append (("ElemSeq",proto_uuid),)))
avpairs.append (("ElemSeq",proto_list))
# make the service publicly browseable
avpairs.append (("UInt16",BROWSE_GROUP_LIST_ATTRID))
avpairs.append (("ElemSeq",PUBLIC_BROWSE_GROUP),)))
# profile descriptor list
if len (profiles) > 0:
seq = [ ("ElemSeq",uuid),("UInt16",version))) \
for uuid,version in profiles ]
avpairs.append (("UInt16",BLUETOOTH_PROFILE_DESCRIPTOR_LIST_ATTRID))
avpairs.append (("ElemSeq",seq))
# service name
avpairs.append (("UInt16",SERVICE_NAME_ATTRID))
avpairs.append (("String",name))
# service description
if len (description) > 0:
avpairs.append (("UInt16",SERVICE_DESCRIPTION_ATTRID))
avpairs.append (("String",description))
# service provider
if len (provider) > 0:
avpairs.append (("UInt16",PROVIDER_NAME_ATTRID))
avpairs.append (("String",provider))
sock._raw_sdp_record = sdp_make_data_element ("ElemSeq",avpairs)
# pr = sdp_parse_raw_record (sock._raw_sdp_record)
# for attrid,val in pr.items ():
# print "%5s: %s" % (attrid,val)
# print binascii.hexlify (sock._raw_sdp_record)
# print repr (sock._raw_sdp_record)
sock._sdp_handle = bt.set_service_raw (sock._raw_sdp_record,True)
def stop_advertising (sock):
if sock._raw_sdp_record is None:
raise OSError("service isn't advertised," \
"but trying to un-advertise")
bt.set_service_raw (sock._raw_sdp_record,False,sock._sdp_handle)
sock._raw_sdp_record = None
sock._sdp_handle = None
def find_service (name = None,uuid = None,address = None):
if address is not None:
addresses = [ address ]
else:
addresses = discover_devices (lookup_names = False)
results = []
for addr in addresses:
uuidstr = uuid or PUBLIC_BROWSE_GROUP
if not is_valid_uuid (uuidstr): raise ValueError ("invalid UUID")
uuidstr = to_full_uuid (uuidstr)
dresults = bt.find_service (addr,uuidstr)
for dict in dresults:
raw = dict["rawrecord"]
record = sdp_parse_raw_record (raw)
if SERVICE_CLASS_ID_LIST_ATTRID in record:
svc_class_id_list = [ t[1] for t in \
record[SERVICE_CLASS_ID_LIST_ATTRID] ]
dict["service-classes"] = svc_class_id_list
else:
dict["services-classes"] = []
if BLUETOOTH_PROFILE_DESCRIPTOR_LIST_ATTRID in record:
pdl = []
for profile_desc in \
record[BLUETOOTH_PROFILE_DESCRIPTOR_LIST_ATTRID]:
uuidpair,versionpair = profile_desc[1]
pdl.append ((uuidpair[1],versionpair[1]))
dict["profiles"] = pdl
else:
dict["profiles"] = []
dict["provider"] = record.get (PROVIDER_NAME_ATTRID,None)
dict["service-id"] = record.get (SERVICE_ID_ATTRID,None)
# XXX the C version is buggy (retrieves an extra byte or two),# so get the service name here even though it may have already
# been set
dict["name"] = record.get (SERVICE_NAME_ATTRID,None)
dict["handle"] = record.get (SERVICE_RECORD_HANDLE_ATTRID,None)
# if LANGUAGE_BASE_ATTRID_LIST_ATTRID in record:
# for triple in record[LANGUAGE_BASE_ATTRID_LIST_ATTRID]:
# code_ISO639,encoding,base_offset = triple
#
# if SERVICE_DESCRIPTION_ATTRID in record:
# service_description = record[SERVICE_DESCRIPTION_ATTRID]
if name is None:
results.extend (dresults)
else:
results.extend ([ d for d in dresults if d["name"] == name ])
return results
# =============== DeviceDiscoverer ==================
class DeviceDiscoverer:
def __init__ (self):
raise NotImplementedError
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。