def _create_set_output(self, parameters): """ load buffer with sync byte (A5), ID byte (01), and size word (# of words in little-endian form) 'user' configuration is 512 bytes = 256 words long = size 0x100 """ output = ['\xa5\x00\x00\x01'] CHECK_SUM_SEED = 0xb58c for param in self.order_of_user_config: log.trace('_create_set_output: adding %s to list', param) if param == Parameter.COMMENTS: output.append(parameters.format(param).ljust(180, "\x00")) elif param == Parameter.DEPLOYMENT_NAME: output.append(parameters.format(param).ljust(6, "\x00")) elif param == Parameter.QUAL_CONSTANTS: output.append('\x00'.ljust(16, "\x00")) elif param == Parameter.VELOCITY_ADJ_TABLE: output.append(base64.b64decode(parameters.format(param))) elif param in [ Parameter.A1_1_SPARE, Parameter.B0_1_SPARE, Parameter.B1_1_SPARE, Parameter.USER_1_SPARE, Parameter.A1_2_SPARE, Parameter.B0_2_SPARE, Parameter.USER_2_SPARE, Parameter.USER_3_SPARE ]: output.append( self.spare_param_values.get(param).ljust(2, "\x00")) elif param in [ Parameter.WAVE_MEASUREMENT_MODE, Parameter.WAVE_TRANSMIT_PULSE, Parameter.WAVE_BLANKING_DISTANCE, Parameter.WAVE_CELL_SIZE, Parameter.NUMBER_DIAG_SAMPLES, Parameter.DYN_PERCENTAGE_POSITION ]: output.append('\x00'.ljust(2, "\x00")) elif param == Parameter.USER_4_SPARE: output.append( self.spare_param_values.get(param).ljust(30, "\x00")) else: output.append(parameters.format(param)) log.trace('_create_set_output: ADDED %s output size = %s', param, len(output)) log.debug("Created set output: %r with length: %s", output, len(output)) checksum = CHECK_SUM_SEED output = "".join(output) for word_index in range(0, len(output), 2): word_value = NortekProtocolParameterDict.convert_word_to_int( output[word_index:word_index + 2]) checksum = (checksum + word_value) % 0x10000 log.debug('_create_set_output: user checksum = %r', checksum) output += (NortekProtocolParameterDict.word_to_string(checksum)) return output
def _build_parsed_values(self): """ Take the velocity header data sample format and parse it into values with appropriate tags. @throws SampleException If there is a problem with sample creation """ log.debug('VectorVelocityHeaderDataParticle: raw data =%r', self.raw_data) try: unpack_string = '<4s6sH8B20sH' sync, timestamp, number_of_records, noise1, noise2, noise3, _, correlation1, correlation2, correlation3, _,\ _, cksum = struct.unpack(unpack_string, self.raw_data) if not validate_checksum('<20H', self.raw_data, cksum): log.warn("Bad vel3d_cd_data_header from instrument (%r)", self.raw_data) self.contents[DataParticleKey.QUALITY_FLAG] = DataParticleValue.CHECKSUM_FAILED timestamp = NortekProtocolParameterDict.convert_time(timestamp) except Exception: log.error('Error creating particle vel3d_cd_data_header, raw data: %r', self.raw_data) raise SampleException result = [{DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.TIMESTAMP, DataParticleKey.VALUE: timestamp}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NUMBER_OF_RECORDS, DataParticleKey.VALUE: number_of_records}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NOISE1, DataParticleKey.VALUE: noise1}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NOISE2, DataParticleKey.VALUE: noise2}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NOISE3, DataParticleKey.VALUE: noise3}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.CORRELATION1, DataParticleKey.VALUE: correlation1}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.CORRELATION2, DataParticleKey.VALUE: correlation2}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.CORRELATION3, DataParticleKey.VALUE: correlation3}] log.debug('VectorVelocityHeaderDataParticle: particle=%s', result) return result
def _build_particle(self, match): timestamp = NortekProtocolParameterDict.convert_time(match.group(1)) py_timestamp = time.strptime(timestamp, "%d/%m/%Y %H:%M:%S") self.set_internal_timestamp(unix_time=time.mktime(py_timestamp)) battery = NortekProtocolParameterDict.convert_word_to_int(match.group(2)) sound_speed = NortekProtocolParameterDict.convert_word_to_int(match.group(3)) heading = NortekProtocolParameterDict.convert_word_to_int(match.group(4)) pitch = NortekProtocolParameterDict.convert_word_to_int(match.group(5)) roll = NortekProtocolParameterDict.convert_word_to_int(match.group(6)) temperature = NortekProtocolParameterDict.convert_word_to_int(match.group(7)) error = ord(match.group(8)) status = ord(match.group(9)) analog_input = NortekProtocolParameterDict.convert_word_to_int(match.group(10)) if None == timestamp: raise SampleException("No timestamp parsed") if None == battery: raise SampleException("No battery value parsed") if None == sound_speed: raise SampleException("No sound_speed value parsed") if None == heading: raise SampleException("No heading value parsed") if None == pitch: raise SampleException("No pitch value parsed") if None == roll: raise SampleException("No roll value parsed") if None == temperature: raise SampleException("No temperature value parsed") if None == error: raise SampleException("No error value parsed") if None == status: raise SampleException("No status value parsed") if None == analog_input: raise SampleException("No analog_input value parsed") result = [{DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.TIMESTAMP, DataParticleKey.VALUE: timestamp}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.BATTERY, DataParticleKey.VALUE: battery}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.SOUND_SPEED, DataParticleKey.VALUE: sound_speed}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.HEADING, DataParticleKey.VALUE: heading}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.PITCH, DataParticleKey.VALUE: pitch}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.ROLL, DataParticleKey.VALUE: roll}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.TEMPERATURE, DataParticleKey.VALUE: temperature}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.ERROR, DataParticleKey.VALUE: error}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.STATUS, DataParticleKey.VALUE: status}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.ANALOG_INPUT, DataParticleKey.VALUE: analog_input}] return result
def _build_particle(self, match): timestamp = NortekProtocolParameterDict.convert_time(match.group(1)) py_timestamp = time.strptime(timestamp, "%d/%m/%Y %H:%M:%S") self.set_internal_timestamp(unix_time=time.mktime(py_timestamp)) number_of_records = NortekProtocolParameterDict.convert_word_to_int(match.group(2)) noise1 = ord(match.group(3)) noise2 = ord(match.group(4)) noise3 = ord(match.group(5)) correlation1 = ord(match.group(6)) correlation2 = ord(match.group(7)) correlation3 = ord(match.group(8)) if None == timestamp: raise SampleException("No timestamp parsed") if None == number_of_records: raise SampleException("No number_of_records value parsed") if None == noise1: raise SampleException("No noise1 value parsed") if None == noise2: raise SampleException("No noise2 value parsed") if None == noise3: raise SampleException("No noise3 value parsed") if None == correlation1: raise SampleException("No correlation1 value parsed") if None == correlation2: raise SampleException("No correlation2 value parsed") if None == correlation3: raise SampleException("No correlation3 value parsed") result = [{DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.TIMESTAMP, DataParticleKey.VALUE: timestamp}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NUMBER_OF_RECORDS, DataParticleKey.VALUE: number_of_records}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NOISE1, DataParticleKey.VALUE: noise1}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NOISE2, DataParticleKey.VALUE: noise2}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NOISE3, DataParticleKey.VALUE: noise3}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.CORRELATION1, DataParticleKey.VALUE: correlation1}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.CORRELATION2, DataParticleKey.VALUE: correlation2}, {DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.CORRELATION3, DataParticleKey.VALUE: correlation3}] return result
def _create_set_output(self, parameters): """ load buffer with sync byte (A5), ID byte (01), and size word (# of words in little-endian form) 'user' configuration is 512 bytes = 256 words long = size 0x100 """ output = ['\xa5\x00\x00\x01'] CHECK_SUM_SEED = 0xb58c for param in self.order_of_user_config: log.trace('_create_set_output: adding %s to list', param) if param == Parameter.COMMENTS: output.append(parameters.format(param).ljust(180, "\x00")) elif param == Parameter.DEPLOYMENT_NAME: output.append(parameters.format(param).ljust(6, "\x00")) elif param == Parameter.QUAL_CONSTANTS: output.append('\x00'.ljust(16, "\x00")) elif param == Parameter.VELOCITY_ADJ_TABLE: output.append(base64.b64decode(parameters.format(param))) elif param in [Parameter.A1_1_SPARE, Parameter.B0_1_SPARE, Parameter.B1_1_SPARE, Parameter.USER_1_SPARE, Parameter.A1_2_SPARE, Parameter.B0_2_SPARE, Parameter.USER_2_SPARE, Parameter.USER_3_SPARE]: output.append(self.spare_param_values.get(param).ljust(2, "\x00")) elif param in [Parameter.WAVE_MEASUREMENT_MODE, Parameter.WAVE_TRANSMIT_PULSE, Parameter.WAVE_BLANKING_DISTANCE, Parameter.WAVE_CELL_SIZE, Parameter.NUMBER_DIAG_SAMPLES, Parameter.DYN_PERCENTAGE_POSITION]: output.append('\x00'.ljust(2, "\x00")) elif param == Parameter.USER_4_SPARE: output.append(self.spare_param_values.get(param).ljust(30, "\x00")) else: output.append(parameters.format(param)) log.trace('_create_set_output: ADDED %s output size = %s', param, len(output)) log.debug("Created set output: %r with length: %s", output, len(output)) checksum = CHECK_SUM_SEED output = "".join(output) for word_index in range(0, len(output), 2): word_value = NortekProtocolParameterDict.convert_word_to_int(output[word_index:word_index+2]) checksum = (checksum + word_value) % 0x10000 log.debug('_create_set_output: user checksum = %r', checksum) output += (NortekProtocolParameterDict.word_to_string(checksum)) return output
def _build_parsed_values(self): """ Take the velocity data sample and parse it into values with appropriate tags. @throws SampleException If there is a problem with sample creation """ log.debug('AquadoppDwVelocityDataParticle: raw data =%r', self.raw_data) try: unpack_string = '<4s6s2h2H3hBbH4h3B1sH' sync, timestamp, error, analog1, battery_voltage, sound_speed, heading, pitch, roll, pressure_msb, status, \ pressure_lsw, temperature, velocity_beam1, velocity_beam2, velocity_beam3, amplitude_beam1, \ amplitude_beam2, amplitude_beam3, _, cksum = struct.unpack(unpack_string, self.raw_data) if not validate_checksum('<20H', self.raw_data, cksum): log.warn("Bad velpt_velocity_data instrument (%r)", self.raw_data) self.contents[DataParticleKey.QUALITY_FLAG] = DataParticleValue.CHECKSUM_FAILED timestamp = NortekProtocolParameterDict.convert_time(timestamp) pressure = pressure_msb * 0x10000 + pressure_lsw except Exception: log.error('Error creating particle velpt_velocity_data, raw data: %r', self.raw_data) raise SampleException result = [{DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.TIMESTAMP, DataParticleKey.VALUE: timestamp}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.ERROR, DataParticleKey.VALUE: error}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.ANALOG1, DataParticleKey.VALUE: analog1}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.BATTERY_VOLTAGE, DataParticleKey.VALUE: battery_voltage}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.SOUND_SPEED_ANALOG2, DataParticleKey.VALUE: sound_speed}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.HEADING, DataParticleKey.VALUE: heading}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.PITCH, DataParticleKey.VALUE: pitch}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.ROLL, DataParticleKey.VALUE: roll}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.STATUS, DataParticleKey.VALUE: status}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.PRESSURE, DataParticleKey.VALUE: pressure}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.TEMPERATURE, DataParticleKey.VALUE: temperature}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.VELOCITY_BEAM1, DataParticleKey.VALUE: velocity_beam1}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.VELOCITY_BEAM2, DataParticleKey.VALUE: velocity_beam2}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.VELOCITY_BEAM3, DataParticleKey.VALUE: velocity_beam3}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.AMPLITUDE_BEAM1, DataParticleKey.VALUE: amplitude_beam1}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.AMPLITUDE_BEAM2, DataParticleKey.VALUE: amplitude_beam2}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.AMPLITUDE_BEAM3, DataParticleKey.VALUE: amplitude_beam3}] log.debug('AquadoppDwVelocityDataParticle: particle=%s', result) return result
def _build_param_dict(self): NortekInstrumentProtocol._build_param_dict(self) self._param_dict.add_parameter( NortekParameterDictVal(Parameter.NUMBER_SAMPLES_PER_BURST, r'^.{%s}(.{2}).*' % str(452), lambda match : NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL)) self._param_dict.add_parameter( NortekParameterDictVal(Parameter.USER_3_SPARE, r'^.{%s}(.{2}).*' % str(460), lambda match : match.group(1), lambda string : string, visibility=ParameterDictVisibility.READ_ONLY, regex_flags=re.DOTALL)) self._param_dict.load_strings(RESOURCE_FILE)
def _build_parsed_values(self): """ Take the system data sample format and parse it into values with appropriate tags. @throws SampleException If there is a problem with sample creation """ log.debug('VectorSystemDataParticle: raw data =%r', self.raw_data) try: unpack_string = '<4s6s2H4h2bHH' sync, timestamp, battery, sound_speed, heading, pitch, roll, temperature, error, status, analog_input, cksum =\ struct.unpack_from(unpack_string, self.raw_data) if not validate_checksum('<13H', self.raw_data): log.warn("Failed checksum in %s from instrument (%r)", self._data_particle_type, self.raw_data) self.contents[DataParticleKey.QUALITY_FLAG] = DataParticleValue.CHECKSUM_FAILED timestamp = NortekProtocolParameterDict.convert_time(timestamp) self.set_internal_timestamp((timestamp-datetime(1900, 1, 1)).total_seconds()) except Exception as e: log.error('Error creating particle vel3d_cd_system_data, raw data: %r', self.raw_data) raise SampleException(e) result = [{DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.TIMESTAMP, DataParticleKey.VALUE: str(timestamp)}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.BATTERY, DataParticleKey.VALUE: battery}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.SOUND_SPEED, DataParticleKey.VALUE: sound_speed}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.HEADING, DataParticleKey.VALUE: heading}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.PITCH, DataParticleKey.VALUE: pitch}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.ROLL, DataParticleKey.VALUE: roll}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.TEMPERATURE, DataParticleKey.VALUE: temperature}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.ERROR, DataParticleKey.VALUE: error}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.STATUS, DataParticleKey.VALUE: status}, {DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.ANALOG_INPUT, DataParticleKey.VALUE: analog_input}] log.debug('VectorSystemDataParticle: particle=%r', result) return result
def _build_parsed_values(self): """ Take the system data sample format and parse it into values with appropriate tags. @throws SampleException If there is a problem with sample creation """ log.debug('VectorSystemDataParticle: raw data =%r', self.raw_data) try: unpack_string = '<4s6s2H4h2bHH' sync, timestamp, battery, sound_speed, heading, pitch, roll, temperature, error, status, analog_input, cksum =\ struct.unpack_from(unpack_string, self.raw_data) if not validate_checksum('<13H', self.raw_data): log.warn("Failed checksum in %s from instrument (%r)", self._data_particle_type, self.raw_data) self.contents[DataParticleKey. QUALITY_FLAG] = DataParticleValue.CHECKSUM_FAILED timestamp = NortekProtocolParameterDict.convert_time(timestamp) self.set_internal_timestamp( (timestamp - datetime(1900, 1, 1)).total_seconds()) except Exception as e: log.error( 'Error creating particle vel3d_cd_system_data, raw data: %r', self.raw_data) raise SampleException(e) result = [{ DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.TIMESTAMP, DataParticleKey.VALUE: str(timestamp) }, { DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.BATTERY, DataParticleKey.VALUE: battery }, { DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.SOUND_SPEED, DataParticleKey.VALUE: sound_speed }, { DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.HEADING, DataParticleKey.VALUE: heading }, { DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.PITCH, DataParticleKey.VALUE: pitch }, { DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.ROLL, DataParticleKey.VALUE: roll }, { DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.TEMPERATURE, DataParticleKey.VALUE: temperature }, { DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.ERROR, DataParticleKey.VALUE: error }, { DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.STATUS, DataParticleKey.VALUE: status }, { DataParticleKey.VALUE_ID: VectorSystemDataParticleKey.ANALOG_INPUT, DataParticleKey.VALUE: analog_input }] log.debug('VectorSystemDataParticle: particle=%r', result) return result
def _build_parsed_values(self): """ Take the velocity header data sample format and parse it into values with appropriate tags. @throws SampleException If there is a problem with sample creation """ log.debug('VectorVelocityHeaderDataParticle: raw data =%r', self.raw_data) try: unpack_string = '<4s6sH8B20sH' sync, timestamp, number_of_records, noise1, noise2, noise3, _, correlation1, correlation2, correlation3, _,\ _, cksum = struct.unpack(unpack_string, self.raw_data) if not validate_checksum('<20H', self.raw_data): log.warn("Failed checksum in %s from instrument (%r)", self._data_particle_type, self.raw_data) self.contents[DataParticleKey. QUALITY_FLAG] = DataParticleValue.CHECKSUM_FAILED timestamp = NortekProtocolParameterDict.convert_time(timestamp) self.set_internal_timestamp( (timestamp - datetime(1900, 1, 1)).total_seconds()) except Exception as e: log.error( 'Error creating particle vel3d_cd_data_header, raw data: %r', self.raw_data) raise SampleException(e) result = [{ DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.TIMESTAMP, DataParticleKey.VALUE: str(timestamp) }, { DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NUMBER_OF_RECORDS, DataParticleKey.VALUE: number_of_records }, { DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NOISE1, DataParticleKey.VALUE: noise1 }, { DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NOISE2, DataParticleKey.VALUE: noise2 }, { DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.NOISE3, DataParticleKey.VALUE: noise3 }, { DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.CORRELATION1, DataParticleKey.VALUE: correlation1 }, { DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.CORRELATION2, DataParticleKey.VALUE: correlation2 }, { DataParticleKey.VALUE_ID: VectorVelocityHeaderDataParticleKey.CORRELATION3, DataParticleKey.VALUE: correlation3 }] log.debug('VectorVelocityHeaderDataParticle: particle=%s', result) return result
def _build_param_dict(self): """ Overwrite base classes method. Creates base class's param dictionary, then sets parameter values for those specific to this instrument. """ NortekInstrumentProtocol._build_param_dict(self) self._param_dict.add(Parameter.TRANSMIT_PULSE_LENGTH, r'^.{%s}(.{2}).*' % str(4), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Transmit Pulse Length", description="Pulse duration of the transmitted signal.", default_value=2, units=Units.COUNTS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.BLANKING_DISTANCE, r'^.{%s}(.{2}).*' % str(6), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Blanking Distance", description="Minimum sensing range of the sensor.", default_value=16, units=Units.COUNTS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.RECEIVE_LENGTH, r'^.{%s}(.{2}).*' % str(8), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Receive Length", description="Length of the received pulse.", default_value=7, units=Units.COUNTS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.TIME_BETWEEN_PINGS, r'^.{%s}(.{2}).*' % str(10), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Time Between Pings", description="Length of time between each ping.", default_value=44, units=Units.COUNTS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.TIME_BETWEEN_BURST_SEQUENCES, r'^.{%s}(.{2}).*' % str(12), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Time Between Burst Sequences", description="Length of time between each burst.", default_value=0, units=Units.COUNTS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.NUMBER_PINGS, r'^.{%s}(.{2}).*' % str(14), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Number Pings", description="Number of pings in each burst sequence.", default_value=0, units=Units.HERTZ, startup_param=True, direct_access=True) self._param_dict.add(Parameter.AVG_INTERVAL, r'^.{%s}(.{2}).*' % str(16), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Average Interval", description="Interval for continuous sampling.", default_value=64, units=Units.SECOND, startup_param=True, direct_access=True) self._param_dict.add(Parameter.MEASUREMENT_INTERVAL, r'^.{%s}(.{2}).*' % str(38), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Measurement Interval", description="Interval for single measurements.", units=Units.SECOND, default_value=600, startup_param=True, direct_access=True) self._param_dict.add(Parameter.DIAGNOSTIC_INTERVAL, r'^.{%s}(.{4}).*' % str(54), lambda match: NortekProtocolParameterDict.convert_double_word_to_int(match.group(1)), NortekProtocolParameterDict.double_word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Diagnostic Interval", description='Number of seconds between diagnostics measurements.', default_value=10800, units=Units.SECOND, startup_param=True, direct_access=True) self._param_dict.add(Parameter.ADJUSTMENT_SOUND_SPEED, r'^.{%s}(.{2}).*' % str(60), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Adjustment Sound Speed", description='User input sound speed adjustment factor.', default_value=16657, units=Units.METER + '/' + Units.SECOND, startup_param=True, direct_access=True) self._param_dict.add(Parameter.NUMBER_SAMPLES_DIAGNOSTIC, r'^.{%s}(.{2}).*' % str(62), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Diagnostic Samples", description='Number of samples in diagnostics mode.', default_value=1, startup_param=True, direct_access=True) self._param_dict.add(Parameter.SW_VERSION, r'^.{%s}(.{2}).*' % str(72), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_ONLY, direct_access=True, display_name="Software Version", description="Current software version installed on instrument.") self._param_dict.add(Parameter.SAMPLE_RATE, r'^.{%s}(.{2}).*' % str(454), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Sample Rate", description="Number of samples per burst.", default_value=16, startup_param=True) self._param_dict.add(Parameter.ANALOG_OUTPUT_SCALE, r'^.{%s}(.{2}).*' % str(456), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Analog Output Scale Factor", description="Scale factor used in calculating analog output.", default_value=6711, startup_param=True, direct_access=True)
def _build_parsed_values(self): """ Take the velocity data sample and parse it into values with appropriate tags. @throws SampleException If there is a problem with sample creation typedef struct { unsigned char cSync; // sync = 0xa5 unsigned char cId; // identification (0x01=normal, 0x80=diag) unsigned short hSize; // size of structure (words) PdClock clock; // date and time short hError; // error code: unsigned short hAnaIn1; // analog input 1 unsigned short hBattery; // battery voltage (0.1 V) union { unsigned short hSoundSpeed; // speed of sound (0.1 m/s) unsigned short hAnaIn2; // analog input 2 } u; short hHeading; // compass heading (0.1 deg) short hPitch; // compass pitch (0.1 deg) short hRoll; // compass roll (0.1 deg) unsigned char cPressureMSB; // pressure MSB char cStatus; // status: unsigned short hPressureLSW; // pressure LSW short hTemperature; // temperature (0.01 deg C) short hVel[3]; // velocity unsigned char cAmp[3]; // amplitude char cFill; short hChecksum; // checksum } PdMeas; """ try: unpack_format = ( ('sync', '<4s'), # cSync, cId, hSize ('timestamp', '6s'), # PdClock ('error', 'H'), # defined as signed short, but represents bitmap, using unsigned ('analog1', 'H'), ('battery_voltage', 'H'), ('sound_speed', 'H'), ('heading', 'h'), ('pitch', 'h'), ('roll', 'h'), ('pressure_msb', 'B'), ('status', 'B'), # defined as char, but represents bitmap, using unsigned ('pressure_lsw', 'H'), ('temperature', 'h'), ('velocity_beam1', 'h'), ('velocity_beam2', 'h'), ('velocity_beam3', 'h'), ('amplitude_beam1', 'B'), ('amplitude_beam2', 'B'), ('amplitude_beam3', 'B'), ) data = unpack_from_format(self._data_particle_type, unpack_format, self.raw_data) if not validate_checksum('<20H', self.raw_data): log.warn("Failed checksum in %s from instrument (%r)", self._data_particle_type, self.raw_data) self.contents[DataParticleKey.QUALITY_FLAG] = DataParticleValue.CHECKSUM_FAILED timestamp = NortekProtocolParameterDict.convert_time(data.timestamp) self.set_internal_timestamp((timestamp-datetime(1900, 1, 1)).total_seconds()) pressure = data.pressure_msb * 0x10000 + data.pressure_lsw except Exception as e: log.error('Error creating particle velpt_velocity_data, raw data: %r', self.raw_data) raise SampleException(e) key = AquadoppDwVelocityDataParticleKey result = [{DataParticleKey.VALUE_ID: key.TIMESTAMP, DataParticleKey.VALUE: str(timestamp)}, {DataParticleKey.VALUE_ID: key.ERROR, DataParticleKey.VALUE: data.error}, {DataParticleKey.VALUE_ID: key.ANALOG1, DataParticleKey.VALUE: data.analog1}, {DataParticleKey.VALUE_ID: key.BATTERY_VOLTAGE, DataParticleKey.VALUE: data.battery_voltage}, {DataParticleKey.VALUE_ID: key.SOUND_SPEED_ANALOG2, DataParticleKey.VALUE: data.sound_speed}, {DataParticleKey.VALUE_ID: key.HEADING, DataParticleKey.VALUE: data.heading}, {DataParticleKey.VALUE_ID: key.PITCH, DataParticleKey.VALUE: data.pitch}, {DataParticleKey.VALUE_ID: key.ROLL, DataParticleKey.VALUE: data.roll}, {DataParticleKey.VALUE_ID: key.STATUS, DataParticleKey.VALUE: data.status}, {DataParticleKey.VALUE_ID: key.PRESSURE, DataParticleKey.VALUE: pressure}, {DataParticleKey.VALUE_ID: key.TEMPERATURE, DataParticleKey.VALUE: data.temperature}, {DataParticleKey.VALUE_ID: key.VELOCITY_BEAM1, DataParticleKey.VALUE: data.velocity_beam1}, {DataParticleKey.VALUE_ID: key.VELOCITY_BEAM2, DataParticleKey.VALUE: data.velocity_beam2}, {DataParticleKey.VALUE_ID: key.VELOCITY_BEAM3, DataParticleKey.VALUE: data.velocity_beam3}, {DataParticleKey.VALUE_ID: key.AMPLITUDE_BEAM1, DataParticleKey.VALUE: data.amplitude_beam1}, {DataParticleKey.VALUE_ID: key.AMPLITUDE_BEAM2, DataParticleKey.VALUE: data.amplitude_beam2}, {DataParticleKey.VALUE_ID: key.AMPLITUDE_BEAM3, DataParticleKey.VALUE: data.amplitude_beam3}] return result
def _build_param_dict(self): """ Overwrite base classes method. Creates base class's param dictionary, then sets parameter values for those specific to this instrument. """ NortekInstrumentProtocol._build_param_dict(self) self._param_dict.add(Parameter.TRANSMIT_PULSE_LENGTH, r'^.{%s}(.{2}).*' % str(4), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Transmit Pulse Length", default_value=125, units=ParameterUnits.CENTIMETERS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.BLANKING_DISTANCE, r'^.{%s}(.{2}).*' % str(6), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Blanking Distance", default_value=49, units=ParameterUnits.CENTIMETERS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.RECEIVE_LENGTH, r'^.{%s}(.{2}).*' % str(8), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Receive Length", default_value=32, units=ParameterUnits.CENTIMETERS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.TIME_BETWEEN_PINGS, r'^.{%s}(.{2}).*' % str(10), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Time Between Pings", units=ParameterUnits.CENTIMETERS, default_value=437, startup_param=True, direct_access=True) self._param_dict.add(Parameter.TIME_BETWEEN_BURST_SEQUENCES, r'^.{%s}(.{2}).*' % str(12), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Time Between Burst Sequences", default_value=512, units=None, startup_param=True, direct_access=True) self._param_dict.add(Parameter.NUMBER_PINGS, r'^.{%s}(.{2}).*' % str(14), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Number Pings", default_value=1, units=ParameterUnits.HERTZ, startup_param=True, direct_access=True) self._param_dict.add(Parameter.AVG_INTERVAL, r'^.{%s}(.{2}).*' % str(16), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Average Interval", default_value=60, units=ParameterUnits.SECONDS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.USER_NUMBER_BEAMS, r'^.{%s}(.{2}).*' % str(18), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_ONLY, display_name="User Number Beams", direct_access=True, value=3) self._param_dict.add(Parameter.TIMING_CONTROL_REGISTER, r'^.{%s}(.{2}).*' % str(20), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Timing Control Register", direct_access=True, value=130) self._param_dict.add(Parameter.POWER_CONTROL_REGISTER, r'^.{%s}(.{2}).*' % str(22), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Power Control Register", default_value=0, startup_param=True, direct_access=True) self._param_dict.add(Parameter.A1_1_SPARE, r'^.{%s}(.{2}).*' % str(24), lambda match: match.group(1).encode('hex'), lambda string: string.decode('hex'), regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_ONLY, display_name="A1 1 Spare", description='Not used.') self._param_dict.add(Parameter.B0_1_SPARE, r'^.{%s}(.{2}).*' % str(26), lambda match: match.group(1).encode('hex'), lambda string: string.decode('hex'), regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_ONLY, display_name="B0 1 Spare", description='Not used.') self._param_dict.add(Parameter.B1_1_SPARE, r'^.{%s}(.{2}).*' % str(28), lambda match: match.group(1).encode('hex'), lambda string: string.decode('hex'), regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_ONLY, display_name="B1 1 Spare", description='Not used.') self._param_dict.add(Parameter.COMPASS_UPDATE_RATE, r'^.{%s}(.{2}).*' % str(30), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Compass Update Rate", default_value=1, units=ParameterUnits.HERTZ, startup_param=True, direct_access=True) self._param_dict.add(Parameter.COORDINATE_SYSTEM, r'^.{%s}(.{2}).*' % str(32), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Coordinate System", description='Coordinate System (0=ENU, 1=XYZ, 2=BEAM)', default_value=2, startup_param=True, direct_access=True) self._param_dict.add(Parameter.NUMBER_BINS, r'^.{%s}(.{2}).*' % str(34), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Number Bins", default_value=1, units=ParameterUnits.METERS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.BIN_LENGTH, r'^.{%s}(.{2}).*' % str(36), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Bin Length", default_value=7, units=ParameterUnits.SECONDS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.MEASUREMENT_INTERVAL, r'^.{%s}(.{2}).*' % str(38), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Measurement Interval", default_value=60, units=ParameterUnits.SECONDS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.DEPLOYMENT_NAME, r'^.{%s}(.{6}).*' % str(40), lambda match: NortekProtocolParameterDict.convert_bytes_to_string(match.group(1)), lambda string: string, regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Deployment Name", startup_param=True, direct_access=True) self._param_dict.add(Parameter.WRAP_MODE, r'^.{%s}(.{2}).*' % str(46), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Wrap Mode", description='Recorder wrap mode (0=NO WRAP, 1=WRAP WHEN FULL)', default_value=0, startup_param=True, direct_access=True) self._param_dict.add(Parameter.CLOCK_DEPLOY, r'^.{%s}(.{6}).*' % str(48), lambda match: NortekProtocolParameterDict.convert_words_to_datetime(match.group(1)), NortekProtocolParameterDict.convert_datetime_to_words, regex_flags=re.DOTALL, type=ParameterDictType.LIST, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Clock Deploy", description='Deployment start time.', default_value=[0, 0, 0, 0, 0, 0], startup_param=True, direct_access=True) self._param_dict.add(Parameter.DIAGNOSTIC_INTERVAL, r'^.{%s}(.{4}).*' % str(54), lambda match: NortekProtocolParameterDict.convert_double_word_to_int(match.group(1)), NortekProtocolParameterDict.double_word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Diagnostic Interval", description='Number of seconds between diagnostics measurements.', default_value=11250, startup_param=True, units=ParameterUnits.SECONDS, direct_access=True) self._param_dict.add(Parameter.MODE, r'^.{%s}(.{2}).*' % str(58), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Mode", default_value=48, startup_param=True, direct_access=True) self._param_dict.add(Parameter.ADJUSTMENT_SOUND_SPEED, r'^.{%s}(.{2}).*' % str(60), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Adjustment Sound Speed", description='User input sound speed adjustment factor.', units=ParameterUnits.METERS_PER_SECOND, default_value=1525, startup_param=True, direct_access=True) self._param_dict.add(Parameter.NUMBER_SAMPLES_DIAGNOSTIC, r'^.{%s}(.{2}).*' % str(62), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Number Samples Diagnostic", description='Samples in diagnostics mode.', default_value=20, startup_param=True, direct_access=True) self._param_dict.add(Parameter.NUMBER_BEAMS_CELL_DIAGNOSTIC, r'^.{%s}(.{2}).*' % str(64), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Number Beams Cell Diagnostic", description='Beams/cell number to measure in diagnostics mode', default_value=1, startup_param=True, direct_access=True) self._param_dict.add(Parameter.NUMBER_PINGS_DIAGNOSTIC, r'^.{%s}(.{2}).*' % str(66), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Number Pings Diagnostic", description='Pings in diagnostics/wave mode.', default_value=1, startup_param=True, direct_access=True) self._param_dict.add(Parameter.MODE_TEST, r'^.{%s}(.{2}).*' % str(68), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Mode Test", default_value=4, startup_param=True, direct_access=True) self._param_dict.add(Parameter.ANALOG_INPUT_ADDR, r'^.{%s}(.{2}).*' % str(70), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Analog Input Address", default_value=0, startup_param=True, direct_access=True) self._param_dict.add(Parameter.SW_VERSION, r'^.{%s}(.{2}).*' % str(72), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Software Version", default_value=13902, startup_param=True, direct_access=True) self._param_dict.add(Parameter.USER_1_SPARE, r'^.{%s}(.{2}).*' % str(74), lambda match: match.group(1).encode('hex'), lambda string: string.decode('hex'), regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_ONLY, display_name="User 1 Spare", description='Not used.') self._param_dict.add(Parameter.VELOCITY_ADJ_TABLE, r'^.{%s}(.{180}).*' % str(76), lambda match: base64.b64encode(match.group(1)), lambda string: string, regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_WRITE, display_name="Velocity Adj Table", units=ParameterUnits.PARTS_PER_TRILLION, startup_param=True, direct_access=True) self._param_dict.add(Parameter.COMMENTS, r'^.{%s}(.{180}).*' % str(256), lambda match: NortekProtocolParameterDict.convert_bytes_to_string(match.group(1)), lambda string: string, regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Comments", startup_param=True, direct_access=True) self._param_dict.add(Parameter.WAVE_MEASUREMENT_MODE, r'^.{%s}(.{2}).*' % str(436), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Wave Measurement Mode", default_value=0, startup_param=True, direct_access=True) self._param_dict.add(Parameter.DYN_PERCENTAGE_POSITION, r'^.{%s}(.{2}).*' % str(438), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Dyn Percentage Position", description='Percentage for wave cell positioning.', default_value=0, startup_param=True, direct_access=True) self._param_dict.add(Parameter.WAVE_TRANSMIT_PULSE, r'^.{%s}(.{2}).*' % str(440), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Wave Transmit Pulse", default_value=0, startup_param=True, direct_access=True) self._param_dict.add(Parameter.WAVE_BLANKING_DISTANCE, r'^.{%s}(.{2}).*' % str(442), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Fixed Wave Blanking Distance", default_value=0, startup_param=True, direct_access=True) self._param_dict.add(Parameter.WAVE_CELL_SIZE, r'^.{%s}(.{2}).*' % str(444), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Wave Measurement Cell Size", default_value=0, units=ParameterUnits.METERS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.NUMBER_DIAG_SAMPLES, r'^.{%s}(.{2}).*' % str(446), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Number Diag Samples", description='Number of diagnostics/wave samples.', default_value=0, startup_param=True, direct_access=True) self._param_dict.add(Parameter.A1_2_SPARE, r'^.{%s}(.{2}).*' % str(448), lambda match: match.group(1).encode('hex'), lambda string: string.decode('hex'), regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_ONLY, display_name="A1 2 Spare", description='Not used.') self._param_dict.add(Parameter.B0_2_SPARE, r'^.{%s}(.{2}).*' % str(450), lambda match: match.group(1).encode('hex'), lambda string: string.decode('hex'), regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_ONLY, display_name="B0 2 Spare", description='Not used.') self._param_dict.add(Parameter.NUMBER_SAMPLES_PER_BURST, r'^.{%s}(.{2}).*' % str(452), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, expiration=None, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Number of Samples per Burst", default_value=0, startup_param=True, direct_access=True) self._param_dict.add(Parameter.USER_2_SPARE, r'^.{%s}(.{2}).*' % str(454), lambda match: match.group(1).encode('hex'), lambda string: string.decode('hex'), regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_ONLY, display_name="User 2 Spare", description='Not used.') self._param_dict.add(Parameter.ANALOG_OUTPUT_SCALE, r'^.{%s}(.{2}).*' % str(456), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Analog Output Scale Factor", default_value=0, startup_param=True, direct_access=True) self._param_dict.add(Parameter.CORRELATION_THRESHOLD, r'^.{%s}(.{2}).*' % str(458), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Correlation Threshold", description='Correlation threshold for resolving ambiguities.', default_value=0, startup_param=True, direct_access=True) self._param_dict.add(Parameter.USER_3_SPARE, r'^.{%s}(.{2}).*' % str(460), lambda match: match.group(1).encode('hex'), lambda string: string.decode('hex'), regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_ONLY, display_name="User 3 Spare", description='Not used.') self._param_dict.add(Parameter.TRANSMIT_PULSE_LENGTH_SECOND_LAG, r'^.{%s}(.{2}).*' % str(462), lambda match: NortekProtocolParameterDict.convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Transmit Pulse Length Second Lag", default_value=2, startup_param=True, direct_access=True) self._param_dict.add(Parameter.USER_4_SPARE, r'^.{%s}(.{30}).*' % str(464), lambda match: match.group(1).encode('hex'), lambda string: string.decode('hex'), regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_ONLY, display_name="User 4 Spare", description='Not used.') self._param_dict.add(Parameter.QUAL_CONSTANTS, r'^.{%s}(.{16}).*' % str(494), lambda match: base64.b64encode(match.group(1)), lambda string: string, regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Qual Constants", description='Stage match filter constants.', startup_param=True, direct_access=True)
def _build_parsed_values(self): """ Take something in the velocity data sample format and parse it into values with appropriate tags. @throws SampleException If there is a problem with sample creation """ match = VELOCITY_DATA_REGEX.match(self.raw_data) if not match: raise SampleException("VectorVelocityDataParticle: No regex match of parsed sample data: [%s]", self.raw_data) analog_input2 = ord(match.group(1)) count = ord(match.group(2)) pressure = ord(match.group(3)) * 0x10000 analog_input2 += ord(match.group(4)) * 0x100 pressure += NortekProtocolParameterDict.convert_word_to_int(match.group(5)) analog_input1 = NortekProtocolParameterDict.convert_word_to_int(match.group(6)) velocity_beam1 = NortekProtocolParameterDict.convert_word_to_int(match.group(7)) velocity_beam2 = NortekProtocolParameterDict.convert_word_to_int(match.group(8)) velocity_beam3 = NortekProtocolParameterDict.convert_word_to_int(match.group(9)) amplitude_beam1 = ord(match.group(10)) amplitude_beam2 = ord(match.group(11)) amplitude_beam3 = ord(match.group(12)) correlation_beam1 = ord(match.group(13)) correlation_beam2 = ord(match.group(14)) correlation_beam3 = ord(match.group(15)) if None == analog_input2: raise SampleException("No analog_input2 value parsed") if None == count: raise SampleException("No count value parsed") if None == pressure: raise SampleException("No pressure value parsed") if None == analog_input1: raise SampleException("No analog_input1 value parsed") if None == velocity_beam1: raise SampleException("No velocity_beam1 value parsed") if None == velocity_beam2: raise SampleException("No velocity_beam2 value parsed") if None == velocity_beam3: raise SampleException("No velocity_beam3 value parsed") if None == amplitude_beam1: raise SampleException("No amplitude_beam1 value parsed") if None == amplitude_beam2: raise SampleException("No amplitude_beam2 value parsed") if None == amplitude_beam3: raise SampleException("No amplitude_beam3 value parsed") if None == correlation_beam1: raise SampleException("No correlation_beam1 value parsed") if None == correlation_beam2: raise SampleException("No correlation_beam2 value parsed") if None == correlation_beam3: raise SampleException("No correlation_beam3 value parsed") result = [{DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.ANALOG_INPUT2, DataParticleKey.VALUE: analog_input2}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.COUNT, DataParticleKey.VALUE: count}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.PRESSURE, DataParticleKey.VALUE: pressure}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.ANALOG_INPUT1, DataParticleKey.VALUE: analog_input1}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.VELOCITY_BEAM1, DataParticleKey.VALUE: velocity_beam1}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.VELOCITY_BEAM2, DataParticleKey.VALUE: velocity_beam2}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.VELOCITY_BEAM3, DataParticleKey.VALUE: velocity_beam3}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.AMPLITUDE_BEAM1, DataParticleKey.VALUE: amplitude_beam1}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.AMPLITUDE_BEAM2, DataParticleKey.VALUE: amplitude_beam2}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.AMPLITUDE_BEAM3, DataParticleKey.VALUE: amplitude_beam3}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.CORRELATION_BEAM1, DataParticleKey.VALUE: correlation_beam1}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.CORRELATION_BEAM2, DataParticleKey.VALUE: correlation_beam2}, {DataParticleKey.VALUE_ID: VectorVelocityDataParticleKey.CORRELATION_BEAM3, DataParticleKey.VALUE: correlation_beam3}] log.debug('VectorVelocityDataParticle: particle=%s' %result) return result
def _build_parsed_values(self): """ Take the velocity data sample and parse it into values with appropriate tags. @throws SampleException If there is a problem with sample creation typedef struct { unsigned char cSync; // sync = 0xa5 unsigned char cId; // identification (0x01=normal, 0x80=diag) unsigned short hSize; // size of structure (words) PdClock clock; // date and time short hError; // error code: unsigned short hAnaIn1; // analog input 1 unsigned short hBattery; // battery voltage (0.1 V) union { unsigned short hSoundSpeed; // speed of sound (0.1 m/s) unsigned short hAnaIn2; // analog input 2 } u; short hHeading; // compass heading (0.1 deg) short hPitch; // compass pitch (0.1 deg) short hRoll; // compass roll (0.1 deg) unsigned char cPressureMSB; // pressure MSB char cStatus; // status: unsigned short hPressureLSW; // pressure LSW short hTemperature; // temperature (0.01 deg C) short hVel[3]; // velocity unsigned char cAmp[3]; // amplitude char cFill; short hChecksum; // checksum } PdMeas; """ try: unpack_format = ( ('sync', '<4s'), # cSync, cId, hSize ('timestamp', '6s'), # PdClock ('error', 'H'), # defined as signed short, but represents bitmap, using unsigned ('analog1', 'H'), ('battery_voltage', 'H'), ('sound_speed', 'H'), ('heading', 'h'), ('pitch', 'h'), ('roll', 'h'), ('pressure_msb', 'B'), ('status', 'B'), # defined as char, but represents bitmap, using unsigned ('pressure_lsw', 'H'), ('temperature', 'h'), ('velocity_beam1', 'h'), ('velocity_beam2', 'h'), ('velocity_beam3', 'h'), ('amplitude_beam1', 'B'), ('amplitude_beam2', 'B'), ('amplitude_beam3', 'B'), ) data = unpack_from_format(self._data_particle_type, unpack_format, self.raw_data) if not validate_checksum('<20H', self.raw_data): log.warn("Failed checksum in %s from instrument (%r)", self._data_particle_type, self.raw_data) self.contents[DataParticleKey.QUALITY_FLAG] = DataParticleValue.CHECKSUM_FAILED timestamp = NortekProtocolParameterDict.convert_time(data.timestamp) self.set_internal_timestamp((timestamp-datetime(1900, 1, 1)).total_seconds()) pressure = data.pressure_msb * 0x10000 + data.pressure_lsw except Exception as e: log.error('Error creating particle velpt_velocity_data, raw data: %r', self.raw_data) raise SampleException(e) key = AquadoppDwVelocityDataParticleKey result = [{DataParticleKey.VALUE_ID: key.TIMESTAMP, DataParticleKey.VALUE: str(timestamp)}, {DataParticleKey.VALUE_ID: key.ERROR, DataParticleKey.VALUE: data.error}, {DataParticleKey.VALUE_ID: key.ANALOG1, DataParticleKey.VALUE: data.analog1}, {DataParticleKey.VALUE_ID: key.BATTERY_VOLTAGE, DataParticleKey.VALUE: data.battery_voltage}, {DataParticleKey.VALUE_ID: key.SOUND_SPEED_ANALOG2, DataParticleKey.VALUE: data.sound_speed}, {DataParticleKey.VALUE_ID: key.HEADING, DataParticleKey.VALUE: data.heading}, {DataParticleKey.VALUE_ID: key.PITCH, DataParticleKey.VALUE: data.pitch}, {DataParticleKey.VALUE_ID: key.ROLL, DataParticleKey.VALUE: data.roll}, {DataParticleKey.VALUE_ID: key.STATUS, DataParticleKey.VALUE: data.status}, {DataParticleKey.VALUE_ID: key.PRESSURE, DataParticleKey.VALUE: pressure}, {DataParticleKey.VALUE_ID: key.TEMPERATURE, DataParticleKey.VALUE: data.temperature}, {DataParticleKey.VALUE_ID: key.VELOCITY_BEAM1, DataParticleKey.VALUE: data.velocity_beam1}, {DataParticleKey.VALUE_ID: key.VELOCITY_BEAM2, DataParticleKey.VALUE: data.velocity_beam2}, {DataParticleKey.VALUE_ID: key.VELOCITY_BEAM3, DataParticleKey.VALUE: data.velocity_beam3}, {DataParticleKey.VALUE_ID: key.AMPLITUDE_BEAM1, DataParticleKey.VALUE: data.amplitude_beam1}, {DataParticleKey.VALUE_ID: key.AMPLITUDE_BEAM2, DataParticleKey.VALUE: data.amplitude_beam2}, {DataParticleKey.VALUE_ID: key.AMPLITUDE_BEAM3, DataParticleKey.VALUE: data.amplitude_beam3}] return result
def _build_param_dict(self): """ Overwrite base classes method. Creates base class's param dictionary, then sets parameter values for those specific to this instrument. """ NortekInstrumentProtocol._build_param_dict(self) self._param_dict.add( Parameter.TRANSMIT_PULSE_LENGTH, r'^.{%s}(.{2}).*' % str(4), lambda match: NortekProtocolParameterDict.convert_word_to_int( match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Transmit Pulse Length", description="Pulse duration of the transmitted signal.", range=(1, 65535), default_value=2, units=Units.COUNTS, startup_param=True, direct_access=True) self._param_dict.add( Parameter.BLANKING_DISTANCE, r'^.{%s}(.{2}).*' % str(6), lambda match: NortekProtocolParameterDict.convert_word_to_int( match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Blanking Distance", description="Minimum sensing range of the sensor.", range=(1, 65535), default_value=16, units=Units.COUNTS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.RECEIVE_LENGTH, r'^.{%s}(.{2}).*' % str(8), lambda match: NortekProtocolParameterDict. convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Receive Length", description="Length of the received pulse.", range=(1, 65535), default_value=7, units=Units.COUNTS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.TIME_BETWEEN_PINGS, r'^.{%s}(.{2}).*' % str(10), lambda match: NortekProtocolParameterDict. convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Time Between Pings", description="Length of time between each ping.", default_value=44, units=Units.COUNTS, startup_param=True, direct_access=True) self._param_dict.add(Parameter.TIME_BETWEEN_BURST_SEQUENCES, r'^.{%s}(.{2}).*' % str(12), lambda match: NortekProtocolParameterDict. convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Time Between Burst Sequences", description="Length of time between each burst.", range=(1, 65535), default_value=0, units=Units.COUNTS, startup_param=True, direct_access=True) self._param_dict.add( Parameter.NUMBER_PINGS, r'^.{%s}(.{2}).*' % str(14), lambda match: NortekProtocolParameterDict.convert_word_to_int( match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Number Pings", description="Number of pings in each burst sequence.", range=(1, 65535), default_value=0, units=Units.HERTZ, startup_param=True, direct_access=True) self._param_dict.add(Parameter.AVG_INTERVAL, r'^.{%s}(.{2}).*' % str(16), lambda match: NortekProtocolParameterDict. convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Average Interval", description="Interval for continuous sampling.", default_value=64, range=(1, 65535), units=Units.SECOND, startup_param=True, direct_access=True) self._param_dict.add(Parameter.MEASUREMENT_INTERVAL, r'^.{%s}(.{2}).*' % str(38), lambda match: NortekProtocolParameterDict. convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Measurement Interval", description="Interval for single measurements.", units=Units.SECOND, default_value=600, range=(0, 65535), startup_param=True, direct_access=True) self._param_dict.add( Parameter.DIAGNOSTIC_INTERVAL, r'^.{%s}(.{4}).*' % str(54), lambda match: NortekProtocolParameterDict. convert_double_word_to_int(match.group(1)), NortekProtocolParameterDict.double_word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Diagnostic Interval", description='Number of seconds between diagnostics measurements.', default_value=10800, units=Units.SECOND, startup_param=True, direct_access=True) self._param_dict.add( Parameter.ADJUSTMENT_SOUND_SPEED, r'^.{%s}(.{2}).*' % str(60), lambda match: NortekProtocolParameterDict.convert_word_to_int( match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Adjustment Sound Speed", description='User input sound speed adjustment factor.', default_value=16657, units=Units.METER + '/' + Units.SECOND, startup_param=True, direct_access=True) self._param_dict.add( Parameter.NUMBER_SAMPLES_DIAGNOSTIC, r'^.{%s}(.{2}).*' % str(62), lambda match: NortekProtocolParameterDict.convert_word_to_int( match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Diagnostic Samples", description='Number of samples in diagnostics mode.', default_value=1, startup_param=True, direct_access=True) self._param_dict.add( Parameter.SW_VERSION, r'^.{%s}(.{2}).*' % str(72), lambda match: NortekProtocolParameterDict.convert_word_to_int( match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.STRING, visibility=ParameterDictVisibility.READ_ONLY, direct_access=True, display_name="Software Version", description="Current software version installed on instrument.") self._param_dict.add(Parameter.SAMPLE_RATE, r'^.{%s}(.{2}).*' % str(454), lambda match: NortekProtocolParameterDict. convert_word_to_int(match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.READ_WRITE, display_name="Sample Rate", description="Number of samples per burst.", range=(1, 65535), default_value=16, startup_param=True) self._param_dict.add( Parameter.ANALOG_OUTPUT_SCALE, r'^.{%s}(.{2}).*' % str(456), lambda match: NortekProtocolParameterDict.convert_word_to_int( match.group(1)), NortekProtocolParameterDict.word_to_string, regex_flags=re.DOTALL, type=ParameterDictType.INT, visibility=ParameterDictVisibility.IMMUTABLE, display_name="Analog Output Scale Factor", description="Scale factor used in calculating analog output.", default_value=6711, startup_param=True, direct_access=True)
def _build_particle(self, match): """ Build a particle. Used for parsing Velocity """ timestamp = NortekProtocolParameterDict.convert_time(match.group(1)) error = NortekProtocolParameterDict.convert_word_to_int(match.group(2)) analog1 = NortekProtocolParameterDict.convert_word_to_int(match.group(3)) battery_voltage = NortekProtocolParameterDict.convert_word_to_int(match.group(4)) sound_speed = NortekProtocolParameterDict.convert_word_to_int(match.group(5)) heading = NortekProtocolParameterDict.convert_word_to_int(match.group(6)) pitch = NortekProtocolParameterDict.convert_word_to_int(match.group(7)) roll = NortekProtocolParameterDict.convert_word_to_int(match.group(8)) pressure = ord(match.group(9)) * 0x10000 status = ord(match.group(10)) pressure += NortekProtocolParameterDict.convert_word_to_int(match.group(11)) temperature = NortekProtocolParameterDict.convert_word_to_int(match.group(12)) velocity_beam1 = NortekProtocolParameterDict.convert_word_to_int(match.group(13)) velocity_beam2 = NortekProtocolParameterDict.convert_word_to_int(match.group(14)) velocity_beam3 = NortekProtocolParameterDict.convert_word_to_int(match.group(15)) amplitude_beam1 = ord(match.group(16)) amplitude_beam2 = ord(match.group(17)) amplitude_beam3 = ord(match.group(18)) result = [{DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.TIMESTAMP, DataParticleKey.VALUE: timestamp}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.ERROR, DataParticleKey.VALUE: error}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.ANALOG1, DataParticleKey.VALUE: analog1}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.BATTERY_VOLTAGE, DataParticleKey.VALUE: battery_voltage}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.SOUND_SPEED_ANALOG2, DataParticleKey.VALUE: sound_speed}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.HEADING, DataParticleKey.VALUE: heading}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.PITCH, DataParticleKey.VALUE: pitch}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.ROLL, DataParticleKey.VALUE: roll}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.STATUS, DataParticleKey.VALUE: status}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.PRESSURE, DataParticleKey.VALUE: pressure}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.TEMPERATURE, DataParticleKey.VALUE: temperature}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.VELOCITY_BEAM1, DataParticleKey.VALUE: velocity_beam1}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.VELOCITY_BEAM2, DataParticleKey.VALUE: velocity_beam2}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.VELOCITY_BEAM3, DataParticleKey.VALUE: velocity_beam3}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.AMPLITUDE_BEAM1, DataParticleKey.VALUE: amplitude_beam1}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.AMPLITUDE_BEAM2, DataParticleKey.VALUE: amplitude_beam2}, {DataParticleKey.VALUE_ID: AquadoppDwVelocityDataParticleKey.AMPLITUDE_BEAM3, DataParticleKey.VALUE: amplitude_beam3}] return result