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)
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)
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
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
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)
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)
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