Exemplo n.º 1
0
class BluetoothCore:
    
    def __init__(self, hciIndex = 0):
        self.settings = BluenetSettings()
        self.control  = ControlHandler(self)
        self.setup    = SetupHandler(self)
        self.state    = StateHandler(self)
        self.ble      = BleHandler(self.settings, hciIndex)
        
    def shutDown(self):
        self.ble.shutDown()
    
    def setSettings(self, adminKey, memberKey, guestKey, referenceId = "PythonLib", encryptionEnabled=True):
        self.settings.loadKeys(encryptionEnabled, adminKey, memberKey, guestKey, referenceId)
        
        
    def loadSettingsFromFile(self, path):
        fileReader = JsonFileStore(path)
        data = fileReader.getData()
        
        if "admin" not in data:
            raise BluenetBleException(BluenetError.ADMIN_KEY_REQURED)
        if "member" not in data:
            raise BluenetBleException(BluenetError.MEMBER_KEY_REQUIRED)
        if "guest" not in data:
            raise BluenetBleException(BluenetError.GUEST_KEY_REQURED)
        
        self.setSettings(data["admin"], data["member"], data["guest"])
        

    def connect(self, address):
        self.ble.connect(address)
        if self.settings.encryptionEnabled:
            try:
                self.control.getAndSetSessionNone()
            except BluenetBleException as err:
                # the only relevant error here is this one. If it is any other, the Crownstone is in the wrong mode
                if err.type is BleError.COULD_NOT_VALIDATE_SESSION_NONCE:
                    raise err


    def setupCrownstone(self, address, crownstoneId, meshAccessAddress, ibeaconUUID, ibeaconMajor, ibeaconMinor):
        self.connect(address)
        self.setup.setup(crownstoneId, meshAccessAddress, ibeaconUUID, ibeaconMajor, ibeaconMinor)
        self.disconnect()
        
    
    def disconnect(self):
        self.ble.disconnect()
    
    def startScanning(self, scanDuration=3):
        self.ble.startScanning(scanDuration)

    def stopScanning(self):
        self.ble.stopScanning()

    def getCrownstonesByScanning(self, scanDuration=3):
        gatherer = Gatherer()
    
        subscriptionIdValidated = BluenetEventBus.subscribe(Topics.advertisement,             lambda advertisementData: gatherer.handleAdvertisement(advertisementData, True)          )
        subscriptionIdAll       = BluenetEventBus.subscribe(SystemBleTopics.rawAdvertisement, lambda advertisement: gatherer.handleAdvertisement(advertisement.getDictionary(), False) )
    
        self.ble.startScanning(scanDuration=scanDuration)
    
        BluenetEventBus.unsubscribe(subscriptionIdValidated)
        BluenetEventBus.unsubscribe(subscriptionIdAll)
        
        return gatherer.getCollection()

    def isCrownstoneInSetupMode(self, address, scanDuration=3, waitUntilInRequiredMode=False):
        # print("Checking if it is in setup mode, address", address)
        checker = SetupChecker(address, waitUntilInRequiredMode)
        subscriptionId = BluenetEventBus.subscribe(Topics.advertisement, checker.handleAdvertisement)

        self.ble.startScanning(scanDuration=scanDuration)

        BluenetEventBus.unsubscribe(subscriptionId)

        return checker.getResult()

    def isCrownstoneInNormalMode(self, address, scanDuration=3, waitUntilInRequiredMode=False):
        # print("Checking if it is in normal mode, address", address)
        checker = NormalModeChecker(address, waitUntilInRequiredMode)
        subscriptionId = BluenetEventBus.subscribe(Topics.advertisement, checker.handleAdvertisement)

        self.ble.startScanning(scanDuration=scanDuration)

        BluenetEventBus.unsubscribe(subscriptionId)

        return checker.getResult()

    def getRssiAverage(self, address, scanDuration=3):
        # print("Checking if it is in normal mode, address", address)
        checker = RssiChecker(address)
        subscriptionId = BluenetEventBus.subscribe(Topics.advertisement, checker.handleAdvertisement)

        self.ble.startScanning(scanDuration=scanDuration)

        BluenetEventBus.unsubscribe(subscriptionId)

        return checker.getResult()

    def getNearestCrownstone(self, rssiAtLeast=-100, scanDuration=3, returnFirstAcceptable=False, addressesToExclude=[]):
        return self._getNearest(False, rssiAtLeast, scanDuration, returnFirstAcceptable, False, addressesToExclude)
    
    
    def getNearestValidatedCrownstone(self, rssiAtLeast=-100, scanDuration=3, returnFirstAcceptable=False, addressesToExclude=[]):
        return self._getNearest(False, rssiAtLeast, scanDuration, returnFirstAcceptable, True, addressesToExclude)
    
    
    def getNearestSetupCrownstone(self, rssiAtLeast=-100, scanDuration=3, returnFirstAcceptable=False, addressesToExclude=[]):
        return self._getNearest(True, rssiAtLeast, scanDuration, returnFirstAcceptable, True, addressesToExclude)
    

    def _getNearest(self, setup, rssiAtLeast, scanDuration, returnFirstAcceptable, validated, addressesToExclude):
        addressesToExcludeSet = set()
        for data in addressesToExclude:
            if isinstance(data, dict):
                if "address" in data:
                    addressesToExcludeSet.add(data["address"].lower())
                else:
                    raise BluenetException(BluenetError.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 = Topics.advertisement
        if not validated:
            topic = SystemBleTopics.rawAdvertisement
    
        subscriptionId = BluenetEventBus.subscribe(topic, selector.handleAdvertisement)
        
        self.ble.startScanning(scanDuration=scanDuration)
    
        BluenetEventBus.unsubscribe(subscriptionId)
        
        return selector.getNearest()
Exemplo n.º 2
0
class BluetoothCore:
    control = None
    setup = None
    config = None
    state = None
    mesh = None
    ble = None

    def __init__(self, hciIndex=0):
        self.settings = BluenetSettings()
        self.control = ControlHandler(self)
        self.setup = SetupHandler(self)
        self.state = StateHandler(self)
        self.ble = BleHandler(self.settings, hciIndex)

    def shutDown(self):
        self.ble.shutDown()

    def setSettings(self,
                    adminKey,
                    memberKey,
                    guestKey,
                    referenceId="PythonLib",
                    encryptionEnabled=True):
        self.settings.loadKeys(encryptionEnabled, adminKey, memberKey,
                               guestKey, referenceId)

    def loadSettingsFromFile(self, path):
        fileReader = JsonFileStore(path)
        data = fileReader.getData()

        if "admin" not in data:
            raise BluenetBleException(BluenetError.ADMIN_KEY_REQURED)
        if "member" not in data:
            raise BluenetBleException(BluenetError.MEMBER_KEY_REQUIRED)
        if "guest" not in data:
            raise BluenetBleException(BluenetError.GUEST_KEY_REQURED)

        self.setSettings(data["admin"], data["member"], data["guest"])

    def connect(self, address):
        self.ble.connect(address)
        if self.settings.encryptionEnabled:
            try:
                self.control.getAndSetSessionNone()
            except BluenetBleException as err:
                # the only relevant error here is this one. If it is any other, the Crownstone is in the wrong mode
                if err.type is BleError.COULD_NOT_VALIDATE_SESSION_NONCE:
                    raise err

    def setupCrownstone(self, address, crownstoneId, meshAccessAddress,
                        ibeaconUUID, ibeaconMajor, ibeaconMinor):
        self.connect(address)
        self.setup.setup(crownstoneId, meshAccessAddress, ibeaconUUID,
                         ibeaconMajor, ibeaconMinor)
        self.disconnect()

    def disconnect(self):
        self.ble.disconnect()

    def startScanning(self, timeout=3):
        self.ble.startScanning()

    def stopScanning(self):
        self.ble.stopScanning()

    def getNearestCrownstone(self,
                             rssiAtLeast=-100,
                             timeout=3,
                             returnFirstAcceptable=False):
        return self._getNearest(False, rssiAtLeast, timeout,
                                returnFirstAcceptable, False)

    def getNearestValidatedCrownstone(self,
                                      rssiAtLeast=-100,
                                      timeout=3,
                                      returnFirstAcceptable=False):
        return self._getNearest(False, rssiAtLeast, timeout,
                                returnFirstAcceptable, True)

    def getNearestSetupCrownstone(self,
                                  rssiAtLeast=-100,
                                  timeout=3,
                                  returnFirstAcceptable=False):
        return self._getNearest(True, rssiAtLeast, timeout,
                                returnFirstAcceptable, True)

    def _getNearest(self, setup, rssiAtLeast, timeout, returnFirstAcceptable,
                    validated):
        selector = NearestSelector(setup, rssiAtLeast, returnFirstAcceptable)

        topic = Topics.advertisement
        if not validated:
            topic = SystemBleTopics.rawAdvertisement

        subscriptionId = BluenetEventBus.subscribe(
            topic, selector.handleAdvertisement)

        self.ble.startScanning(timeout=timeout)

        BluenetEventBus.unsubscribe(subscriptionId)

        return selector.getNearest()