Beispiel #1
0
    def handleNotification(self, char_handle, data):
        """It is called whenever a notification arises.

        Args:
            char_handle (int): The characteristic's handle to look for.
            data (str): The data notified from the given characteristic.

        Raises:
            :exc:`blue_st_sdk.utils.blue_st_exceptions.InvalidDataException`
                if the data array has not enough data to read.
        """
        try:
            # Calling on-read callback.
            if self._node._debug_console:
                # Calling on-update callback for a debug characteristic.
                characteristic = \
                    self._node._char_handle_to_characteristic_dict[char_handle]
                if Debug.is_debug_characteristic(str(characteristic.uuid)):
                    self._node._debug_console.on_update_characteristic(
                        characteristic, data)
                    return

            # Calling on-read callback for the other characteristics.
            self._node._update_features(char_handle, data, True)

        except InvalidDataException as e:
            self._logger.warning(str(e))
Beispiel #2
0
    def connect(self, user_defined_features=None):
        """Open a connection to the node.

        Args:
            user_defined_features (dict, optional): User-defined feature to be
                added.
        """
        self._update_node_status(NodeStatus.CONNECTING)
        self.add_external_features(user_defined_features)
        super(Node, self).connect(self.get_tag(), self._device.addrType)

        # Getting services.
        services = self.getServices()
        if not services:
            self._update_node_status(NodeStatus.DEAD)
            return

        # Handling Debug, Config, and Feature characteristics.
        for service in services:
            if Debug.is_debug_service(str(service.uuid)):
                # Handling Debug.
                self._debug_console = self._build_debug_console(service)
            #elif Config.is_config_service(str(service.uuid)):
            # Handling Config.
            #    pass
            #else:
            # Getting characteristics.
            characteristics = service.getCharacteristics()
            for characteristic in characteristics:

                # Storing characteristics' handle to characteristic mapping.
                self._char_handle_to_characteristic_dict[
                    characteristic.getHandle()] = characteristic

                # Building characteristics' features.
                if FeatureCharacteristic.is_base_feature_characteristic(
                        str(characteristic.uuid)):
                    self._build_features(characteristic)
                elif FeatureCharacteristic.is_extended_feature_characteristic(
                        str(characteristic.uuid)):
                    self._build_features_known_uuid(characteristic, [
                        FeatureCharacteristic.get_extended_feature_class(
                            characteristic.uuid)
                    ])
                elif bool(self._external_uuid_to_features_dic) \
                    and characteristic.uuid in self._external_uuid_to_features_dic:
                    self._build_features_known_uuid(characteristic, [
                        self._external_uuid_to_features_dic[
                            characteristic.uuid]
                    ])

        # For each feature store a reference to the characteristic offering the
        # feature, useful to enable/disable notifications on the characteristic
        # itself.
        self._set_features_characteristics()

        # Change node's status.
        self._update_node_status(NodeStatus.CONNECTED)
Beispiel #3
0
    def read_feature(self, feature):
        """Synchronous request to read a feature.

        Args:
            feature (:class:`blue_st_sdk.feature.Feature`): The feature to read.

        Raises:
            :exc:`blue_st_sdk.utils.blue_st_exceptions.BlueSTInvalidOperationException`
            is raised if the feature is not enabled or the operation
            required is not supported.
            :exc:`blue_st_sdk.utils.blue_st_exceptions.BlueSTInvalidDataException`
            if the data array has not enough data to read.
        """
        if not feature.is_enabled():
            raise BlueSTInvalidOperationException(' The "' +
                                                  feature.get_name() +
                                                  '" feature is not enabled.')

        characteristic = feature.get_characteristic()
        if not self.characteristic_can_be_read(characteristic):
            raise BlueSTInvalidOperationException(' The "' +
                                                  feature.get_name() +
                                                  '" feature is not readable.')

        # Reading data.
        try:
            with lock(self):
                char_handle = characteristic.getHandle()
                data = self.readCharacteristic(char_handle)

            # Calling on-read callback.
            if self._debug_console and \
                Debug.is_debug_characteristic(str(characteristic.uuid)):
                # Calling on-read callback for a debug characteristic.
                self._debug_console.on_update_characteristic(
                    characteristic, data)
            else:
                # Calling on-read callback for the other characteristics.
                self._update_features(char_handle, data, False)
        except BlueSTInvalidDataException as e:
            raise e
        except BTLEException as e:
            self._unexpected_disconnect()
Beispiel #4
0
    def handleNotification(self, char_handle, data):
        """It is called whenever a notification arises.

        Args:
            char_handle (int): The characteristic's handle to look for.
            data (str): The data notified from the given characteristic.
        """
        try:
            # Calling on-read callback.
            if self._node._debug_console:
                # Calling on-update callback for a debug characteristic.
                characteristic = \
                    self._node._char_handle_to_characteristic_dict[char_handle]
                if Debug.is_debug_characteristic(str(characteristic.uuid)):
                    self._node._debug_console.on_update_characteristic(
                        characteristic, data)
                    return

            # Calling on-read callback for the other characteristics.
            self._node._update_features(char_handle, data, True)
        except BlueSTInvalidDataException as e:
            self._logger.warning(str(e))
        except BTLEException as e:
            self._unexpected_disconnect()
Beispiel #5
0
    def connect(self, user_defined_features=None):
        """Open a connection to the node.

        Please note that there is no supervision timeout API within the SDK,
        hence it is not possible to detect immediately an unexpected
        disconnection; it is detected and notified via listeners as soon as a
        read/write/notify operation is executed on the device (limitation
        intrinsic to the bluepy library).

        Args:
            user_defined_features (dict, optional): User-defined feature to be
            added.

        Returns:
            bool: True if the connection to the node has been successful, False
            otherwise.
        """
        try:
            if not self._status == NodeStatus.IDLE:
                return False

            # Creating a delegate object, which is called when asynchronous
            # events such as Bluetooth notifications occur.
            self.withDelegate(NodeDelegate(self))

            # Connecting.
            self._update_node_status(NodeStatus.CONNECTING)
            self.add_external_features(user_defined_features)
            with lock(self):
                super(Node, self).connect(self.get_tag(),
                                          self._device.addrType)

            # Getting services.
            with lock(self):
                services = self.getServices()
            if not services:
                self.disconnect()
                return False

            # Handling Debug, Config, and Feature characteristics.
            for service in services:
                if Debug.is_debug_service(str(service.uuid)):
                    # Handling Debug.
                    self._debug_console = self._build_debug_console(service)
                #elif Config.is_config_service(str(service.uuid)):
                # Handling Config.
                #    pass
                #else:
                # Getting characteristics.
                with lock(self):
                    characteristics = service.getCharacteristics()
                for characteristic in characteristics:

                    # Storing characteristics' handle to characteristic mapping.
                    with lock(self):
                        self._char_handle_to_characteristic_dict[
                            characteristic.getHandle()] = characteristic

                    # Building characteristics' features.
                    if FeatureCharacteristic.is_base_feature_characteristic(
                            str(characteristic.uuid)):
                        self._build_features(characteristic)
                    elif FeatureCharacteristic.is_extended_feature_characteristic(
                            str(characteristic.uuid)):
                        self._build_features_known_uuid(
                            characteristic, [
                                FeatureCharacteristic.
                                get_extended_feature_class(characteristic.uuid)
                            ])
                    elif bool(self._external_uuid_to_features_dic) \
                        and characteristic.uuid in self._external_uuid_to_features_dic:
                        self._build_features_known_uuid(
                            characteristic, [
                                self._external_uuid_to_features_dic[
                                    characteristic.uuid]
                            ])

            # For each feature store a reference to the characteristic offering the
            # feature, useful to enable/disable notifications on the characteristic
            # itself.
            self._set_features_characteristics()

            # Change node's status.
            self._update_node_status(NodeStatus.CONNECTED)

            return self._status == NodeStatus.CONNECTED
        except BTLEException as e:
            self._unexpected_disconnect()