GLM50C ragnefinder (Bluetooth smart 4) не может подключиться к Windows

Я пытаюсь подключить Bosch GLM 50c с приложениями Windows и проектами кода, но даже если я нахожу устройство, я не могу подключиться.

Я попытался 3 Win-приложений (программное обеспечение Arcadia CAD, программное обеспечение SiteMaster Строительство CAD, программное обеспечение передачи GLM) и 2 проекта для данного устройства (в питон здесь и в C# здесь ) , но все реагируют то же самое.

Все могут найти устройство, но при попытке подключения устройство кажется подключенным и через некоторое время связь теряется.

Однако устройство отлично работает с приложениями Android.

Есть у кого-нибудь идеи? Возможно ли подключение устройства к другой ОС?

1 ответ

Вот простой проект подключения на Python. Выложил 2 кода. Я выделил жирным шрифтом линии, где стоит проблема.

Строка первого кода, выделенная жирным шрифтом, вызывает функцию def connect (self, addrport) второго (библиотечного) кода, а в строке, выделенной жирным шрифтом, второго кода она висит. Кажется, что устройство подключено (на экране появляется символ bluetooth), и через некоторое время соединение теряется и выдается исключение.

Понятия не имею, что делает 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__ )

Вот файл msbt.py из библиотек python39, где и висит код.

      from bluetooth import *
import bluetooth._msbt as bt

bt.initwinsock ()

# ============== SDP service registration and unregistration ============

def discover_devices (duration=8, flush_cache=True, 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, addr, port)

    def listen (self, backlog):
        bt.listen (self._sockfd, backlog)

    def accept (self):
        clientfd, addr, 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, addr, 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", (("UUID", RFCOMM_UUID), ("UInt8", port)))
    proto_list = [ l2cap_pd, rfcomm_pd ]
    for proto_uuid in protocols:
        proto_list.append (("ElemSeq", (("UUID", proto_uuid),)))
    avpairs.append (("ElemSeq", proto_list))

    # make the service publicly browseable
    avpairs.append (("UInt16", BROWSE_GROUP_LIST_ATTRID))
    avpairs.append (("ElemSeq", (("UUID", PUBLIC_BROWSE_GROUP),)))

    # profile descriptor list
    if len (profiles) > 0:
        seq = [ ("ElemSeq", (("UUID",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
Другие вопросы по тегам