示例#1
0
    async def _getNearest(self, setup, rssiAtLeast, scanDuration,
                          returnFirstAcceptable, validated,
                          addressesToExclude) -> ScanData or None:
        addressesToExcludeSet = set()
        if addressesToExclude is not None:
            for data in addressesToExclude:
                if hasattr(data, 'address'):
                    addressesToExcludeSet.add(data.address.lower())
                elif isinstance(data, dict):
                    if "address" in data:
                        addressesToExcludeSet.add(data["address"].lower())
                    else:
                        raise CrownstoneException(
                            CrownstoneError.INVALID_ADDRESS,
                            "Addresses to Exclude is either an array of addresses (like 'f7:19:a4:ef:ea:f6') or an array of dicts with the field 'address'"
                        )
                else:
                    addressesToExcludeSet.add(data.lower())

        selector = NearestSelector(setup, rssiAtLeast, returnFirstAcceptable,
                                   addressesToExcludeSet)

        topic = BleTopics.advertisement
        if not validated:
            topic = BleTopics.rawAdvertisement

        subscriptionId = BleEventBus.subscribe(
            topic, lambda scanData: selector.handleAdvertisement(scanData))

        await self.ble.scan(duration=scanDuration)

        BleEventBus.unsubscribe(subscriptionId)

        return selector.getNearest()
示例#2
0
    async def waitForMode(self,
                          address,
                          requiredMode: CrownstoneOperationMode,
                          scanDuration=5):
        """
        This will wait until it has received an advertisement from the Crownstone with the specified address. Once it has received an advertisement, it knows the mode. We will
        scan for the scanDuration amount of seconds or until the Crownstone is in the required mode.

        It can throw the following CrownstoneBleException
        - BleError.NO_SCANS_RECEIVED
            We have not received any scans from this Crownstone, and can't say anything about it's state.
        - BleError.DIFFERENT_MODE_THAN_REQUIRED
            During the {scanDuration} seconds of scanning, the Crownstone was not in the required mode.
        """
        _LOGGER.debug(
            f"waitForMode address={address} requiredMode={requiredMode} scanDuration={scanDuration}"
        )
        checker = ModeChecker(address, requiredMode, True)
        subscriptionId = BleEventBus.subscribe(
            BleTopics.rawAdvertisement,
            lambda scanData: checker.handleAdvertisement(scanData))
        await self.ble.scan(duration=scanDuration)
        BleEventBus.unsubscribe(subscriptionId)
        result = checker.getResult()

        if result is None:
            raise CrownstoneBleException(
                BleError.NO_SCANS_RECEIVED,
                f'During the {scanDuration} seconds of scanning, no advertisement was received from this address.'
            )
        if result != requiredMode:
            raise CrownstoneBleException(
                BleError.DIFFERENT_MODE_THAN_REQUIRED,
                f'During the {scanDuration} seconds of scanning, the Crownstone was not in the required mode..'
            )
示例#3
0
    async def getMode(self,
                      address,
                      scanDuration=3) -> CrownstoneOperationMode:
        """
        This will wait until it has received an advertisement from the Crownstone with the specified address. Once it has received an advertisement, it knows the mode.

        We will return once we know.

        It can throw the following CrownstoneBleException
        - BleError.NO_SCANS_RECEIVED
            We have not received any scans from this Crownstone, and can't say anything about it's state.
        """
        _LOGGER.debug(f"getMode address={address} scanDuration={scanDuration}")
        checker = ModeChecker(address, None)
        subscriptionId = BleEventBus.subscribe(
            BleTopics.rawAdvertisement,
            lambda scanData: checker.handleAdvertisement(scanData))
        await self.ble.scan(duration=scanDuration)
        BleEventBus.unsubscribe(subscriptionId)
        result = checker.getResult()

        if result is None:
            raise CrownstoneBleException(
                BleError.NO_SCANS_RECEIVED,
                f'During the {scanDuration} seconds of scanning, no advertisement was received from this address.'
            )

        return result
示例#4
0
    async def isCrownstoneInSetupMode(self,
                                      address: str,
                                      scanDuration=3,
                                      waitUntilInSetupMode=False) -> bool:
        _LOGGER.warning(
            "isCrownstoneInSetupMode is deprecated. Will be removed in v3. Use either getMode or waitForMode instead."
        )
        """
        This will wait until it has received an advertisement from the Crownstone with the specified address. Once it has received an advertisement, it knows the mode.
        With default value for waitUntilInSetupMode (False), it will return True if the Crownstone is in setup mode, False if it isn't.

        You can use the boolean waitUntilInSetupMode to have it ignore advertisements from this Crownstone in other modes than setup mode.

        It can throw the following CrownstoneBleException
        - BleError.NO_SCANS_RECEIVED
            We have not received any scans from this Crownstone, and can't say anything about it's state.
        """
        _LOGGER.debug(
            f"isCrownstoneInSetupMode address={address} scanDuration={scanDuration} waitUntilInSetupMode={waitUntilInSetupMode}"
        )
        checker = ModeChecker(address, CrownstoneOperationMode.SETUP,
                              waitUntilInSetupMode)
        subscriptionId = BleEventBus.subscribe(BleTopics.advertisement,
                                               checker.handleAdvertisement)
        await self.ble.scan(duration=scanDuration)
        BleEventBus.unsubscribe(subscriptionId)
        result = checker.getResult()

        if result is None:
            raise CrownstoneBleException(
                BleError.NO_SCANS_RECEIVED,
                f'During the {scanDuration} seconds of scanning, no advertisement was received from this address.'
            )

        return result
示例#5
0
 async def getRssiAverage(self, address, scanDuration=3):
     checker = RssiChecker(address)
     subscriptionId = BleEventBus.subscribe(
         BleTopics.rawAdvertisement,
         lambda scanData: checker.handleAdvertisement(scanData))
     await self.ble.scan(duration=scanDuration)
     BleEventBus.unsubscribe(subscriptionId)
     return checker.getResult()
示例#6
0
 async def getCrownstonesByScanning(self, scanDuration=3):
     gatherer = Gatherer()
     subscriptionIdAll = BleEventBus.subscribe(
         BleTopics.rawAdvertisement,
         lambda scanData: gatherer.handleAdvertisement(scanData))
     await self.ble.scan(duration=scanDuration)
     BleEventBus.unsubscribe(subscriptionIdAll)
     return gatherer.getCollection()
示例#7
0
    async def waitForPeripheralToDisconnect(self, timeout: int = 10):
        if self.activeClient is not None:
            if await self.activeClient.isConnected():
                waiting = True

                def disconnectListener(data):
                    nonlocal waiting
                    waiting = False

                listenerId = BleEventBus.subscribe(
                    SystemBleTopics.forcedDisconnect, disconnectListener)

                timer = 0
                while waiting and timer < 10:
                    await asyncio.sleep(0.1)
                    timer += 0.1

                BleEventBus.unsubscribe(listenerId)

                self.activeClient = None
示例#8
0
 async def shutDown(self):
     for subscriptionId in self.subscriptionIds:
         BleEventBus.unsubscribe(subscriptionId)
     await self.disconnect()
     await self.stopScanning()