# Path: ogn/parser/pattern.py
# PATTERN_TRACKER_POSITION_COMMENT = re.compile(r"""
#     id(?P<details>[\dA-F]{2})(?P<address>[\dA-F]{6}?)\s?
#     (?:(?P<climb_rate>[+-]\d+?)fpm\s)?
#     (?:(?P<turn_rate>[+-][\d.]+?)rot\s)?
#     (?:FL(?P<flight_level>[\d.]+)\s)?
#     (?:(?P<signal_quality>[\d.]+?)dB\s)?
#     (?:(?P<error_count>\d+)e\s)?
#     (?:(?P<frequency_offset>[+-][\d.]+?)kHz\s?)?
#     (?:gps(?P<gps_quality>(?P<gps_quality_horizontal>(\d+))x(?P<gps_quality_vertical>(\d+)))\s?)?
#     (?:(?P<signal_power>[+-][\d.]+)dBm\s?)?
# """, re.VERBOSE | re.MULTILINE)
# 
# PATTERN_TRACKER_STATUS_COMMENT = re.compile(r"""
#     h(?P<hardware_version>[\d]{2})\s
#     v(?P<software_version>[\d]{2})\s?
#     (?:(?P<gps_satellites>[\d]+)sat/(?P<gps_quality>\d)\s?)?
#     (?:(?P<gps_altitude>\d+)m\s?)?
#     (?:(?P<pressure>[\d.]+)hPa\s?)?
#     (?:(?P<temperature>[+-][\d.]+)degC\s?)?
#     (?:(?P<humidity>\d+)%\s?)?
#     (?:(?P<voltage>[\d.]+)V\s?)?
#     (?:(?P<transmitter_power>\d+)/(?P<noise_level>[+-][\d.]+)dBm\s?)?
#     (?:(?P<relays>\d+)/min)?
# """, re.VERBOSE | re.MULTILINE)
# 
# Path: ogn/parser/utils.py
# FPM_TO_MS = FEETS_TO_METER / 60     # ratio fpm to m/s
# 
# HPM_TO_DEGS = 180 / 60              # ratio between half turn per minute and degrees/s
# 
# Path: ogn/parser/aprs_comment/base.py
# class BaseParser():
#     def __init__(self):
#         self.beacon_type = 'unknown'
# 
#     def parse(self, aprs_comment, aprs_type):
#         if aprs_type.startswith('position'):
#             data = self.parse_position(aprs_comment)
#         elif aprs_type.startswith('status'):
#             data = self.parse_status(aprs_comment)
#         else:
#             raise ValueError("aprs_type {} unknown".format(aprs_type))
#         data.update({'beacon_type': self.beacon_type})
#         return data
# 
#     def parse_position(self, aprs_comment):
#         raise NotImplementedError("Position parser for parser '{}' not yet implemented".format(self.beacon_type))
# 
#     def parse_status(self, aprs_comment):
#         raise NotImplementedError("Status parser for parser '{}' not yet implemented".format(self.beacon_type))


from ogn.parser.pattern import PATTERN_TRACKER_POSITION_COMMENT, PATTERN_TRACKER_STATUS_COMMENT
from ogn.parser.utils import FPM_TO_MS, HPM_TO_DEGS
from .base import BaseParser
        if match.group('signal_quality'): result['signal_quality'] = float(match.group('signal_quality'))
        if match.group('error_count'): result['error_count'] = int(match.group('error_count'))
        if match.group('frequency_offset'): result['frequency_offset'] = float(match.group('frequency_offset'))
        if match.group('gps_quality'):
            result.update({
                'gps_quality': {
                    'horizontal': int(match.group('gps_quality_horizontal')),
                    'vertical': int(match.group('gps_quality_vertical'))
                }
            })
        if match.group('signal_power'): result['signal_power'] = float(match.group('signal_power'))
        return result

    def parse_status(self, aprs_comment):
        match = self.status_pattern.match(aprs_comment)
        if match:
            result = {}

            if match.group('hardware_version'): result['hardware_version'] = int(match.group('hardware_version'))
            if match.group('software_version'): result['software_version'] = int(match.group('software_version'))
            if match.group('gps_satellites'): result['gps_satellites'] = int(match.group('gps_satellites'))
            if match.group('gps_quality'): result['gps_quality'] = int(match.group('gps_quality'))
            if match.group('gps_altitude'): result['gps_altitude'] = int(match.group('gps_altitude'))
            if match.group('pressure'): result['pressure'] = float(match.group('pressure'))
            if match.group('temperature'): result['temperature'] = float(match.group('temperature'))
            if match.group('humidity'): result['humidity'] = int(match.group('humidity'))
            if match.group('voltage'): result['voltage'] = float(match.group('voltage'))
            if match.group('transmitter_power'): result['transmitter_power'] = int(match.group('transmitter_power'))
            if match.group('noise_level'): result['noise_level'] = float(match.group('noise_level'))
            if match.group('relays'): result['relays'] = int(match.group('relays'))

# Path: ogn/parser/pattern.py
# PATTERN_TRACKER_POSITION_COMMENT = re.compile(r"""
#     id(?P<details>[\dA-F]{2})(?P<address>[\dA-F]{6}?)\s?
#     (?:(?P<climb_rate>[+-]\d+?)fpm\s)?
#     (?:(?P<turn_rate>[+-][\d.]+?)rot\s)?
#     (?:FL(?P<flight_level>[\d.]+)\s)?
#     (?:(?P<signal_quality>[\d.]+?)dB\s)?
#     (?:(?P<error_count>\d+)e\s)?
#     (?:(?P<frequency_offset>[+-][\d.]+?)kHz\s?)?
#     (?:gps(?P<gps_quality>(?P<gps_quality_horizontal>(\d+))x(?P<gps_quality_vertical>(\d+)))\s?)?
#     (?:(?P<signal_power>[+-][\d.]+)dBm\s?)?
# """, re.VERBOSE | re.MULTILINE)
# 
# PATTERN_TRACKER_STATUS_COMMENT = re.compile(r"""
#     h(?P<hardware_version>[\d]{2})\s
#     v(?P<software_version>[\d]{2})\s?
#     (?:(?P<gps_satellites>[\d]+)sat/(?P<gps_quality>\d)\s?)?
#     (?:(?P<gps_altitude>\d+)m\s?)?
#     (?:(?P<pressure>[\d.]+)hPa\s?)?
#     (?:(?P<temperature>[+-][\d.]+)degC\s?)?
#     (?:(?P<humidity>\d+)%\s?)?
#     (?:(?P<voltage>[\d.]+)V\s?)?
#     (?:(?P<transmitter_power>\d+)/(?P<noise_level>[+-][\d.]+)dBm\s?)?
#     (?:(?P<relays>\d+)/min)?
# """, re.VERBOSE | re.MULTILINE)
# 
# Path: ogn/parser/utils.py
# FPM_TO_MS = FEETS_TO_METER / 60     # ratio fpm to m/s
# 
# HPM_TO_DEGS = 180 / 60              # ratio between half turn per minute and degrees/s
# 
# Path: ogn/parser/aprs_comment/base.py
# class BaseParser():
#     def __init__(self):
#         self.beacon_type = 'unknown'
# 
#     def parse(self, aprs_comment, aprs_type):
#         if aprs_type.startswith('position'):
#             data = self.parse_position(aprs_comment)
#         elif aprs_type.startswith('status'):
#             data = self.parse_status(aprs_comment)
#         else:
#             raise ValueError("aprs_type {} unknown".format(aprs_type))
#         data.update({'beacon_type': self.beacon_type})
#         return data
# 
#     def parse_position(self, aprs_comment):
#         raise NotImplementedError("Position parser for parser '{}' not yet implemented".format(self.beacon_type))
# 
#     def parse_status(self, aprs_comment):
#         raise NotImplementedError("Status parser for parser '{}' not yet implemented".format(self.beacon_type))


# Path: ogn/parser/aprs_comment/tracker_parser.py
from ogn.parser.pattern import PATTERN_TRACKER_POSITION_COMMENT, PATTERN_TRACKER_STATUS_COMMENT
from ogn.parser.utils import FPM_TO_MS, HPM_TO_DEGS
from .base import BaseParser

        if match.group('signal_quality'): result['signal_quality'] = float(match.group('signal_quality'))
        if match.group('error_count'): result['error_count'] = int(match.group('error_count'))
        if match.group('frequency_offset'): result['frequency_offset'] = float(match.group('frequency_offset'))
        if match.group('gps_quality'):
            result.update({
                'gps_quality': {
                    'horizontal': int(match.group('gps_quality_horizontal')),
                    'vertical': int(match.group('gps_quality_vertical'))
                }
            })
        if match.group('signal_power'): result['signal_power'] = float(match.group('signal_power'))
        return result

    def parse_status(self, aprs_comment):
        match = self.status_pattern.match(aprs_comment)
        if match:
            result = {}

            if match.group('hardware_version'): result['hardware_version'] = int(match.group('hardware_version'))
            if match.group('software_version'): result['software_version'] = int(match.group('software_version'))
            if match.group('gps_satellites'): result['gps_satellites'] = int(match.group('gps_satellites'))
            if match.group('gps_quality'): result['gps_quality'] = int(match.group('gps_quality'))
            if match.group('gps_altitude'): result['gps_altitude'] = int(match.group('gps_altitude'))
            if match.group('pressure'): result['pressure'] = float(match.group('pressure'))
            if match.group('temperature'): result['temperature'] = float(match.group('temperature'))
            if match.group('humidity'): result['humidity'] = int(match.group('humidity'))
            if match.group('voltage'): result['voltage'] = float(match.group('voltage'))
            if match.group('transmitter_power'): result['transmitter_power'] = int(match.group('transmitter_power'))
            if match.group('noise_level'): result['noise_level'] = float(match.group('noise_level'))
            if match.group('relays'): result['relays'] = int(match.group('relays'))

            return result