Exemple #1
0
    def _parse_data_message(self, header):
        header, def_mesg, field_datas = self._parse_data_message_components(header)

        # Apply data processors
        for field_data in field_datas:
            # Apply type name processor
            self._processor.run_type_processor(field_data)
            self._processor.run_field_processor(field_data)
            self._processor.run_unit_processor(field_data)

        data_message = DataMessage(header=header, def_mesg=def_mesg, fields=field_datas)
        self._processor.run_message_processor(data_message)

        return data_message
Exemple #2
0
    def _parse_data_message(self, header):
        def_mesg = self._local_mesgs.get(header.local_mesg_num)
        if not def_mesg:
            raise FitParseError(
                'Got data message with invalid local message type %d' %
                (header.local_mesg_num))

        raw_values = self._parse_raw_values_from_data_message(def_mesg)
        field_datas = [
        ]  # TODO: I don't love this name, update on DataMessage too

        # TODO: Maybe refactor this and make it simpler (or at least broken
        #       up into sub-functions)
        for field_def, raw_value in zip(
                def_mesg.field_defs + def_mesg.dev_field_defs, raw_values):
            field, parent_field = field_def.field, None
            if field:
                field, parent_field = self._resolve_subfield(
                    field, def_mesg, raw_values)

                # Resolve component fields
                if field.components:
                    for component in field.components:
                        # Render its raw value
                        cmp_raw_value = component.render(raw_value)

                        # Apply accumulated value
                        if component.accumulate:
                            accumulator = self._accumulators[def_mesg.mesg_num]
                            cmp_raw_value = self._apply_compressed_accumulation(
                                cmp_raw_value,
                                accumulator[component.def_num],
                                component.bits,
                            )
                            accumulator[component.def_num] = cmp_raw_value

                        # Apply scale and offset from component, not from the dynamic field
                        # as they may differ
                        cmp_raw_value = self._apply_scale_offset(
                            component, cmp_raw_value)

                        # Extract the component's dynamic field from def_mesg
                        cmp_field = def_mesg.mesg_type.fields[
                            component.def_num]

                        # Resolve a possible subfield
                        cmp_field, cmp_parent_field = self._resolve_subfield(
                            cmp_field, def_mesg, raw_values)
                        cmp_value = cmp_field.render(cmp_raw_value)

                        # Plop it on field_datas
                        field_datas.append(
                            FieldData(
                                field_def=None,
                                field=cmp_field,
                                parent_field=cmp_parent_field,
                                value=cmp_value,
                                raw_value=cmp_raw_value,
                            ))

                # TODO: Do we care about a base_type and a resolved field mismatch?
                # My hunch is we don't
                value = self._apply_scale_offset(field,
                                                 field.render(raw_value))
            else:
                value = raw_value

            # Update compressed timestamp field
            if (field_def.def_num
                    == FIELD_TYPE_TIMESTAMP.def_num) and (raw_value
                                                          is not None):
                self._compressed_ts_accumulator = raw_value

            field_datas.append(
                FieldData(
                    field_def=field_def,
                    field=field,
                    parent_field=parent_field,
                    value=value,
                    raw_value=raw_value,
                ))

        # Apply timestamp field if we got a header
        if header.time_offset is not None:
            ts_value = self._compressed_ts_accumulator = self._apply_compressed_accumulation(
                header.time_offset,
                self._compressed_ts_accumulator,
                5,
            )
            field_datas.append(
                FieldData(
                    field_def=None,
                    field=FIELD_TYPE_TIMESTAMP,
                    parent_field=None,
                    value=FIELD_TYPE_TIMESTAMP.render(ts_value),
                    raw_value=ts_value,
                ))

        # Apply data processors
        for field_data in field_datas:
            # Apply type name processor
            self._processor.run_type_processor(field_data)
            self._processor.run_field_processor(field_data)
            self._processor.run_unit_processor(field_data)

        data_message = DataMessage(header=header,
                                   def_mesg=def_mesg,
                                   fields=field_datas)
        self._processor.run_message_processor(data_message)

        return data_message
Exemple #3
0
 def _parse_data_message(self, header):
     header, def_mesg, field_datas = self._parse_data_message_components(header)
     return DataMessage(header=header, def_mesg=def_mesg, fields=field_datas)
Exemple #4
0
    def _parse_data_message(self, header):
        def_mesg = self._local_mesgs.get(header.local_mesg_num)
        if not def_mesg:
            raise FitParseError(
                'Got data message with invalid local message type %d' %
                (header.local_mesg_num))

        raw_values = self._parse_raw_values_from_data_message(def_mesg)
        field_datas = [
        ]  # TODO: I don't love this name, update on DataMessage too

        # TODO: Maybe refactor this and make it simpler (or at least broken
        #       up into sub-functions)
        for field_def, raw_value in zip(def_mesg.field_defs, raw_values):
            field, parent_field = field_def.field, None
            if field:
                if field.components:
                    for component in field.components:
                        # Render it's raw value
                        cmp_raw_value = component.render(raw_value)

                        if component.accumulate:
                            accumulator = self._accumulators[def_mesg.mesg_num]
                            cmp_raw_value = self._apply_compressed_accumulation(
                                cmp_raw_value,
                                accumulator[component.def_num],
                                component.bits,
                            )
                            accumulator[component.def_num] = cmp_raw_value

                        # Apply scale and offset from component, not from the dynamic field
                        # as they may differ
                        cmp_raw_value = self._apply_scale_offset(
                            component, cmp_raw_value)

                        # Extract the component's dynamic field from def_mesg
                        cmp_field = def_mesg.mesg_type.fields[
                            component.def_num]
                        # Resolve a possible subfield
                        cmp_field, cmp_parent_field = self._resolve_subfield(
                            cmp_field, def_mesg, raw_values)
                        cmp_value = cmp_field.render(cmp_raw_value)

                        # Plop it on field_datas
                        field_datas.append(
                            FieldData(
                                field_def=None,
                                field=cmp_field,
                                parent_field=cmp_parent_field,
                                value=cmp_value,
                                raw_value=cmp_raw_value,
                            ))

                else:
                    # Component fields shouldn't also have subfields
                    field, parent_field = self._resolve_subfield(
                        field, def_mesg, raw_values)

                # TODO: Do we care about a base_type and a resolved field mismatch?
                # My hunch is we don't
                value = self._apply_scale_offset(field,
                                                 field.render(raw_value))
            else:
                value = raw_value

            # Update compressed timestamp field
            if (field_def.def_num
                    == FIELD_TYPE_TIMESTAMP.def_num) and (raw_value
                                                          is not None):
                self._compressed_ts_accumulator = raw_value

            field_datas.append(
                FieldData(
                    field_def=field_def,
                    field=field,
                    parent_field=parent_field,
                    value=value,
                    raw_value=raw_value,
                ))

        # Apply timestamp field if we got a header
        if header.time_offset is not None:
            ts_value = self._compressed_ts_accumulator = self._apply_compressed_accumulation(
                header.time_offset,
                self._compressed_ts_accumulator,
                5,
            )
            field_datas.append(
                FieldData(
                    field_def=None,
                    field=FIELD_TYPE_TIMESTAMP,
                    parent_field=None,
                    value=FIELD_TYPE_TIMESTAMP.render(ts_value),
                    raw_value=ts_value,
                ))

        # Apply data processors
        for field_data in field_datas:
            # Apply type name processor
            type_processor = getattr(self._processor,
                                     'process_type_%s' % field_data.type.name,
                                     None)
            if type_processor:
                type_processor(field_data)

            # Apply field name processor
            field_processor = getattr(self._processor,
                                      'process_field_%s' % field_data.name,
                                      None)
            if field_processor:
                field_processor(field_data)

            # Apply units name processor
            if field_data.units:
                process_func_name = 'process_units_%s' % field_data.units
                # Do unit name replacements padded with spaces
                for replace_from, replace_to in self.UNIT_NAME_TO_FUNC_REPLACEMENTS:
                    process_func_name = process_func_name.replace(
                        replace_from,
                        ' %s ' % replace_to,
                    )
                # Then strip and convert spaces to underscores
                process_func_name = process_func_name.strip().replace(' ', '_')
                units_processor = getattr(self._processor, process_func_name,
                                          None)
                if units_processor:
                    units_processor(field_data)

        data_message = DataMessage(header=header,
                                   def_mesg=def_mesg,
                                   fields=field_datas)

        mesg_processor = getattr(self._processor,
                                 'process_message_%s' % def_mesg.name, None)
        if mesg_processor:
            mesg_processor(data_message)

        return data_message