コード例 #1
0
    def run(self):
        while not self.stop_event.wait(2):
            if not self.scanDelegate.identify_queue.empty(): #check for pending identify command
                delegate = self.scanDelegate.identify_queue.get()
                
                time_wait = .25
                cnt = int(delegate.identify_timeout/time_wait)
                logger.debug('identifying: cnt=' + str(cnt) +', timeout = ' + str(delegate.identify_timeout))
                cmd = '{:02x}'.format(tb_protocol.TB_COMMAND_IDENTIFY)
                for i in range(cnt):
                    f, data = btle_sendcmd(delegate.target_mac, cmd)
                    if f:
                        delegate.identified = True
                        delegate.stop_event.set()
                        #logger.debug('identify succeeded ' + data.hex())
                        logger.debug('identify succeeded ')
                        break
                    if delegate.stop_event.wait(time_wait):
                        break
                self.scanDelegate.identify_queue.task_done()

            scanner = Scanner().withDelegate(self.scanDelegate)
            try:
                scanner.clear()
                scanner.start()
                scanner.process(10)
                scanner.stop()
            except Exception as exc:
                logger.debug('Exception > ' + str(exc))
                pass
        logger.debug('ScannerThread: exit')
コード例 #2
0
ファイル: miScale.py プロジェクト: Wingjam/ReverseMiScale
def MiScale(mac_addr, callback, send_only_stabilized_weight):
    mac_addr = mac_addr.upper()
    scanner = Scanner().withDelegate(ScanDelegate(mac_addr, callback, send_only_stabilized_weight))
    while True:
        scanner.start()
        scanner.process(1)
        scanner.stop()
コード例 #3
0
ファイル: puck-gst-rest-test.py プロジェクト: lekstonjm/puck
 def run(self):
     scanner = Scanner().withDelegate(PuckClickDelegate())
     scanner.start()
     while not self.stop:
         print "coucou"
         scanner.process(10)
     scanner.stop()
コード例 #4
0
ファイル: temp_sensor.py プロジェクト: daviessm/heating
 def find_temp_sensors(sensors):
   TempSensor._scanning_lock.acquire()
   logger.debug('Scanning for devices')
   scanner = Scanner().withDelegate(ScanDelegate())
   try:
     devices = scanner.scan(10.0)
     if sensors is None:
       sensors = {}
     for device in devices:
       if device.addr in sensors:
         continue
       name = ''
       if device.getValueText(9):
         name = device.getValueText(9)
       elif device.getValueText(8):
         name = device.getValueText(8)
       logger.debug('Device name: ' + name)
       if 'SensorTag' in name:
         logger.info('Found SensorTag with address: ' + device.addr)
         sensors[device.addr] = SensorTag(device)
       elif 'MetaWear' in name:
         logger.info('Found MetaWear with address: ' + device.addr)
         sensors[device.addr] = MetaWear(device)
     logger.debug('Finished scanning for devices')
     TempSensor._scanning_lock.release()
     if len(sensors) == 0:
       raise NoTagsFoundException('No sensors found!')
   except BTLEException as e:
     scanner.stop()
     logger.warn('Got exception ' + e.message)
     TempSensor._scanning_lock.release()
   return sensors
コード例 #5
0
def COLLECTOR(timeout):
    global runthegame
    global pmdata
    global playermonitor
    global stopmeplease
    scanner = Scanner().withDelegate(ScanDelegate())

    while True:
        if runthegame:  # 0: rawrssi 1:timestamp 2:lastresult 3: ? 4: item counter 5: KalmanRssi 6:KalmanTime
            pmdata = [
                [0, [[], [], 0, 0, 0, [], []]],
                [1, [[], [], 0, 0, 0, [], []]],
                [2, [[], [], 0, 0, 0, [], []]],
                [3, [[], [], 0, 0, 0, [], []]],
                [4, [[], [], 0, 0, 0, [], []]],
            ]
            playermonitor = []
            scanner.clear()
            scanner.start(passive=True)

            while runthegame:
                most = timer()
                scanner.process(0.1)

                if stopmeplease == True:
                    runthegame = False
                    scanner.stop()
        time.sleep(0.01)
コード例 #6
0
ファイル: btle.py プロジェクト: DeShrike/experiments
    def scan(match=None, duration=5, just_one=False, match_scan_entry=False):
        """This looks through any advertising btle devices for matching ones.

        *** Note you must run this as root ***

        match(scan_data) should return True if scan_data is from the device you're looking for.

            If no match function is provided, it is treated as always returning True (you want
                to see all devices that respond within duration).

            scan_data is a dict mapping description to value, unless match_scan_entry is True
                in which case scan_data is a btle ScanEntry object.

        Duration is how many seconds to scan before returning.

        If just_one is False, scans for the full duration and then
            returns a list of matching ScanEntry objects. (https://ianharvey.github.io/bluepy-doc/scanentry.html)

        If just_one is True, this returns the first match immediately (no list)
            or None after full duration timeout.

        Note (match==None and just_one==True) results in just the first device
            to respond being immediately returned.
        """
        scanner = Scanner().withDelegate(DefaultDelegate())
        scanner.clear()
        scanner.start()
        if not just_one:
            found = []
        try:
            for i in range(max(int(duration * 10),
                               1)):  # Break duration into 10ths
                scanner.process(
                    0.1)  # Handle incoming messages for 1/10th of a second...
                devices = scanner.getDevices()
                for dev in devices:
                    if debug:
                        BtleDevice.dump_scan_entry(dev)
                    if match_scan_entry:
                        params = dev
                    else:
                        params = {
                            name: val
                            for tag, name, val in dev.getScanData()
                        }
                    if match is None or match(params):
                        if just_one:
                            return dev
                        else:
                            found.append(dev)
                scanner.clear()
        finally:
            scanner.stop()

        if just_one:
            return None
        return found
コード例 #7
0
ファイル: switchmate.py プロジェクト: jeffl78/switchmate-1
def status(mac_address):
    print('Looking for switchmate status...')
    sys.stdout.flush()

    scanner = Scanner().withDelegate(ScanDelegate(mac_address))

    scanner.clear()
    scanner.start()
    scanner.process(5)
    scanner.stop()
コード例 #8
0
ファイル: background.py プロジェクト: bjlofton/restswitchmate
 def run(self):
     while True:
         # Do something
         print('Starting Scan Process')
         scanner = Scanner(int(os.environ['SCAN_HCI'])).withDelegate(
             ScanDelegate())
         scanner.clear()
         scanner.start()
         scanner.process(5)
         scanner.stop()
         time.sleep(self.interval)
コード例 #9
0
 def process_message(client, userdata, msg):
     topic = msg.topic.split('/')
     print(msg.topic + " " + str(msg.payload))
     print("  using {}/{}/{} len={}".format(topic[0], topic[1], topic[2],
                                            len(topic)))
     if len(topic) == 3 and topic[0] == 'ble' and topic[
             1] == 'scan' and topic[2] == 'commands':
         print(topic)
         try:
             with ble_map_lock:
                 for v in ble_dev_map.values():
                     v.acquire()
                 print("    starting scan")
                 scanner = Scanner().withDelegate(ScanDelegate())
                 scanner.scan(int(msg.payload))
         except Exception as e:
             client.publish('ble/scanning/error', str(e))
             sleep(12)
         finally:
             with ble_map_lock:
                 for v in ble_dev_map.values():
                     v.release()
             try:
                 scanner.stop()
             except:
                 pass
             sleep(8)
             client.publish(topic=msg.topic,
                            payload=msg.payload,
                            qos=msg.qos,
                            retain=msg.retain)
     elif len(topic) == 3 and topic[0] == 'ble' and topic[2] == 'commands':
         try:
             data = json.loads(msg.payload.decode('utf-8'))
             try:
                 conn = BLEConnection(topic[1])
                 conn.process_commands(data['commands'])
             except Exception as e:
                 print('Error: {}'.format(str(e)))
                 if 'tries' in data:
                     if data['tries'] > 1:
                         data['tries'] -= 1
                         # sleep here to give the BT some rest
                         sleep(10)
                         # then try again
                         client.publish(topic=msg.topic,
                                        payload=json.dumps(data),
                                        qos=msg.qos,
                                        retain=msg.retain)
                         return
         except Exception as e2:
             print('Error: {}'.format(str(e2)))
コード例 #10
0
 def run(self):
     while True:
         try:
             scanner = Scanner().withDelegate(ScanDelegate())
             scanner.scan(20)
         except Exception as e:
             client.publish('ble/scanning/error', str(e))
             sleep(10)
         finally:
             try:
                 scanner.stop()
             except:
                 pass
コード例 #11
0
def main():
    logging.basicConfig(filename='logs/' + __file__ + '.log',
                        level=logging.INFO,
                        format='%(message)s')

    scanner = Scanner(BLE_INTERFACE).withDelegate(ScanDelegate())
    try:
        while True:
            scanner.start()
            scanner.process(timeout=5)
            scanner.stop()
            scanner.clear()
    except KeyboardInterrupt:
        pass
コード例 #12
0
def main():
    parser = argparse.ArgumentParser(
        description="Get Xiaomi Mi Smart Scale 2 weight.")
    parser.add_argument("mac", help="Device MAC address")
    parser.add_argument('--with-units',
                        action='store_true',
                        help="return weight \w units")
    parser.add_argument('--verbose', '-v', action='count', default=0)
    scanner = Scanner().withDelegate(ScanDelegate(parser.parse_args()))

    while True:
        scanner.start()
        scanner.process(2)
        scanner.stop()
コード例 #13
0
 def run(self):
     while True:
         # Do something
         print('Starting Scan Process')
         items = set()
         scanner = Scanner(int(os.environ['SCAN_HCI'])).withDelegate(
             ScanDelegate(items))
         scanner.clear()
         scanner.start()
         scanner.process(5)
         scanner.stop()
         for item in items:
             readnewFirmware(item)
         time.sleep(self.interval)
     sys.exit(
     )  #If the loop exists because of an error, let the process go down and have docker restart it.
コード例 #14
0
ファイル: Scanner.py プロジェクト: rheehot/openwifipass
 def scan(self):
     """
     Scans for PWS advertisements with the given SSID and returns the first match
     """
     logger.info("Start scanning...")
     scanner = Scanner().withDelegate(self)
     scanner.clear()
     scanner.start(passive=True)
     while self.result is None:
         scanner.process(0.1)
     logger.info(f"SSID match in PWS advertisement from {self.result.addr}")
     scanner.stop()
     # return and clear result
     result = self.result
     self.result = None
     return result
コード例 #15
0
ファイル: main.py プロジェクト: danacr/mi-scale-2-fitbit
def main():
    load_dotenv()
    if os.path.isfile('refresh_token'):
        f = open('refresh_token', 'r+')
        os.environ['refresh_token'] = f.read()

    parser = argparse.ArgumentParser(
        description=
        "Get Xiaomi Mi Smart Scale 2 weight, upload to fitbit, and notify using OpsGenie"
    )

    parser.add_argument('--verbose', '-v', action='count', default=0)
    scanner = Scanner().withDelegate(scan.ScanDelegate(parser.parse_args()))
    print("Started Get weight")

    while True:
        scanner.start()
        scanner.process(2)
        scanner.stop()
コード例 #16
0
ファイル: airmentorpro2.py プロジェクト: rex0hk/airmentor
def main():
    
    bluetooth_adr = sys.argv[1].lower()
    hci = sys.argv[2] # hci # to use
    print  "Will follow broadcasts from:",bluetooth_adr
    print  "hci used: ",hci

    while True:
        try:   
            # BTLE UUSB is on hci0, so pass 0 to Scanner
            scanner = Scanner(hci).withDelegate(AirMentorProDelegate(bluetooth_adr))

   	    while(1):
	        scanner.start()
	        scanner.process(1)
	        scanner.stop()

        except:
            pass
コード例 #17
0
def main():

	scanner = Scanner().withDelegate(ScanDelegate())

	# listen for ADV_IND packages for 10s, then exit
	# scanner.scan(10.0, passive=True)
	try:
		# scanner.start(passive=True)
		# lasttime = time()
		# scanner.process(1.0)
		while True:
			# do nothing
			# if(time()-lasttime > 1.0):
			scanner.scan(10.0, passive=True)
			print(".", end=" ")
			sys.stdout.flush()
		# lasttime =time()
	except KeyboardInterrupt:
		scanner.stop()
	print("exiting...")
コード例 #18
0
ファイル: BLEHelper.py プロジェクト: uname/blepi
class BLEHelper(object):
    
    def __init__(self):
        self.scanThread = None
        self.scanner = Scanner().withDelegate(ScanDelegate())
    
    def __scanInThread(self, timeout):
        self.scanThread = threading.Thread(target=self.scanner.scan, args=(timeout,))
        self.scanThread.start()
        return True
        
    def startScan(self, timeout=10):
        if self.scanThread is None:
            return self.__scanInThread(timeout)
        else:
            if self.scanThread.is_alive():
                return False
            else:
                self.scanThread = None
                return self.startScan(timeout)
        
    def stopScan(self):
        self.scanner.stop()
コード例 #19
0
class _StoppableScanner(threading.Thread):
    """Scanner class which can be started and stopped asynchronously.

    Non-thread-safe.

    It is implemented as a thread which checks regularly for the stop
    condition within the :meth:`run()` method; it can be stopped by calling the
    :meth:`stop()` method.
    """

    def __init__(self, show_warnings=False, *args, **kwargs):
        """Constructor.

        Args:
            show_warnings (bool, optional): If True shows warnings, if any, when
            discovering devices not respecting the BlueSTSDK's advertising
            data format, nothing otherwise.
        """
        try:
            super(_StoppableScanner, self).__init__(*args, **kwargs)
            self._stop_called = threading.Event()
            self._process_done = threading.Event()
            with lock(self):
                self._scanner = Scanner().withDelegate(_ScannerDelegate(show_warnings))
        except BTLEException as e:
            # Save details of the exception raised but don't re-raise, just
            # complete the function.
            import sys
            self._exc = sys.exc_info()

    def run(self):
        """Run the thread."""
        self._stop_called.clear()
        self._process_done.clear()
        try:
            with lock(self):
                self._scanner.clear()
                self._exc = None
                self._scanner.start(passive=False)
                while True:
                    #print('.')
                    self._scanner.process(_ScannerDelegate._SCANNING_TIME_PROCESS_s)
                    if self._stop_called.isSet():
                        self._process_done.set()
                        break
 
        except BTLEException as e:
            # Save details of the exception raised but don't re-raise, just
            # complete the function.
            import sys
            self._exc = sys.exc_info()

    def stop(self):
        """Stop the thread."""
        self._stop_called.set()
        while not (self._process_done.isSet() or self._exc):
            pass
        try:
            self._exc = None
            with lock(self):
                self._scanner.stop()
        except BTLEException as e:
            # Save details of the exception raised but don't re-raise, just
            # complete the function.
            import sys
            self._exc = sys.exc_info()

    def join(self):
        """Join the thread.
        
        Raises:
            :exc:`blue_st_sdk.utils.blue_st_exceptions.BlueSTInvalidOperationException`
            is raised if this method is not run as root.
        """
        super(_StoppableScanner, self).join()
        if self._exc:
            msg = '\nBluetooth scanning requires root privilege, ' \
                  'so please run the script with \"sudo\".'
            raise BlueSTInvalidOperationException(msg)
コード例 #20
0
ファイル: BleHandler.py プロジェクト: wickyb94/programmer
class BleHandler:
    
    def __init__(self, settings, hciIndex=0, scanBackend = ScanBackends.Bluepy):
        self.connectedPeripherals = {}

        self.settings = None

        self.connectedPeripherals = {}
        self.connectedPeripheral = None

        self.notificationLoopActive = False
        self.notificationResult = None

        self.scanningActive = False
        self.scanAborted = False

        self.subscriptionIds = []
        
        self.validator = Validator()
        self.settings = settings
        self.hciIndex = hciIndex
        self.scanBackend = scanBackend

        if self.scanBackend == ScanBackends.Aio:
            self.scanner = AioScanner(self.hciIndex).withDelegate(AioScanDelegate(settings))
        else:
            self.scanner = Scanner(self.hciIndex).withDelegate(ScanDelegate(settings))
        self.subscriptionIds.append(BluenetEventBus.subscribe(SystemBleTopics.abortScanning, lambda x: self.abortScanning()))
        
    
    def shutDown(self):
        for subscriptionId in self.subscriptionIds:
            BluenetEventBus.unsubscribe(subscriptionId)
            
        self.validator.shutDown()
    
    
    def connect(self, address):
        if address not in self.connectedPeripherals:
            self.connectedPeripherals[address] = Peripheral(iface=self.hciIndex)
            print("Connecting...")
            self.connectedPeripheral = address
            self.connectedPeripherals[address].connect(address, addrType=ADDR_TYPE_RANDOM, iface=self.hciIndex)
            self.connectedPeripherals[address].getServices()
            print("Connected")
            
    
    def disconnect(self):
        print("Disconnecting... Cleaning up")
        if self.connectedPeripheral:
            self.connectedPeripherals[self.connectedPeripheral].disconnect()
            del self.connectedPeripherals[self.connectedPeripheral]
            self.connectedPeripheral = None
            print("Cleaned up")
    
    
    def startScanning(self, scanDuration=3):
        if not self.scanningActive:
            self.scanningActive = True
            self.scanAborted = False
            if self.scanBackend == ScanBackends.Aio:
                self.scanner.start(scanDuration)
            else:
                self.scanner.start()
                scanTime = 0
                processInterval = 0.5
                while self.scanningActive and scanTime < scanDuration and not self.scanAborted:
                    scanTime += processInterval
                    self.scanner.process(processInterval)

                self.stopScanning()

    def startScanningBackground(self, scanDuration=3):
        Timer(0.0001, lambda: self.startScanning(scanDuration))

    
    def stopScanning(self):
        if self.scanningActive:
            self.scanner.stop()
            self.scanningActive = False
            
    def abortScanning(self):
        if self.scanningActive:
            self.scanAborted = True
            if self.scanBackend == ScanBackends.Aio:
                self.scanner.stop()
    
    def enableNotifications(self):
        print("ENABLE NOTIFICATIONS IS NOT IMPLEMENTED YET")
    
    def disableNotifications(self):
        print("DISABLE NOTIFICATIONS IS NOT IMPLEMENTED YET")

    def writeToCharacteristic(self, serviceUUID, characteristicUUID, content):
        targetCharacteristic = self.getCharacteristic(serviceUUID, characteristicUUID)
        encryptedContent = EncryptionHandler.encrypt(content, self.settings)
        targetCharacteristic.write(encryptedContent, withResponse=True)

    def writeToCharacteristicWithoutEncryption(self, serviceUUID, characteristicUUID, content):
        byteContent = bytes(content)
        targetCharacteristic = self.getCharacteristic(serviceUUID, characteristicUUID)
        targetCharacteristic.write(byteContent, withResponse=True)

    def readCharacteristic(self, serviceUUID, characteristicUUID):
        data = self.readCharacteristicWithoutEncryption(serviceUUID, characteristicUUID)
        if self.settings.isEncryptionEnabled():
            return EncryptionHandler.decrypt(data, self.settings)


    def readCharacteristicWithoutEncryption(self, serviceUUID, characteristicUUID):
        targetCharacteristic = self.getCharacteristic(serviceUUID, characteristicUUID)
        data = targetCharacteristic.read()
        return data



    def getCharacteristics(self, serviceUUID):
        if self.connectedPeripheral:
            peripheral = self.connectedPeripherals[self.connectedPeripheral]

            try:
                service = peripheral.getServiceByUUID(serviceUUID)
            except BTLEException:
                raise BluenetBleException(BleError.CAN_NOT_FIND_SERVICE, "Can not find service: " + serviceUUID)

            characteristics = service.getCharacteristics()

            return characteristics

        else:
            raise BluenetBleException(BleError.CAN_NOT_GET_CHACTERISTIC, "Can't get characteristics: Not connected.")


    def getCharacteristic(self, serviceUUID, characteristicUUID):
        if self.connectedPeripheral:
            peripheral = self.connectedPeripherals[self.connectedPeripheral]
        
            try:
                service = peripheral.getServiceByUUID(serviceUUID)
            except BTLEException:
                raise BluenetBleException(BleError.CAN_NOT_FIND_SERVICE, "Can not find service: " + serviceUUID)
        
            characteristics = service.getCharacteristics(characteristicUUID)
            if len(characteristics) == 0:
                raise BluenetBleException(BleError.CAN_NOT_FIND_CHACTERISTIC, "Can not find characteristic: " + characteristicUUID)

            return characteristics[0]
        
        else:
            raise BluenetBleException(BleError.CAN_NOT_GET_CHACTERISTIC, "Can't get characteristic: Not connected.")
        
        
    def setupSingleNotification(self, serviceUUID, characteristicUUID, writeCommand):
        characteristic = self.getCharacteristic(serviceUUID, characteristicUUID)
        peripheral = self.connectedPeripherals[self.connectedPeripheral]
        
        peripheral.withDelegate(PeripheralDelegate(lambda x: self._killNotificationLoop(x), self.settings))
        
        characteristicCCCDList = characteristic.getDescriptors(forUUID=CCCD_UUID)
        if len(characteristicCCCDList) == 0:
            raise BluenetBleException(BleError.CAN_NOT_FIND_CCCD, "Can not find CCCD handle to use notifications for characteristic: " + characteristicUUID)
        
        characteristicCCCD = characteristicCCCDList[0]
        
        # enable notifications.. This is ugly but necessary
        characteristicCCCD.write(b"\x01\x00", True)
        
        # execute something that will trigger the notifications
        writeCommand()
        
        self.notificationLoopActive = True

        loopCount = 0
        while self.notificationLoopActive and loopCount < 10:
            peripheral.waitForNotifications(0.5)
            loopCount += 1


        if self.notificationResult is None:
            raise BluenetBleException(BleError.NO_NOTIFICATION_DATA_RECEIVED, "No notification data received.")
        
        result = self.notificationResult
        self.notificationResult = None
        
        return result
    
    def setupNotificationStream(self, serviceUUID, characteristicUUID, writeCommand, resultHandler, timeout):
        characteristic = self.getCharacteristic(serviceUUID, characteristicUUID)
        peripheral = self.connectedPeripherals[self.connectedPeripheral]
        
        peripheral.withDelegate(PeripheralDelegate(lambda x: self._loadNotificationResult(x), self.settings))
    
        characteristicCCCDList = characteristic.getDescriptors(forUUID=CCCD_UUID)
        if len(characteristicCCCDList) == 0:
            raise BluenetBleException(BleError.CAN_NOT_FIND_CCCD, "Can not find CCCD handle to use notifications for characteristic: " + characteristicUUID)
    
        characteristicCCCD = characteristicCCCDList[0]
    
        # enable notifications.. This is ugly but necessary
        characteristicCCCD.write(b"\x01\x00", True)
    
        # execute something that will trigger the notifications
        writeCommand()
    
        self.notificationLoopActive = True
        self.notificationResult = None
        
        loopCount = 0
        successful = False
        while self.notificationLoopActive and loopCount < timeout*2:
            peripheral.waitForNotifications(0.5)
            loopCount += 1
            if self.notificationResult is not None:
                command = resultHandler(self.notificationResult)
                self.notificationResult = None
                if command == ProcessType.ABORT_ERROR:
                    self.notificationLoopActive = False
                    raise BluenetBleException(BleError.ABORT_NOTIFICATION_STREAM_W_ERROR, "Aborting the notification stream because the resultHandler raised an error.")
                elif command == ProcessType.FINISHED:
                    self.notificationLoopActive = False
                    successful = True
    
        if not successful:
            raise BluenetBleException(BleError.NOTIFICATION_STREAM_TIMEOUT, "Notification stream not finished within timeout.")
    
        
    def _killNotificationLoop(self, result):
        self.notificationLoopActive = False
        self.notificationResult = result
        
    def _loadNotificationResult(self, result):
        self.notificationResult = result


    def broadcast(self):
        pass
コード例 #21
0
ファイル: central.py プロジェクト: lampi-remote/remote
class CentralManager(DefaultDelegate):

    SCAN_COUNT = 5
    SCAN_INTERVAL = 2.0

    def __init__(self):
        DefaultDelegate.__init__(self)
        self._scanner = Scanner().withDelegate(self)
        self._lamps = []
        self._candidateFound = False
        self.isConnected = False

    def scan(self):
        self.isConnected = False

        # Clear existing connected lamps
        for lamp in self._lamps:
            lamp.disconnect()

        self._lamps = []

        # Scan for new lamps to connect to
        print("Scanning for devices...")

        self._candidateFound = False
        self._scanner.clear()
        self._scanner.start()

        for iter in range(0, CentralManager.SCAN_COUNT):
            self._scanner.process(CentralManager.SCAN_INTERVAL)
            if (self._candidateFound):
                print("Candidate found after {} scan(s). Ending early".format(
                    iter + 1))
                break

        self._scanner.stop()

        scanResult = self._scanner.getDevices()

        # Connect to any lamps found
        for device in scanResult:
            if (Lampi.isLampCandidate(device)):
                lamp = Lampi(device)
                lamp.validate()
                if (lamp.isValid):
                    print("Connected to a lamp with MAC address {}".format(
                        device.addr))
                    self._lamps.append(lamp)
                    self.isConnected = True
                else:
                    lamp.disconnect()

        print("Scan complete")

    def handleDiscovery(self, device, isNew, _):
        if isNew and device.connectable:
            if (Lampi.isLampCandidate(device)):
                self._candidateFound = True
                print(" • Candidate found with MAC address {}".format(
                    device.addr))

    # Discard any lamps that are no longer connected
    def pruneLamps(self):
        for i in range(0, len(self._lamps)):
            lamp = self._lamps[i]
            if (not lamp.isConnected()):
                print("Pruned {}".format(lamp.addr))
                self._lamps.pop(i)
                i -= 1

    def toggleOnOff(self):
        print("Toggling on/off")
        self.pruneLamps()
        for lamp in self._lamps:
            lamp.toggleOnOff()

    def brightnessUp(self):
        print("Sending brightness up")
        self.pruneLamps()
        for lamp in self._lamps:
            lamp.brightnessUp()

    def brightnessDown(self):
        print("Sending brightness down")
        self.pruneLamps()
        for lamp in self._lamps:
            lamp.brightnessDown()

    def preset(self, number):
        print("Starting Preset", str(number))
        self.pruneLamps()
        for lamp in self._lamps:
            lamp.setPreset(number)
コード例 #22
0
class BLEScan():
 bledev = 0
 timeout = 5.0
 scanner = None
 devices = []
 devrssi = []
 lastscan = 0

 def __init__(self,devnum=0,timeout=5.0):
  self.bledev = int(devnum)
  self.timeout = float(timeout)
  self.scanner = None
  self.devices = []
  self.devrssi = []
  self.lastscan = 0
  self._scanning = False
  self.scantime = 10
  self.minsleep = 15
  self.maxsleep = 40

 def stop(self):
    try:
     if self.scanner is not None:
      self.scanner.stop()
    except:
     pass
    self._scanning = False

 def scan(self):
    result = False
    devices = []
    self._scanning = True
    try:
     self.scanner = Scanner(self.bledev)
     devices = self.scanner.scan(self.timeout)
     result = True
     self.lastscan = time.time()
    except Exception as e:
     print("BLE error: ",e)
     self.devices = []
     self.devrssi = []
    self._scanning = False
    tempdev = []
    temprssi = []
    for dev in devices:
      try:
       if self.bledev == int(dev.iface):
        temprssi.append(dev.rssi)
        tempdev.append(str(dev.addr).lower().strip())
      except:
        pass
    self.devices = tempdev
    self.devrrsi = temprssi
    return result

 def isdevonline(self,devaddress):
  return (self.getdevrssi(devaddress) != -100)

 def getdevrssi(self,devaddress):
   try:
    for d in range(len(self.devices)):
     if str(devaddress).lower().strip()==str(self.devices[d]).lower().strip():
      return self.devrrsi[d]
    return -100
   except Exception as e:
    return -100

 def getage(self):
  if self.lastscan==0:
   return -1
  try:
   result = time.time()-self.lastscan
  except:
   result = -1
  return result

 def sniff(self, callback,startwait=0,scantime=10,minsleep=15,maxsleep=40):
    self._scanning = True
    self.scantime = scantime
    self.minsleep = minsleep
    self.maxsleep = maxsleep
    _blestatus = BLEHelper.BLEStatus[self.bledev]
    time.sleep(startwait)
    try:
     if self.timeout==0:
      while self._scanning:
       while _blestatus.norequesters()==False or _blestatus.nodataflows()==False or _blestatus.isscaninprogress():
        time.sleep(0.5)
#       print("scan start")#debug
       _blestatus.reportscan(1)
       try:
        self.scanner = Scanner(self.bledev).withDelegate(SniffDelegate(callback))
       except:
        pass
       self.scanner.clear()
       self.scanner.start(passive=True)
       self.scanner.process(scantime)
       self.scanner.stop()
       _blestatus.reportscan(0)
#       print("scan pause")#debug
       time.sleep(uniform(minsleep,maxsleep))
     else:
      while _blestatus.norequesters()==False or _blestatus.nodataflows()==False or _blestatus.isscaninprogress():
        time.sleep(0.5)
      _blestatus.reportscan(1)
      self.scanner = Scanner(self.bledev).withDelegate(SniffDelegate(callback))
      self.scanner.scan(self.timeout,passive=True)
      _blestatus.reportscan(0)
     self.lastscan = time.time()
    except Exception as e:
     _blestatus.reportscan(0)
    self._scanning = False
コード例 #23
0
 def scan(self):
     scanner = Scanner().withDelegate(ScanDelegate())
     devices = scanner.clear()
     devices = scanner.start()
     data = scanner.process(timeout=10)
     devices = scanner.stop()
コード例 #24
0
class BleHandler:
    scanner = None
    settings = None

    connectedPeripherals = {}
    connectedPeripheral = None

    notificationLoopActive = False
    notificationResult = None

    scanningActive = False
    scanAborted = False

    subscriptionIds = []
    hciIndex = 0

    def __init__(self, settings, hciIndex=0):
        self.connectedPeripherals = {}
        self.validator = Validator()
        self.settings = settings
        self.hciIndex = hciIndex
        self.scanner = Scanner(self.hciIndex).withDelegate(ScanDelegate())
        self.subscriptionIds.append(
            BluenetEventBus.subscribe(SystemBleTopics.abortScanning,
                                      lambda x: self.abortScanning()))

    def shutDown(self):
        for subscriptionId in self.subscriptionIds:
            BluenetEventBus.unsubscribe(subscriptionId)

        self.validator.shutDown()

    def connect(self, address):
        if address not in self.connectedPeripherals:
            self.connectedPeripherals[address] = Peripheral(
                iface=self.hciIndex)
            print("Connecting...")
            self.connectedPeripheral = address
            self.connectedPeripherals[address].connect(address,
                                                       ADDR_TYPE_RANDOM)
            self.connectedPeripherals[address].getServices()
            print("Connected")

    def disconnect(self):
        print("Disconnecting... Cleaning up")
        if self.connectedPeripheral:
            self.connectedPeripherals[self.connectedPeripheral].disconnect()
            del self.connectedPeripherals[self.connectedPeripheral]
            self.connectedPeripheral = None
            print("Cleaned up")

    def startScanning(self, timeout=3):
        if not self.scanningActive:
            self.scanner.start()
            self.scanningActive = True
            self.scanAborted = False
            scanTime = 0
            while self.scanningActive and scanTime < timeout and not self.scanAborted:
                scanTime += 0.5
                self.scanner.process(scanTime)

            self.stopScanning()

    def startScanningBackground(self, timeout=3):
        Timer(0.0001, lambda: self.startScanning(timeout))

    def stopScanning(self):
        if self.scanningActive:
            self.scanner.stop()
            self.scanningActive = False

    def abortScanning(self):
        if self.scanningActive:
            self.scanAborted = True

    def enableNotifications(self):
        print("ENABLE NOTIFICATIONS IS NOT IMPLEMENTED YET")

    def disableNotifications(self):
        print("DISABLE NOTIFICATIONS IS NOT IMPLEMENTED YET")

    def writeToCharacteristic(self, serviceUUID, characteristicUUID, content):
        targetCharacteristic = self._getCharacteristic(serviceUUID,
                                                       characteristicUUID)
        encryptedContent = EncryptionHandler.encrypt(content, self.settings)
        targetCharacteristic.write(encryptedContent, withResponse=True)

    def readCharacteristic(self, serviceUUID, characteristicUUID):
        data = self.readCharacteristicWithoutEncryption(
            serviceUUID, characteristicUUID)
        if self.settings.isEncryptionEnabled():
            return EncryptionHandler.decrypt(data, self.settings)

    def readCharacteristicWithoutEncryption(self, serviceUUID,
                                            characteristicUUID):
        targetCharacteristic = self._getCharacteristic(serviceUUID,
                                                       characteristicUUID)
        data = targetCharacteristic.read()
        return data

    def _getCharacteristic(self, serviceUUID, characteristicUUID):
        if self.connectedPeripheral:
            peripheral = self.connectedPeripherals[self.connectedPeripheral]

            try:
                service = peripheral.getServiceByUUID(serviceUUID)
            except BTLEException:
                raise BluenetBleException(
                    BleError.CAN_NOT_FIND_SERVICE,
                    "Can not find service: " + serviceUUID)

            characteristics = service.getCharacteristics(characteristicUUID)
            if len(characteristics) == 0:
                raise BluenetBleException(
                    BleError.CAN_NOT_FIND_CHACTERISTIC,
                    "Can not find characteristic: " + characteristicUUID)

            return characteristics[0]

        else:
            raise BluenetBleException(
                BleError.CAN_NOT_GET_CHACTERISTIC,
                "Can't get characteristic: Not connected.")

    def setupSingleNotification(self, serviceUUID, characteristicUUID,
                                writeCommand):
        characteristic = self._getCharacteristic(serviceUUID,
                                                 characteristicUUID)
        peripheral = self.connectedPeripherals[self.connectedPeripheral]

        peripheral.withDelegate(
            PeripheralDelegate(lambda x: self._killNotificationLoop(x),
                               self.settings))

        characteristicCCCDList = characteristic.getDescriptors(
            forUUID=CCCD_UUID)
        if len(characteristicCCCDList) == 0:
            raise BluenetBleException(
                BleError.CAN_NOT_FIND_CCCD,
                "Can not find CCCD handle to use notifications for characteristic: "
                + characteristicUUID)

        characteristicCCCD = characteristicCCCDList[0]

        # enable notifications
        characteristicCCCD.write(b"\x01\x00", True)

        # execute something that will trigger the notifications
        writeCommand()

        self.notificationLoopActive = True

        loopCount = 0
        while self.notificationLoopActive and loopCount < 10:
            peripheral.waitForNotifications(0.5)
            loopCount += 1

        if self.notificationResult is None:
            raise BluenetBleException(BleError.NO_NOTIFICATION_DATA_RECEIVED,
                                      "No notification data received.")

        result = self.notificationResult
        self.notificationResult = None

        return result

    def _killNotificationLoop(self, result):
        self.notificationLoopActive = False
        self.notificationResult = result
コード例 #25
0
ファイル: advertising.py プロジェクト: lekstonjm/puck
from bluepy.btle import Scanner, DefaultDelegate


class ScanDelegate(DefaultDelegate):
    def __init__(self):
        DefaultDelegate.__init__(self)

    def handleDiscovery(self, dev, isNewDev, isNewData):
        print "Device %s" % dev.addr
        for (adtype, desc, value) in dev.getScanData():
            print "adtype %s, desc  %s, value %s" % (adtype, desc, value)
        print "---------------"


scanner = Scanner().withDelegate(ScanDelegate())
scanner.clear()
scanner.start()
while True:
    scanner.process(10)
scanner.stop()
コード例 #26
0
def scan(callback,
         devices=None,
         raw=False,
         iface=0,
         reset_timeout=30,
         reset_deadtime=300):
    """Listen for BLE advertising packets from Ruuvitags.

    Args:
        callback: Function which will be called for each received
            Ruuvitag packet.
        devices: List of BT address strings in format "fe:ed:de:ad:be:ef"
            for whitelisting devices. If None, no address filtering is made.
        raw: If False, callback is called with a dictionary with decoded
            values from advertising message, plus "time" and "rssi" keys
            which have the packet arrival time and rssi as values.
            If True, callback is called with a tuple (value, addr, rssi)
            with the value being the raw BLE packet data, addr the BT address
            of the sending device and rssi the received signal strength
            indicator from the BT stack.
        iface: The number part of the BT interface device (0 for
            /dev/hci0 etc.)
        reset_timeout: Time in seconds, after which a reset of the BT
            adapter is made, if no packets are received.
        reset_deadtime: Time in seconds. If a BT reset is made and packets
            are still not arriving, the next reset attempt is made after
            this time has passed.
    """
    if devices:
        dev = [s.lower() for s in devices]
        devices = dev

    recv_event = threading.Event()

    reset_thread = threading.Thread(target=idlereset,
                                    args=(recv_event, reset_timeout,
                                          reset_deadtime))
    reset_thread.daemon = True
    reset_thread.start()

    # Start scanning
    scanner = Scanner(iface).withDelegate(
        ScanDelegate(recv_event, callback, devices, raw))
    scanner.clear()
    scanner.start(passive=True)
    try:
        while True:
            try:
                scanner.process(0)
            except BTLEException:
                try:
                    scanner.stop()
                except BTLEException:
                    scanner._stopHelper()
                    reset_btadapter()
                scanner.clear()
                scanner.start(passive=True)
    except (KeyboardInterrupt, SystemExit):
        pass

    log.info("Stopping scan.")
    scanner.stop()
コード例 #27
0
class BLE_network:
    """
    BLE network class
    < UNDER DEVELOPMENT >
    This class contains of one or multiple peripherals (= device = node = profile). Each of these peripherals can be read from and written to. In addition, if the characteristic supports NOTIFY (notifications), these can also be read.
    
    ...
    
    attributes
    ----------
    All attributes below are read-only.
    - netID
        Network ID
    
    methods
    -------
    - scanning
    scan_for_new_ble_devices(self, device_type, scan_time = 10.0):
        Scan for new ble devices and asks user to add device to ble network
        device_type must be of type string
        scan_time default value is 10.0 seconds
        
    __scan_for_ble_devices(self, device_type, scan_time = 10.0):
        Scan all for all ble devices. It returns a list containing all found ble devices.
        device_type must be of type string.
        scan_time default value is 10.0 seconds
    
    - peripherals
    add_peripherals(self, peripheral_addr, addrType = ADDR_TYPE_PUBLIC, iface = None)
        Add one or mutliple peripherals
        peripheral_addr must be of type str/unicode (one) or list (one or multiple)
        addrType and iface must be the same for all peripherals
    
    delete_peripherals(self, peripheral_addr = None)
        Delete all peripherals or specified peripheral(s) with MAC address peripheral_addr
        peripheral_addr must be of type None (all) str/unicode (one) or list (one or multiple)
   
    get_peripherals(self, peripheral_addr = None)
        Return a list containing the Peripherals of all peripherals or specified peripheral(s)
        peripheral_addr must be of type None (all), str/unicode (one) or list (one or multiple)
    
    
    - Characteristic control
    read_characteristics(self, peripheral = None, service_uuid = None, characteristic_uuid = None)
        Read and save one or multiple characteristics of one or multiple peripherals
        peripheral must be of type None (all), Peripheral (one) or list (one or multiple)
        service_uuid and characteristic_uuid must be of type None (all), str/unicode (one) or list (one or multiple)
        type of return value depends on the characteristic
        
    __read_characteristics_for_one_peripheral(self, peripheral, service_uuid = None, characteristic_uuid = None)
        Read and save characteristics in the memory for one (1) peripheral (currently only printed for debug purposes)
        peripheral must be of type Peripheral
        service_uuid and characteristic_uuid must be of type None (all), str/unicode (one) or list (one or multiple)
        Note: When a service/characteristic is not part of the current peripheral/service, it is ignored

    write_characteristics(self, value, peripheral = None, service_uuid = None, characteristic_uuid = None)
        Write 'value' to one or multiple characteristics of one or multiple peripherals
        value must be of type str
        peripheral must be of type None (all), Peripheral (one) or list (one or multiple)
        service_uuid and characteristic_uuid must be of type None (all), str/unicode (one) or list (one or multiple)
        
    __write_characteristics_for_one_peripheral(self, peripheral, service_uuid = None, characteristic_uuid = None):
        Write 'value' to all, one or multiple characteristics of one (1) peripherals (currently with random values for debug purposes)
        value must be of type str
        peripheral must be of type Peripheral
        service_uuid and characteristic_uuid must be of type None (all), str/unicode (one) or list (one or multiple)
    
    - Delegates
    enable_notifications(self, peripheral = None, characteristic_uuid = None, timeout = 2.0, enable = True)
        Enable/Disable notifications for the specified characteristic(s) on the specified peripheral(s)
        peripheral must be of type None (all), Peripheral (one) or list (one or multiple)
        characteristic must be of type None (all) or str (one)
        timeout has a default value of 2.0 seconds
        To disable, set enable = False
        
    enable_broadcast_data_receive(self, enable = True)
        Enable/Disable receiving of broadcast data
        To disable, set enable = False
    
    receive_broadcast_data(self, timeout = 10)
        If new data is availabe, receive broadcast data (must be enabled before)
        stops when timeout is reached and may be called multiple times when broadcast data is enabled
        this method must be called continuously if broadcastdata can't be missed
        NOTE: _DataScanDelegete.handleDiscovery() is called when data is received
    
    ------

    """
    
    # attributes #
    @property
    def netID(self):
        '''Network ID'''
        return self.__netID
    
    
    # consturctor #
    def __init__(self, network_ID, device_type, scan_time = 10.0):
        '''Initialize a dictionary of peripherals and scan for ble device to add to this network
        network_ID should not be of type None. Any other type is acceptable
        device_type must be of type string
        scan_time default value is 10.0 seconds'''
        
        # network ID and empty peripheral dictionary
        self.__netID = network_ID
        self.__peripherals = {}
        
        # Scan for (new) ble devices
        self.scan_for_new_ble_devices(device_type, scan_time)
        
        
        # my mqtt init
        self.__spms_mqtt_client = spms_mqtt_init()
        
        # Reset broadcastDataReceiveEnabled
        self.__broadcastDataReceiveEnabled = False
        
        
        print('')
        return
    
    # destructor
    def __del__(self):
        '''Delete network with ID x.'''
        print('')
        
        # Disconnnect from alll peripherals
        for addr, p in self.__peripherals.iteritems():
            print("Disconencting from device with MAC address %s ..." %addr)
            p.disconnect()
            print("Disconnecting successfull")
        
        # Terminate connection to cloud
        spms_mqtt_stop(self.__spms_mqtt_client)
        print("Connection with cloud has been terminated.")
        
        # BLE network has been deleted
        print("BLE network '%s' has been deleted." %self.netID)
        return
    
    
    # methods #
    # scanning
    def scan_for_new_ble_devices(self, device_type, scan_time = 10.0):
        '''Scan for new ble devices and asks user to add device to ble network
        device_type must be of type string
        scan_time default value is 10.0 seconds'''
        # Scan for ble devices with name = device_type
        sce_devices = self.__scan_for_ble_devices(device_type, scan_time)
        
        # Check if sce_device is empty (no valid devices found)
        if len(sce_devices) == 0:
            print("No valid devices found (searched for device type: '%s' (uuid=%s)). Make sure the device is turned on and the correct device_type is searched for." %(device_type, getNameByUUID(device_type)))
            print('')
            return
        
        # Only add non duplicates to network
        for sce_device in sce_devices:
            # Check duplicate
            if sce_device.addr in self.__peripherals.keys():
                # Duplicate
                print("Duplicate is ignored (MAC address=%s)." %sce_device.addr)
            else:
                # Non duplicate
                response = raw_input("Do you want to connect to device with MAC address %s? [y/N] " % sce_device.addr).lower()
                if response == "y" or response == "yes": # Accepted connection
                    print("Connecting to device with MAC address %s" % sce_device.addr)
                    self.add_peripherals(sce_device.addr, sce_device.addrType, sce_device.iface)
                else: # Declined connection
                    print("You did not connect to device '%s' with MAC address %s" %(device_type, sce_device.addr))
                    continue #skip this device/peripheral
        
        print('')
        return
    
    def __scan_for_ble_devices(self, device_type, scan_time = 10.0):
        '''Scan all for all ble devices. It returns a list containing all found ble devices.
        device_type must be of type string.
        scan_time default value is 10.0 seconds.'''
        
        # Check if device_type is specified
        if device_type is None:
            print("ERROR while trying to scan for ble devices: device_type is not specified. Please try again.")
            return
        
        scanner = Scanner().withDelegate(_DeviceScanDelegate())
        sc_devices = scanner.scan(scan_time)    # Scan for specified time (in seconds) default = 10.0 seconds

        # Create empty list of sce_devices (objects of ScanEntry class)
        sce_devices = []
        
        for device in sc_devices:
            valid_device = False
            print("Device %s (%s), RSSI=%d dB" % (device.addr, device.addrType, device.rssi))
            
            # Display all adtype, desc and value of current device
            for (adtype, desc, value) in device.getScanData(): # adtype (flag), descriptor, value
                if desc == "Complete Local Name" and value == device_type:
                    print("  %s    %s = %s" % (hex(adtype), desc, value)) # normal print
#                 if desc == "Complete 128b Services" and getNameByUUID(value) == device_type:
#                     print("  %s    %s = %s (uuid=%s)" % (hex(adtype), desc, getNameByUUID(value), value)) # special print
                    
                    valid_device = True;    # Valid device is found (works only for the first device called "Nordic_Blinky"
                    print("Found valid device!")
                    sce_devices.append(device)
                else:
                    print("  %s    %s = %s" % (hex(adtype), desc, value)) # normal print

            # save + print correct device address
            if valid_device:
                print("MAC address valid device: %s\n" %  device.addr)
            else:
                print("Not a valid device!\n")

        return sce_devices
    
    # peripherals
    def add_peripherals(self, peripheral_addr, addrType = ADDR_TYPE_PUBLIC, iface = None):
        '''Add one or mutliple peripherals
        peripheral_addr must be of type str/unicode (one) or list (one or multiple)
        addrType and iface must be the same for all peripherals'''
        
        # Convert to list
        if (isinstance(peripheral_addr, str) or isinstance(peripheral_addr, unicode)):
            peripheral_addr = [peripheral_addr]
            
            
        # Add
        if (isinstance(peripheral_addr, list)):
            # Remove duplicates
            peripheral_addr = list(dict.fromkeys(peripheral_addr))
            
            print("Added peripherals to network with network ID: '%s'" %self.netID)
            for i in range(len(peripheral_addr)):
                no_repeat = False
                no_repeat = self.__peripherals.get(peripheral_addr[i], True)
                
                # Create Preripheral object from scanEntry object + Connect to it
                p_device = Peripheral(peripheral_addr[i], addrType, iface)
                self.__peripherals[peripheral_addr[i]] = p_device
                
                if (no_repeat == True):
                    print("    [new] Added peripheral has MAC address: %s" %peripheral_addr[i])
                else:
                    print("    [update] Updated peripheral has MAC address: %s" %peripheral_addr[i])
        else:
            print("ERROR while trying to add peripherals: peripheral is of wrong type (type = %s). Valid types: Peripheral, list (of Peripheral)" %type(peripheral))
        
        print('')
        return
    
    def delete_peripherals(self, peripheral_addr = None):
        '''Delete all peripherals or specified peripheral(s) with MAC address peripheral_addr
        peripheral_addr must be of type None (all) str/unicode (one) or list (one or multiple)'''
        
        # Convert to list
        if (isinstance(peripheral_addr, str) or isinstance(peripheral_addr, unicode)):
            peripheral_addr = [peripheral_addr]
            
            
        # Delete
        if (peripheral_addr == None):
            # Disable notifications
            self.enable_notifications(enable = False)
            
            for addr, p in self.__peripherals.iteritems():
                print("Disconencting from device with MAC address %s ..." %addr)
                p.disconnect()
                print("Successfully disconnected")
            
            self.__peripherals.clear()
            print("Deleted all peripherals from this network")
        elif (isinstance(peripheral_addr, list)):
            # Remove duplicates
            peripheral_addr = list(dict.fromkeys(peripheral_addr))
            
            for i in range(len(peripheral_addr)):
                p = self.__peripherals.get(peripheral_addr[i], "Not in list")
                if p != "Not in list":
                    # Disable notifications
                    self.enable_notifications(peripheral = p, enable = False)
                    
                    # Disconnect
                    print("Disconencting from device with MAC address %s ..." %peripheral_addr[i])
                    self.__peripherals[peripheral_addr[i]].disconnect()
                    print("Disonnecting successfull")
                    
                    # Delete
                    self.__peripherals.pop(peripheral_addr[i])
                    print("Deleted peripheral with MAC address %s from network" %peripheral_addr[i])
                else:
                    print("peripheral with MAC address %s is not part of this network (network ID = %s)" %(peripheral_addr[i], self.netID))
        else:
            print("ERROR while trying to delete peripherals: peripheral is of wrong type (type = %s). Valid types: None, unicode, str or list (of unicode/str)" %type(peripheral_addr))
        
        print('')
        return
    
    def get_peripherals(self, peripheral_addr = None):
        '''Return a list containing the Peripherals of all peripherals or specified peripheral(s)
        peripheral_addr must be of type None (all), str/unicode (one) or list (one or multiple)'''
        p = []
                
        # Convert to list
        if (isinstance(peripheral_addr, str) or isinstance(peripheral_addr, unicode)):
            peripheral_addr = [peripheral_adddr]
            
        
        # Get
        if (peripheral_addr == None):
            p = self.__peripherals.values()
        elif (isinstance(peripheral_addr, list)):
            # Remove duplicates
            peripheral_addr = list(dict.fromkeys(peripheral_addr))
            
            for i in range(len(peripheral_addr)):
                val = self.__peripherals.get(peripheral_addr[i], "not in list")
                if (val == "not in list"):
                    print("peripheral with MAC address '%s' is not part of this network (network ID = %s)" %s(peripheral_addr[i], self.netID))
                else:
                    p.append(val)
        else:
            print("ERROR while trying to get peripherals: peripheral is of wrong type (type = %s). Valid types: None, unicode, list (of unicode)" %type(peripheral))
        
        return p

    
    # Characteristic control
    def read_characteristics(self, peripheral = None, service_uuid = None, characteristic_uuid = None):
        '''Read and save one or multiple characteristics of one or multiple peripherals
        peripheral must be of type None (all), Peripheral (one) or list (one or multiple)
        service_uuid and characteristic_uuid must be of type None (all), str/unicode (one) or list (one or multiple)
        type of return value depends on the characteristic'''
                
        # Convert to list
        if peripheral is None:
            peripheral = self.__peripherals.values()
        elif isinstance(peripheral, Peripheral):
            peripheral = [peripheral]
            
        
        # Read
        if (isinstance(peripheral, list)):
            # Remove duplicates
            peripheral = list(dict.fromkeys(peripheral))
            
            for i in range(len(peripheral)):
                addr = self.__peripherals.get(peripheral[i].addr, "not in list")
                if (addr == "not in list"):
                    print("peripheral with MAC address %s is not part of this network (network ID = %s)" %(peripheral[i].addr, self.netID))
                    print("characteristic(s) for this peripheral will not be read")
                else:
                    # read characteristics
                    self.__read_characteristics_for_one_peripheral(peripheral[i], service_uuid, characteristic_uuid)
        else:
            print("ERROR while trying to save characteristics: peripheral is of wrong type (type = %s). Valid type: None, Peripheral or list" %type(peripheral))
        
        print('')
        return
    
    def __read_characteristics_for_one_peripheral(self, peripheral, service_uuid = None, characteristic_uuid = None):
        '''Read and save characteristics in the memory for one (1) peripheral (currently only printed for debug purposes)
        peripheral must be of type Peripheral
        service_uuid and characteristic_uuid must be of type None (all), str/unicode (one) or list (one or multiple)
        Note: When a service/characteristic is not part of the current peripheral/service, it is ignored'''
        
        # Convert to list
        if service_uuid is None:
            service_uuid = []
            for service in peripheral.getServices():
                service_uuid.append(service.uuid)
        elif isinstance(service_uuid, str) or isinstance(service_uuid, unicode):
            service_uuid = [service_uuid]
        elif not isinstance(service_uuid, list):
            print("ERROR while trying to save characteristics: service_uuid is of wrong type (type = %s). Valid types: None, str, unicode or list" %type(service_uuid))
            return
        
        # Convert to list
        if characteristic_uuid is None:
            characteristic_uuid = []
            for characteristic in peripheral.getCharacteristics():
                characteristic_uuid.append(characteristic.uuid)
        elif isinstance(characteristic_uuid, str) or isinstance(characteristic_uuid, unicode):
            characteristic_uuid = [characteristic_uuid]
        elif not isinstance(characteristic_uuid, list):
            print("ERROR while trying to save characteristics: characteristic_uuid is of wrong type (type = %s). Valid types: None, str, unicode or list" %type(characteristic_uuid))
            return
        
        if not isinstance(peripheral, Peripheral):
            print("ERROR while trying to save characteristics: peripheral is of wrong type (type = %s). Valid type: Peripheral" %type(peripheral))
            return
        
        # Remove duplicates
        service_uuid = list(dict.fromkeys(service_uuid))
        characteristic_uuid    = list(dict.fromkeys(characteristic_uuid))
        
        
        # Print device address
        print("Services and Charactertic uuids of device '%s':" %peripheral.addr)

        
        # Get services
        for se_service in peripheral.getServices():
            if (se_service.uuid not in service_uuid):
                continue    # Skip this sevice
            
            chars = False                # More than 0 characteristics?
            firstCharacteristic = True             # Fisrt characteristic?
            
            # Save characteristics
            for ch_characteristic in se_service.getCharacteristics():
                chars = True
                
                if (ch_characteristic.uuid not in characteristic_uuid):
                    continue;    # Skip this characteristic
                
                if firstCharacteristic:
                    # Print current service
                    print("Service:")
                    uuid = se_service.uuid
                    print(getNameByUUID(uuid))
                    print("(uuid=%s)" %uuid)

                    print("    Characteristics:")
                    firstCharacteristic = False
                
                # Print current characteristic
                uuid = ch_characteristic.uuid
                characteristic_name = getNameByUUID(uuid)
                print("    %s" %characteristic_name)
                print("      (uuid=%s)" %uuid)
                
                
                # Show properties
                print("      %s" %ch_characteristic.propertiesToString())
                        
                # Read characteristic if it supports read
                if (ch_characteristic.supportsRead() and characteristic_name != "Battery Level"):
                    # Characteristic is readable => Read + print value
                    val = ch_characteristic.read()
                    data = binascii.b2a_hex(val)
                    print("        Current value: %s" % data)
                    if data[-1:] >= "77": # isReady == 0xFF --> is ready to read
                        # Send data to cloud
                        print("        Value: %s" % data)
                        
                        # Only send to cloud when its spms data
                        inDict = spms_ble_names.get(str(uuid), "Not in dict")
                        
                        if inDict is not "Not in dict":
                            print_ble_data(data, "spms", "LITTLE_ENDIAN")
                            
                            temp     = float.fromhex(data[8:12])/100
                            humid    = float.fromhex(data[12:16])/100
                            pressure = float.fromhex(data[16:20])
                            
                            print(temp, humid, pressure)
                            
                            spms_mqtt_send_data(self.__spms_mqtt_client, temp, humid, pressure)
                            #save_data(peripheral.addr, val)
                        
                        # Print that data is saved
                        print("        Saved! (LBS=%s)" % binascii.b2a_hex(data[-1:]))
                    else: # ignore read value, because isRead = 0x00 (< 0x77) --> is not ready to read
                        print("        Ignored! (LBS=%s)" % binascii.b2a_hex(data[-1:]))

                else:
                    # Not readable
                    print("        Characteristic '%s' (uuid=%s) is not readble" %(getNameByUUID(ch_characteristic.uuid), ch_characteristic.uuid))

            if (chars is False):
                print("    Service '%s' (uiid=%s) has no characteristics" %(getNameByUUID(se_service.uuid), se_service.uuid))
            print('')
            
        return
    
    def write_characteristics(self, value, peripheral = None, service_uuid = None, characteristic_uuid = None):
        '''Write 'value' to one or multiple characteristics of one or multiple peripherals
        value must be of type str
        peripheral must be of type None (all), Peripheral (one) or list (one or multiple)
        service_uuid and characteristic_uuid must be of type None (all), str/unicode (one) or list (one or multiple)'''
        
        # Check type of value
        if not isinstance(value, str):
            print("ERROR while trying to write characteristics: value (%s) is of wrong type (type = %s). Valid type: int or str" %(value, type(value)))
            print('')
            return
        
        # Convert to list
        if peripheral is None:
            peripheral = self.__peripherals.values()
        elif isinstance(peripheral, Peripheral):
            peripheral = [peripheral]
            
        
        # Write
        if (isinstance(peripheral, list)):
            # Remove duplicates
            peripheral = list(dict.fromkeys(peripheral))
            
            for i in range(len(peripheral)):
                addr = self.__peripherals.get(peripheral[i].addr, "not in list")
                if (addr == "not in list"):
                    print("peripheral with MAC address %s is not part of this network (network ID = %s)" %(peripheral[i].addr, self.netID))
                    print("characteristic(s) for this peripheral will not be written")
                else:
                    # write characteristics
                    self.__write_characteristics_for_one_peripheral(value, peripheral[i], service_uuid, characteristic_uuid)
        else:
            print("ERROR while trying to write characteristics: peripheral is of wrong type (type = %s). Valid type: None, Peripheral or list" %type(peripheral))
        
        print('')
        return
    
    def __write_characteristics_for_one_peripheral(self, value, peripheral, service_uuid = None, characteristic_uuid = None):
        '''Write 'value' to all, one or multiple characteristics of one (1) peripherals (currently with random values for debug purposes)
        value must be of type str
        peripheral must be of type Peripheral
        service_uuid and characteristic_uuid must be of type None (all), str/unicode (one) or list (one or multiple)'''
        
        # Convert to list
        if service_uuid is None:
            service_uuid = []
            for service in peripheral.getServices():
                service_uuid.append(service.uuid)
        elif isinstance(service_uuid, str) or isinstance(service_uuid, unicode):
            service_uuid = [service_uuid]
        elif not isinstance(service_uuid, list):
            print("ERROR while trying to write characteristics: service_uuid is of wrong type (type = %s). Valid types: None, str, unicode or list" %type(service_uuid))
            return
        
        # Convert to list
        if characteristic_uuid is None:
            characteristic_uuid = []
            for characteristic in peripheral.getCharacteristics():
                characteristic_uuid.append(characteristic.uuid)
        elif isinstance(characteristic_uuid, str) or isinstance(characteristic_uuid, unicode):
            characteristic_uuid = [characteristic_uuid]
        elif not isinstance(characteristic_uuid, list):
            print("ERROR while trying to save characteristics: characteristic_uuid is of wrong type (type = %s). Valid types: None, str, unicode or list" %type(characteristic_uuid))
            return
        
        if not isinstance(peripheral, Peripheral):
            print("ERROR while trying to save characteristics: peripheral is of wrong type (type = %s). Valid type: Peripheral" %type(peripheral))
            return
        
        # Remove duplicates
        service_uuid = list(dict.fromkeys(service_uuid))
        characteristic_uuid    = list(dict.fromkeys(characteristic_uuid))
        
        
        # Print device address
        print("Services and Charactertic uuids of device '%s':" %peripheral.addr)

        
        # Get services
        for se_service in peripheral.getServices():
            if (se_service.uuid not in service_uuid):
                continue    # Skip this sevice
            
            chars = False                # More than 0 characteristics?
            firstCharacteristic = True             # Fisrt characteristic?
            
            # Save characteristics
            for ch_characteristic in se_service.getCharacteristics():
                chars = True
                
                if (ch_characteristic.uuid not in characteristic_uuid):
                    continue;    # Skip this characteristic
                
                if firstCharacteristic:
                    # Print current service
                    print("Service:")
                    uuid = se_service.uuid
                    print(getNameByUUID(uuid))
                    print("(uuid=%s)" %uuid)

                    print("    Characteristics:")
                    firstCharacteristic = False
                
                # Print current characteristic
                uuid = ch_characteristic.uuid
                characteristic_name = getNameByUUID(uuid)
                print("    %s" %characteristic_name)
                print("      (uuid=%s)" %uuid)
                
                
                # Show properties
                print("      %s" %ch_characteristic.propertiesToString())
                        
                # Write characteristic if it supports writing
                if (ch_characteristic.properties & ch_characteristic.props["WRITE"]):
                    # Characteristic is readable => Write + print written value
                    ch_characteristic.write(value)
                    print("        Written value: %s" %repr(value))
                else:
                    # Not readable
                    print("        Characteristic '%s' (uuid=%s) is not writable" %(getNameByUUID(ch_characteristic.uuid), ch_characteristic.uuid))
        
        return
    
    # Delegate
    def enable_notifications(self, peripheral = None, characteristic_uuid = None, timeout = 2.0, enable = True):
        '''Enable/Disable notifications for the specified characteristic(s) on the specified peripheral(s)
        peripheral must be of type None (all), Peripheral (one) or list (one or multiple)
        characteristic must be of type None (all) or str (one)
        timeout has a default value of 2.0 seconds
        To disable, set enable = False'''
            
        # Convert to peripheral list
        if peripheral is None:
            peripheral = self.__peripherals.values()
        elif isinstance(peripheral, Peripheral):
            peripheral = [peripheral]
            
        
        # Handle notifications
        if (isinstance(peripheral, list)):
            # Remove duplicates
            peripheral = list(dict.fromkeys(peripheral))
            
            for i in range(len(peripheral)):
                addr = self.__peripherals.get(peripheral[i].addr, "not in list")
                if (addr == "not in list"):
                    print("peripheral with MAC address %s is not part of this network (network ID = %s)" %(peripheral[i].addr, self.netID))
                    print("Notifications for this peripheral will not be enabled")
                else:
                    # Convert to characteristic list
                    if (characteristic_uuid is None or isinstance(characteristic_uuid, str)):
                        ch_characteristics = peripheral[i].getCharacteristics(uuid = characteristic_uuid)
                        for j in range(len(ch_characteristics)):
                           if (ch_characteristics[j].properties & ch_characteristics[j].props["NOTIFY"] and ch_characteristics[j].uuid != "00002a19-0000-1000-8000-00805f9b34fb"):
                                handle = ch_characteristics[j].getHandle()
                                currently_disabled = peripheral[i].readCharacteristic(handle + 1)
                                currently_disabled = binascii.b2a_hex(currently_disabled)
                                
                                if enable:
                                    if currently_disabled:
                                        # with _NotifyDelegate
                                        peripheral[i].withDelegate(_NotifyDelegate())
                        
                                        # Enable notifications
                                        peripheral[i].writeCharacteristic(handle + 1, b"\x01\x00", True)
                                        print("Notifications enabled for characteristic %s on peripheral %s" %(ch_characteristics[j].uuid, peripheral[i].addr))
                                    else:
                                        print("Notifications are already enabled for characteristic %s on peripheral %s" %(ch_characteristics[j].uuid, peripheral[i].addr))
                                else:
                                    if currently_disabled:
                                        # Disable notifications
                                        peripheral[i].writeCharacteristic(handle + 1, b"\x00\x00", True)
                                        print("Notifications disabled for characteristic %s on peripheral %s" %(ch_characteristics[j].uuid, peripheral[i].addr))
                                    else:
                                        print("Notifications are already disabled for characteristic %s on peripheral %s" %(ch_characteristics[j].uuid, peripheral[i].addr))
                    else:
                        print("ERROR while trying to enable notifications: characteristic_uuid is of wrong type (type = %s). Valid type: None or str" %type(characteristic_uuid))
        else:
            print("ERROR while trying to enable notifications: peripheral is of wrong type (type = %s). Valid type: None, Peripheral or list" %type(peripheral))
        
        print('')
        return
        
        
    def enable_broadcast_data_receive(self, enable = True):
        '''Enable/Disable receiving of broadcast data
        To disable, set enable = False'''
        
        # Enable/Disable
        if enable == True and self.__broadcastDataReceiveEnabled == False:
            self.broadcastDataReceiveScanner = Scanner().withDelegate(_DataScanDelegate())
            self.broadcastDataReceiveScanner.start()
            self.__broadcastDataReceiveEnabled = True
            print("Broadcast data receive is enabled.")
        elif enable == False and self.__broadcastDataReceiveEnabled == True:
            self.broadcastDataReceiveScanner.stop()
            self.__broadcastDataReceiveEnabled = False
            print("Broadcast data receive is disabled.")
                    
        print('')
        return
    
    def receive_broadcast_data(self, timeout = 10):
        '''If new data is availabe, receive broadcast data (must be enabled before)
        stops when timeout is reached and may be called multiple times when broadcast data is enabled
        this method must be called continuously if broadcastdata can't be missed
        NOTE: _DataScanDelegete.handleDiscovery() is called when data is received'''
        
        if self.__broadcastDataReceiveEnabled == True:
            self.broadcastDataReceiveScanner.process(timeout = timeout)
            print('')
            print("Checking for new broadcast data...")
        else:
            print("ERROR: Braodcast receive is not enabled. Enabled with: BLE_network.enable_broadcast_data_receive(enable = True).")
            print('')
        
        return