def run(self, getnames, duration): if self._inquiring: raise _lightbluecommon.BluetoothError( "Another inquiry in progress") # set inquiry attributes self._inquiry.updatenames = getnames self._inquiry.length = duration # start the inquiry err = self._inquiry.start() if err != _macutil.kIOReturnSuccess: raise _lightbluecommon.BluetoothError( err, "Error starting device inquiry") # if error occurs during inquiry, set _inquiryerr to the error code self._inquiryerr = _macutil.kIOReturnSuccess # wait until the inquiry is complete self._inquiring = True _macutil.waituntil(lambda: not self._inquiring) # if error occured during inquiry, raise exception if self._inquiryerr != _macutil.kIOReturnSuccess: raise _lightbluecommon.BluetoothError(self._inquiryerr, "Error during device inquiry")
def _getavailableport(proto): # Just advertise a service and see what channel it was assigned, then # stop advertising the service and return the channel. # It's a hacky way of doing it, but IOBluetooth doesn't seem to provide # functionality for just getting an available channel. if proto == _lightbluecommon.RFCOMM: try: result, channelID, servicerecordhandle = BBServiceAdvertiser.addRFCOMMServiceDictionary_withName_UUID_channelID_serviceRecordHandle_( BBServiceAdvertiser.serialPortProfileDictionary(), "DummyService", None, None, None) except: result, channelID, servicerecordhandle = BBServiceAdvertiser.addRFCOMMServiceDictionary_withName_UUID_channelID_serviceRecordHandle_( BBServiceAdvertiser.serialPortProfileDictionary(), "DummyService", None) if result != _macutil.kIOReturnSuccess: raise _lightbluecommon.BluetoothError(result, \ "Could not retrieve an available service channel") result = BBServiceAdvertiser.removeService_(servicerecordhandle) if result != _macutil.kIOReturnSuccess: raise _lightbluecommon.BluetoothError(result, \ "Could not retrieve an available service channel") return channelID else: raise NotImplementedError( "L2CAP server sockets not currently supported")
def stopadvertise(sock): if not sock._advertised: raise _lightbluecommon.BluetoothError("no service advertised") try: bluetooth.stop_advertising(sock._sock) except bluetooth.BluetoothError, e: raise _lightbluecommon.BluetoothError(str(e))
def stopadvertise(sock): if sock is None: raise TypeError("Given socket is None") servicerecordhandle = __advertised.get(id(sock)) if servicerecordhandle is None: raise _lightbluecommon.BluetoothError("no service advertised") result = _LightAquaBlue.BBServiceAdvertiser.removeService_(servicerecordhandle) if result != _macutil.kIOReturnSuccess: raise _lightbluecommon.BluetoothError( result, "Error stopping advertising of service")
def _getport(self): if self.__isconnected(): return self.__conn.getport() if self.__isbound(): return self.__port raise _lightbluecommon.BluetoothError( "socket is neither connected nor bound")
def stopadvertise(sock): details = __advertised.get(id(sock)) if details is None: raise _lightbluecommon.BluetoothError("no service advertised") name, servicetype = details _socket.bt_advertise_service(name, sock._sock, False, servicetype)
def _gethostname(): import _lightblueutil try: name = _lightblueutil.getLocalName() except SymbianError, exc: raise _lightbluecommon.BluetoothError( "Cannot read local device name: " + str(exc))
def gethostclass(): import _lightblueutil try: cod = _lightblueutil.getLocalDeviceClass() except SymbianError, exc: raise _lightbluecommon.BluetoothError( "Cannot read local device class: " + str(exc))
def gethostaddr(): import _lightblueutil try: addr = _lightblueutil.getLocalAddress() except SymbianError, exc: raise _lightbluecommon.BluetoothError( "Cannot read local device address: " + str(exc))
def advertise(servicename, sock, serviceclass): try: if serviceclass == _lightbluecommon.RFCOMM: bluetooth.advertise_service( sock._sock, servicename, service_classes=[bluetooth.SERIAL_PORT_CLASS], profiles=[bluetooth.SERIAL_PORT_PROFILE]) elif serviceclass == _lightbluecommon.OBEX: # for pybluez, socket do need to be listening in order to # advertise a service, so we'll call listen() here. This should be # safe since user shouldn't have called listen() already, because # obex.recvfile() docs state that an obex server socket should # *not* be listening before recvfile() is called (due to Series60's # particular implementation) if not sock._listening: sock.listen(1) # advertise Object Push Profile not File Transfer Profile because # obex.recvfile() implementations run OBEX servers which only # advertise Object Push operations bluetooth.advertise_service( sock._sock, servicename, service_classes=[bluetooth.OBEX_OBJPUSH_CLASS], profiles=[bluetooth.OBEX_OBJPUSH_PROFILE], protocols=["0008"]) # OBEX protocol else: raise ValueError("Unknown serviceclass, " + \ "should be either RFCOMM or OBEX constants") # set flag sock._advertised = True except bluetooth.BluetoothError, e: raise _lightbluecommon.BluetoothError(str(e))
def gethostaddr(): addr = _LightAquaBlue.BBLocalDevice.getAddressString() if addr is not None: # PyObjC returns all strings as unicode, but the address doesn't need # to be unicode cos it's just hex values return _macutil.formatdevaddr(addr) raise _lightbluecommon.BluetoothError("Cannot read local device address")
def query(self, device, timeout=10.0): # do SDP query err = device.performSDPQuery_(self) if err != _macutil.kIOReturnSuccess: raise _lightbluecommon.BluetoothError(err, self._errmsg(device)) # performSDPQuery_ is async, so block-wait self._queryresult = None if not _macutil.waituntil(lambda: self._queryresult is not None, timeout): raise _lightbluecommon.BluetoothError( "Timed out getting services for %s" % \ device.getNameOrAddress()) # query is now complete if self._queryresult != _macutil.kIOReturnSuccess: raise _lightbluecommon.BluetoothError( self._queryresult, self._errmsg(device))
def findservices(addr=None, name=None, servicetype=None): if servicetype not in (_lightbluecommon.RFCOMM, _lightbluecommon.OBEX, None): raise ValueError("servicetype must be RFCOMM, OBEX or None, was %s" % \ servicetype) if addr is None: try: founddevices = finddevices() except _lightbluecommon.BluetoothError as e: msg = "findservices() failed, " +\ "error while finding devices: " + str(e) raise _lightbluecommon.BluetoothError(msg) #print founddevices addresses = [dev[0] for dev in founddevices] else: addresses = [addr] services = [] for devaddr in addresses: iobtdevice = _IOBluetooth.IOBluetoothDevice.withAddress_( _macutil.createbtdevaddr(devaddr)) try: lastseen = iobtdevice.getLastServicesUpdate() if lastseen is None or lastseen.timeIntervalSinceNow() < -2: # perform SDP query to update known services. # wait at least a few seconds between service discovery cos # sometimes it doesn't work if doing updates too often. # In future should have option to not do updates. serviceupdater = _SDPQueryRunner.alloc().init() try: serviceupdater.query(iobtdevice) # blocks until updated except _lightbluecommon.BluetoothError as e: msg = "findservices() couldn't get services for %s: %s" % \ (iobtdevice.getNameOrAddress(), str(e)) warnings.warn(msg) # or should I use cached services instead of warning? # but sometimes the cached ones are totally wrong. # if searching for RFCOMM, exclude OBEX services if servicetype == _lightbluecommon.RFCOMM: uuidbad = _macutil.PROTO_UUIDS.get(_lightbluecommon.OBEX) else: uuidbad = None filtered = _searchservices(iobtdevice, name=name, uuid=_macutil.PROTO_UUIDS.get(servicetype), uuidbad=uuidbad) #print "unfiltered:", iobtdevice.getServices() services.extend([_getservicetuple(s) for s in filtered]) finally: # close baseband connection (not sure if this is necessary, but # sometimes the transport connection seems to stay open?) iobtdevice.closeConnection() return services
def initWithAddress_(self, address): try: attr = _IOBluetooth.IOBluetoothDevicePair except AttributeError: raise ImportError("Cannot find IOBluetoothDevicePair class " +\ "to perform device discovery. This class was introduced in " +\ "Mac OS X 10.7, are you running an earlier version?") self = super(_AsyncPair, self).init() self.device = _IOBluetooth.IOBluetoothDevice.withAddressString_(address) if not self.device: raise _lightbluecommon.BluetoothError( "Could not find device name for %s" % address) self.pair = _IOBluetooth.IOBluetoothDevicePair.pairWithDevice_(self.device) if not self.pair: raise _lightbluecommon.BluetoothError( "Could not create pairing state machine.") self.pair.setDelegate_(self) return self
def advertise(name, sock, servicetype): if not isinstance(name, types.StringTypes): raise TypeError("name must be string, was %s" % \ type(name)) # raises exception if socket is not bound boundchannelID = sock._getport() # advertise the service if servicetype == _lightbluecommon.RFCOMM: try: result, finalchannelID, servicerecordhandle = _LightAquaBlue.BBServiceAdvertiser.addRFCOMMServiceDictionary_withName_UUID_channelID_serviceRecordHandle_( _LightAquaBlue.BBServiceAdvertiser.serialPortProfileDictionary(), name, None, None, None) except: result, finalchannelID, servicerecordhandle = _LightAquaBlue.BBServiceAdvertiser.addRFCOMMServiceDictionary_withName_UUID_channelID_serviceRecordHandle_( _LightAquaBlue.BBServiceAdvertiser.serialPortProfileDictionary(), name, None) elif servicetype == _lightbluecommon.OBEX: try: result, finalchannelID, servicerecordhandle = _LightAquaBlue.BBServiceAdvertiser.addRFCOMMServiceDictionary_withName_UUID_channelID_serviceRecordHandle_( _LightAquaBlue.BBServiceAdvertiser.objectPushProfileDictionary(), name, None, None, None) except: result, finalchannelID, servicerecordhandle = _LightAquaBlue.BBServiceAdvertiser.addRFCOMMServiceDictionary_withName_UUID_channelID_serviceRecordHandle_( _LightAquaBlue.BBServiceAdvertiser.objectPushProfileDictionary(), name, None) else: raise ValueError("servicetype must be either RFCOMM or OBEX") if result != _macutil.kIOReturnSuccess: raise _lightbluecommon.BluetoothError( result, "Error advertising service") if boundchannelID != finalchannelID: msg = "socket bound to unavailable channel (%d), " % boundchannelID +\ "use channel value of 0 to bind to dynamically assigned channel" raise _lightbluecommon.BluetoothError(msg) # note service record handle, so that the service can be stopped later __advertised[id(sock)] = servicerecordhandle
def _gethostname(): sock = _gethcisock() try: try: name = _lightblueutil.hci_read_local_name(sock.fileno(), 1000) except IOError, e: raise _lightbluecommon.BluetoothError(str(e)) finally: sock.close() return name
def gethostaddr(): sock = _gethcisock() try: try: addr = _lightblueutil.hci_read_bd_addr(sock.fileno(), 1000) except IOError, e: raise _lightbluecommon.BluetoothError(str(e)) finally: sock.close() return addr
def gethostclass(): sock = _gethcisock() try: try: cod = _lightblueutil.hci_read_class_of_dev(sock.fileno(), 1000) except IOError, e: raise _lightbluecommon.BluetoothError(str(e)) finally: sock.close() return _lightbluecommon._joinclass(cod)
def run(self, getnames=True, length=10): self._founddevices = [] self._inquiry = _MyDiscoverer(self._founddevice, self._inquirycomplete) try: self._inquiry.find_devices(lookup_names=getnames, duration=length) # block until inquiry finishes self._inquiry.process_inquiry() except bluetooth.BluetoothError, e: try: self._inquiry.cancel_inquiry() finally: raise _lightbluecommon.BluetoothError(e)
def finddevicename(address, usecache=True): if not _lightbluecommon._isbtaddr(address): raise ValueError("%s is not a valid bluetooth address" % str(address)) if address == gethostaddr(): return _gethostname() try: # lookupName() expects address without colon separators import _lightblueutil address_no_sep = address.replace(":", "").replace("-", "") name = _lightblueutil.lookupName(address_no_sep, (not usecache)) except SymbianError, e: raise _lightbluecommon.BluetoothError( "Cannot find device name for %s: %s" % (address, str(e)))
def findservices(addr=None, name=None, servicetype=None): if servicetype not in (_lightbluecommon.RFCOMM, _lightbluecommon.OBEX, None): raise ValueError("servicetype must be RFCOMM, OBEX or None, was %s" % \ servicetype) if addr is None: try: founddevices = finddevices() except _lightbluecommon.BluetoothError, e: msg = "findservices() failed, " +\ "error while finding devices: " + str(e) raise _lightbluecommon.BluetoothError(msg) #print founddevices addresses = [dev[0] for dev in founddevices]
def finddevicename(address, usecache=True): if not _lightbluecommon._isbtaddr(address): raise ValueError("%s is not a valid bluetooth address" % str(address)) if address == gethostaddr(): return _gethostname() if usecache: name = _devicenames.get(address) if name is not None: return name name = bluetooth.lookup_name(address) if name is None: raise _lightbluecommon.BluetoothError( "Could not find device name for %s" % address) _devicenames[address] = name return name
def finddevicename(address, usecache=True): if not _lightbluecommon._isbtaddr(address): raise TypeError("%s is not a valid bluetooth address" % str(address)) if address == gethostaddr(): return _gethostname() device = _IOBluetooth.IOBluetoothDevice.withAddressString_(address) if usecache: name = device.getName() if name is not None: return name # do name request with timeout of 10 seconds result = device.remoteNameRequest_withPageTimeout_(None, 10000) if result == _macutil.kIOReturnSuccess: return device.getName() raise _lightbluecommon.BluetoothError( "Could not find device name for %s" % address)
def findservices(addr=None, name=None, servicetype=None): # This always passes a uuid, to force PyBluez to use BlueZ 'search' instead # of 'browse', otherwise some services won't get found. If you use BlueZ's # <sdptool search> or <sdptool records> sometimes you'll get services that # aren't returned through <sdptool browse> -- I think 'browse' only returns # services with recognised protocols or profiles or something. if servicetype is None: uuid = "0100" # L2CAP -- i.e. pretty much all services elif servicetype == _lightbluecommon.RFCOMM: uuid = "0003" elif servicetype == _lightbluecommon.OBEX: uuid = "0008" else: raise ValueError("servicetype must be RFCOMM, OBEX or None, was %s" % \ servicetype) try: services = bluetooth.find_service(name=name, uuid=uuid, address=addr) except bluetooth.BluetoothError, e: raise _lightbluecommon.BluetoothError(str(e))
def __startevents(self): if self.__eventlistener is not None: raise _lightbluecommon.BluetoothError("socket already listening") self.__eventlistener = self.__createlistener()
def selectdevice(): import _lightblueutil try: result = _lightblueutil.selectDevice() except SymbianError, e: raise _lightbluecommon.BluetoothError(str(e))
def _gethcisock(devid=-1): try: sock = _bluetooth.hci_open_dev(devid) except Exception, e: raise _lightbluecommon.BluetoothError("Cannot access local device: " + str(e))
# Copyright (c) 2009 Bea Lam. All rights reserved.
def gethostclass(): cod = _LightAquaBlue.BBLocalDevice.getClassOfDevice() if cod != -1: return int(cod) raise _lightbluecommon.BluetoothError("Cannot read local device class")
def _gethostname(): name = _LightAquaBlue.BBLocalDevice.getName() if name is not None: return name raise _lightbluecommon.BluetoothError("Cannot read local device name")