Example #1
0
    def extract_data(self, timestamp, data, offset):
        """Extract the data from the feature's raw data.
        
        Args:
            timestamp (int): Data's timestamp.
            data (str): The data read from the feature.
            offset (int): Offset where to start reading data.
        
        Returns:
            :class:`blue_st_sdk.feature.ExtractedData`: Container of the number
            of bytes read and the extracted data.

        Raises:
            :exc:`blue_st_sdk.utils.blue_st_exceptions.InvalidDataException`
                if the data array has not enough data to read.
        """
        if len(data) - offset < self.DATA_LENGTH_BYTES:
            raise InvalidDataException(
                'There are no %s bytes available to read.' \
                % (self.DATA_LENGTH_BYTES))
        sample = Sample(
            [LittleEndian.bytes_to_int16(data, offset) / self.SCALE_FACTOR,
             LittleEndian.bytes_to_int16(data, offset + 2) / self.SCALE_FACTOR,
             LittleEndian.bytes_to_int16(data, offset + 4) / self.SCALE_FACTOR],
            self.get_fields_description(),
            timestamp)
        return ExtractedData(sample, self.DATA_LENGTH_BYTES)
    def extract_data(self, timestamp, data, offset):
        """Extract the audio sync data from the feature's raw data.
           In this case it reads a short integer (adpcm_index) and an integer
           (adpcm_predsample).

        Args:
            data (bytearray): The data read from the feature (a 6 bytes array).
            offset (int): Offset where to start reading data (0 by default).
        
        Returns:
            :class:`blue_st_sdk.feature.ExtractedData`: Container of the number
            of bytes read (6)  and the extracted data (audio sync info, a short
            and an int).

        Raises:
            :exc:`blue_st_sdk.utils.blue_st_exceptions.InvalidDataException`
                if the data array has not enough data to read.
        """
        if len(data) != self.DATA_LENGTH_BYTES:
            raise InvalidDataException(
                'There are no %d bytes available to read.' \
                % (self.DATA_LENGTH_BYTES))

        sample = Sample([
            LittleEndian.bytes_to_int16(data, 0),
            LittleEndian.bytes_to_int32(data, 2)
        ], self.get_fields_description(), None)
        return ExtractedData(sample, self.DATA_LENGTH_BYTES)
    def load_file(self, firmware_file):
        """Starts to upload the firmware.

        Args:
            firmware_file (:class:`blue_st_sdk.firmware_upgrade.utils.firmware_file.FirmwareFile`):
                Firmware file.

        Raises:
            :exc:`OSError` if the file is not found or is inaccessible.
            :exc:`ValueError` if the firmware file can not be read properly.
        """
        try:
            # Setting the firmware file.
            self._firmware_file = firmware_file

            # Computing the CRC of the firmware file content.
            self._firmware_crc = self._firmware_file.get_crc_32()

            # Creating the command to start the firmware upgrade.
            command = bytearray(self.FIRMWARE_UPGRADE_COMMAND) \
                + bytearray(LittleEndian.uint32_to_bytes(
                    self._firmware_file.get_size())) \
                + bytearray(LittleEndian.uint32_to_bytes(
                    self._firmware_crc))
        except (OSError, ValueError) as e:
            raise e

        # Opening the firmware file to send data packets.
        self._firmware_fd = self._firmware_file.open()

        # Starting the firmware upgrade.
        self._loading_file_status = LoadingFileStatus.CRC_CHECK
        self._firmware_upgrade_console._debug_console.write(command)
    def extract_data(self, timestamp, data, offset):
        """Extract the data from the feature's raw data.
        In this case it reads a 16-bit signed integer value.

        Args:
            timestamp (int): Data's timestamp.
            data (str): The data read from the feature.
            offset (int): Offset where to start reading data.
        
        Returns:
            :class:`blue_st_sdk.feature.ExtractedData`: Container of the number
            of bytes read and the extracted data.

        Raises:
            :exc:`blue_st_sdk.utils.blue_st_exceptions.BlueSTInvalidDataException`
                if the data array has not enough data to read.
        """
        if (len(data) - offset < self.DATA_LENGTH_BYTES):
            raise BlueSTInvalidDataException(
                'There are no %d bytes available to read.' \
                % (self.DATA_LENGTH_BYTES))

        offset = offset
        flags = data[offset]
        offset += 1

        if self.has8BitHeartRate(flags):
            hr = data[offset]
            offset += 1
        else:
            hr = LittleEndian.bytes_to_uint16(data, offset)
            offset += 2

        if self.hasEnergyExpended(flags):
            ee = LittleEndian.bytes_to_uint16(data, offset)
            offset += 2
        else:
            ee = -1

        if self.hasRRInterval(flags):
            rri = LittleEndian.bytes_to_uint16(data, offset) / 1024.0
            offset += 2
        else:
            rri = float('nan')

        return ExtractedData(
            Sample(timestamp, [hr, ee, rri], getFieldsDescription()),
            offset - offset)
Example #5
0
    def extract_data(self, timestamp, data, offset):
        """Extract the data from the feature's raw data.
        
        Args:
            timestamp (int): Data's timestamp.
            data (str): The data read from the feature.
            offset (int): Offset where to start reading data.
        
        Returns:
            :class:`blue_st_sdk.feature.ExtractedData`: Container of the number
            of bytes read and the extracted data.

        Raises:
            :exc:`blue_st_sdk.utils.blue_st_exceptions.BlueSTInvalidDataException`
                if the data array has not enough data to read.
        """
        if len(data) - offset < self.DATA_LENGTH_BYTES:
            raise BlueSTInvalidDataException(
                'There are no %d bytes available to read.' \
                % (self.DATA_LENGTH_BYTES))
        sample = None
        value = LittleEndian.bytes_to_uint16(data, offset)
        if self._is_low_range_sensor(value):
            sample = self._get_low_range_sample(timestamp, value)
        else:
            sample = self._get_high_range_sample(timestamp, value)
        return ExtractedData(sample, self.DATA_LENGTH_BYTES)
Example #6
0
    def _update_features(self, char_handle, data, notify_update=False):
        """Update the features related to a given characteristic.

        Args:
            char_handle (int): The characteristic's handle to look for.
            data (str): The data read from the given characteristic.
            notify_update (bool, optional): If True all the registered listeners
            are notified about the new data.

        Returns:
            bool: True if the characteristic has some features associated to it
            and they have been updated, False otherwise.

        Raises:
            :exc:`blue_st_sdk.utils.blue_st_exceptions.BlueSTInvalidDataException`
            if the data array has not enough data to read.
        """
        # Getting the features corresponding to the given characteristic.
        features = self._get_corresponding_features(char_handle)
        if features is None:
            return False

        # Computing the timestamp.
        timestamp = self._unwrap_timestamp.unwrap(
            LittleEndian.bytes_to_uint16(data))

        # Updating the features.
        offset = TIMESTAMP_OFFSET_BYTES  # Timestamp sixe in bytes.
        try:
            for feature in features:
                offset += feature.update(timestamp, data, offset,
                                         notify_update)
        except BlueSTInvalidDataException as e:
            raise e
        return True
Example #7
0
    def _update_features(self, char_handle, data, notify_update=False):
        """Update the features related to a given characteristic.

        Args:
            char_handle (int): The characteristic's handle to look for.
            data (str): The data read from the given characteristic.
            notify_update (bool, optional): If True all the registered listeners
                are notified about the new data.

        Returns:
            bool: True if the characteristic has some features associated to it
            and they have been updated, False otherwise.
        """
        # Getting the features corresponding to the given characteristic.
        features = self._get_corresponding_features(char_handle)
        if features is None:
            return False

        # Computing the timestamp.
        timestamp = self._unwrap_timestamp.unwrap(
            LittleEndian.bytesToUInt16(data))

        # Updating the features.
        offset = TIMESTAMP_OFFSET_BYTES  # Timestamp's bytes.
        for feature in features:
            offset += feature.update(timestamp, data, offset, notify_update)
        return True
Example #8
0
 def on_update(self, feature, sample):
     global n_idx
     ###Audio Stream#################################################
     global stream
     ###Audio Stream#################################################
     ###Save Audio File##############################################
     global audioFile
     global save_audio_flag
     ###Save Audio File##############################################
     if isinstance(feature, FeatureAudioADPCM):
         shortData = sample._data
         if len(shortData) != 0:
             for d in shortData:
                 byteData = LittleEndian.int16_to_bytes(d)
                 ###Save Audio File######################################
                 if save_audio_flag == 'y' or save_audio_flag == 'Y':
                     audioFile.write(byteData)
                 ###Save Audio File######################################
                 ###Audio Stream#########################################
                 stream.write(byteData)
                 ###Audio Stream#########################################
             n_idx += 1
     elif isinstance(feature, FeatureAudioOpus):
         if sample is not None:
             byteData = sample._data
             if byteData is not None and len(byteData) != 0:
                 ###Save Audio File######################################
                 if save_audio_flag == 'y' or save_audio_flag == 'Y':
                     audioFile.write(byteData)
                 ###Save Audio File######################################
                 ###Audio Stream#########################################
                 stream.write(byteData)
                 ###Audio Stream#########################################
                 n_idx += 1
    def extract_data(self, timestamp, data, offset):
        """Extract the data from the feature's raw data.

        Args:
            timestamp (int): Data's timestamp.
            data (str): The data read from the feature.
            offset (int): Offset where to start reading data.

        Returns:
            :class:`blue_st_sdk.feature.ExtractedData`: Container of the number
            of bytes read and the extracted data.

        Raises:
            :exc:`Exception` if the data array has not enough data to read.
        """

        if len(data) - offset < self.DATA_LENGTH_BYTES:
            raise Exception('There are no %s bytes available to read.' \
                % (self.DATA_LENGTH_BYTES))

        x = LittleEndian.bytesToFloat(data, offset)
        y = LittleEndian.bytesToFloat(data, offset + 4)
        z = LittleEndian.bytesToFloat(data, offset + 8)

        read_bytes = self.DATA_LENGTH_BYTES

        if len(data) - offset > self.DATA_LENGTH_BYTES:
            w = LittleEndian.bytesToFloat(data, offset + 12)
            read_bytes = 16

            norm = math.sqrt(x*x + y*y + z*z + w*w)

            x /= norm
            y /= norm
            z /= norm
            w /= norm
        else:
            w = math.sqrt(1 - (x*x + y*y + z*z))

        sample = Sample(
            [x, y, z, w],
            self.get_fields_description(),
            timestamp)

        return ExtractedData(sample, read_bytes)
Example #10
0
    def update(self, data):
        """Update the value of the CRC.

        Size of data in bytes must be multiple of 4.

        Args:
            data (bytearray): Data to compute the CRC value of.

        Raises:
            :exc:`ValueError` if the length of the data is not multiple of 4.
        """
        if len(data) % 4 != 0:
            raise ValueError('Size of data to compute the CRC on must be \
                multiple of 4 [bytes].')

        for i in range(0, len(data), 4):
            tmp = LittleEndian.bytes_to_int32(data, i * 4)
            self._current_crc = self._crc32_fast(self._current_crc, tmp)
Example #11
0
    def on_stdout_receive(self, debug_console, message):
        """Called whenever a message is received on the standard output.

        A message is received on the standard output in two cases:
          + When the device sends back the CRC received from the gateway.
          + When the device sends an ACK or a NACK message after receiving the
            firmware file and comparing the CRC computed on it with the CRC
            previously received from the gateway.

        Args:
            debug_console (object): Console that sends the message.
            message (str): The message received on the stdout console.

        Raises:
            :exc:`NotImplementedError` if the method has not been implemented.
        """
        if self._loading_file_status == LoadingFileStatus.CRC_CHECK:
            # Check whether the message received from the node contains the same
            # CRC code that we have sent.
            if message.encode('ISO-8859-1') != \
                LittleEndian.uint32_to_bytes(self._firmware_crc):
                self._on_load_error(FirmwareUpgradeError.TRANSMISSION_ERROR)

            # Sending firmware in blocks of packets.
            self._loading_file_status = LoadingFileStatus.ACK_CHECK
            self._number_of_packets_received = 0
            while self._firmware_file.get_size() - self._bytes_sent > 0:
                if not self._send_block():
                    self._on_load_error(
                        FirmwareUpgradeError.CORRUPTED_FILE_ERROR)
                    break

        elif self._loading_file_status == LoadingFileStatus.ACK_CHECK:
            # Transfer completed.
            #self._timeout.cancel()
            # Python 2.
            #if message.encode('ISO-8859-1').lower() == self.ACK_MSG.lower():
            # Python 3.
            if message.lower() == self.ACK_MSG.lower():
                self._on_load_complete()
            else:
                self._on_load_error(FirmwareUpgradeError.CORRUPTED_FILE_ERROR)
 def on_update(self, feature, sample):
     global nIdx
     ###Audio Stream#################################################
     global stream
     ###Audio Stream#################################################
     ###Save Audio File##############################################
     global audioFile
     global saveAudioFlag
     ###Save Audio File##############################################
     shortData = sample._data
     if len(shortData) != 0:
         for d in shortData:
             byteData = LittleEndian.int16ToBytes(d)
             ###Save Audio File######################################
             if saveAudioFlag == 'y' or saveAudioFlag == 'Y':
                 audioFile.write(byteData)
             ###Save Audio File######################################
             ###Audio Stream#########################################
             stream.write(byteData)
             ###Audio Stream#########################################
         nIdx += 1
    def get_audio(self, sample):
        """Get the audio data from a sample.

        Args:
            sample (:class:`blue_st_sdk.feature.Sample`): Sample data.
        
        Returns:
            short[]: audio values if the data array is valid, None[]
            otherwise.
        """
        audioPckt = []
        if sample is not None:
            if sample._data:
                if sample._data[0] is not None:
                    length = len(sample._data)
                    audioPckt = [None] * length
                    
                    for i in range(0,length):
                        if sample.data[i] != None:
                            audioPckt[i] = LittleEndian.bytes_to_int16(sample._data[i], (2*i))
                    return audioPckt
        return audioPckt