예제 #1
0
def parse_aprs(message, reference_date=None, reference_time=None):
    if reference_date is None:
        now = datetime.utcnow()
        reference_date = now.date()
        reference_time = now.time()

    match_position = re.search(PATTERN_APRS_POSITION, message)
    if match_position:
        return {'name': match_position.group('callsign'),
                'receiver_name': match_position.group('receiver'),
                'dstcall': match_position.group('dstcall'),
                'timestamp': createTimestamp(match_position.group('time'), reference_date, reference_time),
                'latitude': parseAngle('0' + match_position.group('latitude') + (match_position.group('latitude_enhancement') or '0')) *
                (-1 if match_position.group('latitude_sign') == 'S' else 1),
                'symboltable': match_position.group('symbol_table'),
                'longitude': parseAngle(match_position.group('longitude') + (match_position.group('longitude_enhancement') or '0')) *
                (-1 if match_position.group('longitude_sign') == 'W' else 1),
                'symbolcode': match_position.group('symbol'),
                'track': int(match_position.group('course')) if match_position.group('course_extension') else None,
                'ground_speed': int(match_position.group('ground_speed')) * kts2kmh if match_position.group('ground_speed') else None,
                'altitude': int(match_position.group('altitude')) * feet2m,
                'comment': match_position.group('comment')}

    match_status = re.search(PATTERN_APRS_STATUS, message)
    if match_status:
        return {'name': match_status.group('callsign'),
                'receiver_name': match_status.group('receiver'),
                'dstcall': match_status.group('dstcall'),
                'timestamp': createTimestamp(match_status.group('time'), reference_date, reference_time),
                'comment': match_status.group('comment')}

    raise AprsParseError(message)
예제 #2
0
    def test_createTimestamp(self):
        test_data = [
            ('000001', date(2015, 1, 10), time(0, 0, 1),
             datetime(2015, 1, 10, 0, 0,
                      1)),  # packet from current day (on the tick)
            ('235959', date(2015, 1, 10), time(0, 0, 1),
             datetime(2015, 1, 9, 23, 59,
                      59)),  # packet from previous day (2 seconds old)
            ('110000', date(2015, 1, 10), time(0, 0, 1),
             None),  # packet 11 hours from future or 13 hours old
            ('123500', date(2015, 1, 10), time(23, 50, 0),
             datetime(2015, 1, 10, 12, 35,
                      0)),  # packet from current day (11 hours old)
            ('000001', date(2015, 1, 10), time(23, 50, 0),
             datetime(2015, 1, 11, 0, 0,
                      1)),  # packet from next day (11 minutes from future)
            ('000001', date(2015, 1, 10), None,
             datetime(2015, 1, 10, 0, 0, 1)),  # first packet of a specific day
            ('235959', date(2015, 1, 10), None,
             datetime(2015, 1, 10, 23, 59,
                      59)),  # last packet of a specific day
        ]

        for test in test_data:
            if test[3]:
                timestamp = createTimestamp(test[0],
                                            reference_date=test[1],
                                            reference_time=test[2])
                self.assertEqual(timestamp, test[3])
            else:
                with self.assertRaises(AmbigousTimeError):
                    createTimestamp(test[0],
                                    reference_date=test[1],
                                    reference_time=test[2])
def parse(telnet_data):
    reference_timestamp = datetime.utcnow()

    try:
        return {'pps_offset': float(telnet_data[0:5]),
                'frequency': float(telnet_data[9:16]),
                'aircraft_type': int(telnet_data[20:24]),
                'address_type': int(telnet_data[25]),
                'address': telnet_data[27:33],
                'timestamp': createTimestamp(telnet_data[34:40] + 'h', reference_timestamp),
                'latitude': float(telnet_data[43:53]),
                'longitude': float(telnet_data[54:64]),
                'altitude': int(telnet_data[68:73]),
                'climb_rate': float(telnet_data[74:80]),
                'ground_speed': float(telnet_data[83:89]),
                'track': float(telnet_data[92:98]),
                'turn_rate': float(telnet_data[101:107]),
                'magic_number': int(telnet_data[114:116]),
                'gps_status': telnet_data[117:122],
                'frequency_offset': float(telnet_data[123:129]),
                'signal_quality': float(telnet_data[132:137]),
                'error_count': float(telnet_data[139:142]),
                'distance': float(telnet_data[143:150]),
                'bearing': float(telnet_data[152:158]),
                'phi': float(telnet_data[161:167])}
    except:
        raise ParseError
예제 #4
0
def parse(telnet_data):
    reference_timestamp = datetime.utcnow()

    match = telnet_50001_pattern.match(telnet_data)
    if match:
        return {'pps_offset': float(match.group('pps_offset')),
                'frequency': float(match.group('frequency')),
                'aircraft_type': int(match.group('aircraft_type')),
                'address_type': int(match.group('address_type')),
                'address': match.group('address'),
                'timestamp': createTimestamp(match.group('timestamp') + 'h', reference_timestamp),
                'latitude': float(match.group('latitude')),
                'longitude': float(match.group('longitude')),
                'altitude': int(match.group('altitude')),
                'climb_rate': float(match.group('climb_rate')),
                'ground_speed': float(match.group('ground_speed')),
                'track': float(match.group('track')),
                'turn_rate': float(match.group('turn_rate')),
                'magic_number': int(match.group('magic_number')),
                'gps_status': match.group('gps_status'),
                'channel': int(match.group('channel')),
                'flarm_timeslot': match.group('flarm_timeslot') == 'f',
                'ogn_timeslot': match.group('ogn_timeslot') == 'o',
                'frequency_offset': float(match.group('frequency_offset')),
                'decode_quality': float(match.group('decode_quality')),
                'signal_quality': float(match.group('signal_quality')),
                'demodulator_type': int(match.group('demodulator_type')),
                'error_count': float(match.group('error_count')),
                'distance': float(match.group('distance')),
                'bearing': float(match.group('bearing')),
                'phi': float(match.group('phi')),
                'multichannel': match.group('multichannel') == '+'}
    else:
        return None
예제 #5
0
    def test_createTimestamp(self):
        test_data = [
            ('000001', datetime(2015, 1, 10, 0, 0, 1), datetime(2015, 1, 10, 0, 0, 1)),      # packet from current day (on the tick)
            ('235959', datetime(2015, 1, 10, 0, 0, 1), datetime(2015, 1, 9, 23, 59, 59)),    # packet from previous day (2 seconds old)
            ('110000', datetime(2015, 1, 10, 0, 0, 1), None),                                # packet 11 hours from future or 13 hours old
            ('123500', datetime(2015, 1, 10, 23, 50, 0), datetime(2015, 1, 10, 12, 35, 0)),  # packet from current day (11 hours old)
            ('000001', datetime(2015, 1, 10, 23, 50, 0), datetime(2015, 1, 11, 0, 0, 1))     # packet from next day (11 minutes from future)
        ]

        for test in test_data:
            if test[2]:
                timestamp = createTimestamp(test[0], reference=test[1])
                self.assertEqual(timestamp, test[2])
            else:
                with self.assertRaises(AmbigousTimeError):
                    createTimestamp(test[0], reference=test[1])
def parse(telnet_data):
    reference_timestamp = datetime.utcnow()

    try:
        return {
            'pps_offset':
            float(telnet_data[0:5]),
            'frequency':
            float(telnet_data[9:16]),
            'aircraft_type':
            int(telnet_data[20:24]),
            'address_type':
            int(telnet_data[25]),
            'address':
            telnet_data[27:33],
            'timestamp':
            createTimestamp(telnet_data[34:40] + 'h', reference_timestamp),
            'latitude':
            float(telnet_data[43:53]),
            'longitude':
            float(telnet_data[54:64]),
            'altitude':
            int(telnet_data[68:73]),
            'climb_rate':
            float(telnet_data[74:80]),
            'ground_speed':
            float(telnet_data[83:89]),
            'track':
            float(telnet_data[92:98]),
            'turn_rate':
            float(telnet_data[101:107]),
            'magic_number':
            int(telnet_data[114:116]),
            'gps_status':
            telnet_data[117:122],
            'frequency_offset':
            float(telnet_data[123:129]),
            'signal_quality':
            float(telnet_data[132:137]),
            'error_count':
            float(telnet_data[139:142]),
            'distance':
            float(telnet_data[143:150]),
            'bearing':
            float(telnet_data[152:158]),
            'phi':
            float(telnet_data[161:167])
        }
    except:
        raise ParseError
예제 #7
0
def parse_aprs(message, reference_date=None):
    if reference_date is None:
        reference_date = datetime.utcnow()

    match = re.search(PATTERN_APRS, message)
    if match:
        return {
            'name':
            match.group('callsign'),
            'receiver_name':
            match.group('receiver'),
            'timestamp':
            createTimestamp(match.group('time'), reference_date),
            'latitude':
            dmsToDeg(float(match.group('latitude')) / 100) *
            (-1 if match.group('latitude_sign') == 'S' else 1) +
            (int(match.group('latitude_enhancement')) / 1000 /
             60 if match.group('latitude_enhancement') else 0),
            'symboltable':
            match.group('symbol_table'),
            'longitude':
            dmsToDeg(float(match.group('longitude')) / 100) *
            (-1 if match.group('longitude_sign') == 'W' else 1) +
            (int(match.group('longitude_enhancement')) / 1000 /
             60 if match.group('longitude_enhancement') else 0),
            'symbolcode':
            match.group('symbol'),
            'track':
            int(match.group('course'))
            if match.group('course_extension') else 0,
            'ground_speed':
            int(match.group('ground_speed')) *
            kts2kmh if match.group('ground_speed') else 0,
            'altitude':
            int(match.group('altitude')) * feet2m,
            'comment':
            match.group('comment')
        }

    raise AprsParseError(message)
예제 #8
0
def parse_aprs(message, reference_date=None):
    if reference_date is None:
        reference_date = datetime.utcnow()

    match = re.search(PATTERN_APRS, message)
    if match:
        return {'name': match.group('callsign'),
                'receiver_name': match.group('receiver'),
                'timestamp': createTimestamp(match.group('time'), reference_date),
                'latitude': dmsToDeg(float(match.group('latitude')) / 100) *
                (-1 if match.group('latitude_sign') == 'S' else 1) +
                (int(match.group('latitude_enhancement')) / 1000 / 60 if match.group('latitude_enhancement') else 0),
                'symboltable': match.group('symbol_table'),
                'longitude': dmsToDeg(float(match.group('longitude')) / 100) *
                (-1 if match.group('longitude_sign') == 'W' else 1) +
                (int(match.group('longitude_enhancement')) / 1000 / 60 if match.group('longitude_enhancement') else 0),
                'symbolcode': match.group('symbol'),
                'track': int(match.group('course')) if match.group('course_extension') else 0,
                'ground_speed': int(match.group('ground_speed')) * kts2kmh if match.group('ground_speed') else 0,
                'altitude': int(match.group('altitude')) * feet2m,
                'comment': match.group('comment')}

    raise AprsParseError(message)
예제 #9
0
def parse_aprs(message, reference_timestamp=None):
    if reference_timestamp is None:
        reference_timestamp = datetime.utcnow()

    result = {
        'raw_message': message,
        'reference_timestamp': reference_timestamp
    }

    if message and message[0] == '#':
        match_server = re.search(PATTERN_SERVER, message)
        if match_server:
            result.update({
                'version':
                match_server.group('version'),
                'timestamp':
                datetime.strptime(match_server.group('timestamp'),
                                  "%d %b %Y %H:%M:%S %Z"),
                'server':
                match_server.group('server'),
                'ip_address':
                match_server.group('ip_address'),
                'port':
                match_server.group('port'),
                'aprs_type':
                'server'
            })
        else:
            result.update({'comment': message, 'aprs_type': 'comment'})

    else:
        match = re.search(PATTERN_APRS, message)
        if match:
            aprs_type = 'position' if match.group(
                'aprs_type') == '/' else 'status' if match.group(
                    'aprs_type') == '>' else 'unknown'
            result.update({'aprs_type': aprs_type})
            aprs_body = match.group('aprs_body')
            if aprs_type == 'position':
                match_position = re.search(PATTERN_APRS_POSITION, aprs_body)
                if match_position:
                    result.update({
                        'name':
                        match.group('callsign'),
                        'dstcall':
                        match.group('dstcall'),
                        'relay':
                        match.group('relay') if match.group('relay') else None,
                        'receiver_name':
                        match.group('receiver'),
                        'timestamp':
                        createTimestamp(match_position.group('time'),
                                        reference_timestamp),
                        'latitude':
                        parseAngle('0' + match_position.group('latitude') +
                                   (match_position.group(
                                       'latitude_enhancement') or '0'))
                        *  # noqa: W504
                        (-1 if match_position.group('latitude_sign') == 'S'
                         else 1),
                        'symboltable':
                        match_position.group('symbol_table'),
                        'longitude':
                        parseAngle(
                            match_position.group('longitude') +
                            (match_position.group('longitude_enhancement')
                             or '0')) *  # noqa: W504
                        (-1 if match_position.group('longitude_sign') == 'W'
                         else 1),
                        'symbolcode':
                        match_position.group('symbol'),
                        'track':
                        int(match_position.group('course'))
                        if match_position.group('course_extension') else None,
                        'ground_speed':
                        int(match_position.group('ground_speed')) *
                        KNOTS_TO_MS / KPH_TO_MS
                        if match_position.group('ground_speed') else None,
                        'altitude':
                        int(match_position.group('altitude')) * FEETS_TO_METER
                        if match_position.group('altitude') else None,
                        'aircrafttype':
                        get_aircraft_type(match_position.group('symbol_table'),
                                          match_position.group('symbol')),
                        'comment':
                        match_position.group('comment')
                        if match_position.group('comment') else ""
                    })
                else:
                    raise AprsParseError(message)
            elif aprs_type == 'status':
                match_status = re.search(PATTERN_APRS_STATUS, aprs_body)
                if match_status:
                    result.update({
                        'name':
                        match.group('callsign'),
                        'dstcall':
                        match.group('dstcall'),
                        'receiver_name':
                        match.group('receiver'),
                        'timestamp':
                        createTimestamp(match_status.group('time'),
                                        reference_timestamp),
                        'comment':
                        match_status.group('comment')
                        if match_status.group('comment') else ""
                    })
                else:
                    raise NotImplementedError(message)
        else:
            raise AprsParseError(message)

    return result
 def proceed_test_data(self, test_data={}):
     for test in test_data:
         timestamp = createTimestamp(test[0], reference_timestamp=test[1])
         self.assertEqual(timestamp, test[2])
예제 #11
0
 def proceed_test_data(self, test_data={}):
     for test in test_data:
         timestamp = createTimestamp(test[0], reference_timestamp=test[1])
         self.assertEqual(timestamp, test[2])
예제 #12
0
def parse_aprs(message, reference_timestamp=None):
    if reference_timestamp is None:
        reference_timestamp = datetime.utcnow()

    result = {
        'raw_message': message,
        'reference_timestamp': reference_timestamp
    }

    if message and message[0] == '#':
        match_server = re.search(PATTERN_SERVER, message)
        if match_server:
            result.update({
                'version':
                match_server.group('version'),
                'timestamp':
                datetime.strptime(match_server.group('timestamp'),
                                  "%d %b %Y %H:%M:%S %Z"),
                'server':
                match_server.group('server'),
                'ip_address':
                match_server.group('ip_address'),
                'port':
                match_server.group('port'),
                'aprs_type':
                'server'
            })
        else:
            result.update({'comment': message, 'aprs_type': 'comment'})
    else:
        match = re.search(PATTERN_APRS, message)
        if match:
            aprs_type = 'position' if match.group(
                'aprs_type') == '/' else 'status' if match.group(
                    'aprs_type') == '>' else 'unknown'
            result.update({'aprs_type': aprs_type})
            aprs_body = match.group('aprs_body')
            if aprs_type == 'position':
                match_position = re.search(PATTERN_APRS_POSITION, aprs_body)
                if match_position:
                    result.update({
                        'name':
                        match.group('callsign'),
                        'dstcall':
                        match.group('dstcall'),
                        'relay':
                        match.group('relay') if match.group('relay') else None,
                        'receiver_name':
                        match.group('receiver'),
                        'timestamp':
                        createTimestamp(match_position.group('time'),
                                        reference_timestamp),
                        'latitude':
                        parseAngle('0' + match_position.group('latitude') +
                                   (match_position.group(
                                       'latitude_enhancement') or '0'))
                        *  # noqa: W504
                        (-1 if match_position.group('latitude_sign') == 'S'
                         else 1),
                        'symboltable':
                        match_position.group('symbol_table'),
                        'longitude':
                        parseAngle(
                            match_position.group('longitude') +
                            (match_position.group('longitude_enhancement')
                             or '0')) *  # noqa: W504
                        (-1 if match_position.group('longitude_sign') == 'W'
                         else 1),
                        'symbolcode':
                        match_position.group('symbol'),
                        'track':
                        int(match_position.group('course'))
                        if match_position.group('course_extension') else None,
                        'ground_speed':
                        int(match_position.group('ground_speed')) *
                        KNOTS_TO_MS / KPH_TO_MS
                        if match_position.group('ground_speed') else None,
                        'altitude':
                        int(match_position.group('altitude')) * FEETS_TO_METER
                        if match_position.group('altitude') else None,
                        'comment':
                        match_position.group('comment')
                        if match_position.group('comment') else "",
                    })
                    return result

                match_position_weather = re.search(
                    PATTERN_APRS_POSITION_WEATHER, aprs_body)
                if match_position_weather:
                    result.update({
                        'aprs_type':
                        'position_weather',
                        'name':
                        match.group('callsign'),
                        'dstcall':
                        match.group('dstcall'),
                        'relay':
                        match.group('relay') if match.group('relay') else None,
                        'receiver_name':
                        match.group('receiver'),
                        'timestamp':
                        createTimestamp(match_position_weather.group('time'),
                                        reference_timestamp),
                        'latitude':
                        parseAngle('0' +
                                   match_position_weather.group('latitude'))
                        *  # noqa: W504
                        (-1 if match_position_weather.group('latitude_sign')
                         == 'S' else 1),
                        'symboltable':
                        match_position_weather.group('symbol_table'),
                        'longitude':
                        parseAngle(match_position_weather.group('longitude'))
                        *  # noqa: W504
                        (-1 if match_position_weather.group('longitude_sign')
                         == 'W' else 1),
                        'symbolcode':
                        match_position_weather.group('symbol'),
                        'wind_direction':
                        int(match_position_weather.group('wind_direction')) if
                        match_position_weather.group('wind_direction') != '...'
                        else None,
                        'wind_speed':
                        int(match_position_weather.group('wind_speed')) *
                        KNOTS_TO_MS / KPH_TO_MS
                        if match_position_weather.group('wind_speed') != '...'
                        else None,
                        'wind_speed_peak':
                        int(match_position_weather.group('wind_speed_peak')) *
                        KNOTS_TO_MS / KPH_TO_MS
                        if match_position_weather.group('wind_speed_peak') !=
                        '...' else None,
                        'temperature':
                        fahrenheit_to_celsius(
                            float(match_position_weather.group('temperature')))
                        if match_position_weather.group('temperature') != '...'
                        else None,
                        'rainfall_1h':
                        int(match_position_weather.group('rainfall_1h')) /
                        100.0 * INCH_TO_MM if
                        match_position_weather.group('rainfall_1h') else None,
                        'rainfall_24h':
                        int(match_position_weather.group('rainfall_24h')) /
                        100.0 * INCH_TO_MM if
                        match_position_weather.group('rainfall_24h') else None,
                        'humidity':
                        int(match_position_weather.group('humidity')) * 0.01
                        if match_position_weather.group('humidity') else None,
                        'barometric_pressure':
                        int(match_position_weather.group(
                            'barometric_pressure'))
                        if match_position_weather.group('barometric_pressure')
                        else None,
                        'comment':
                        match_position_weather.group('comment')
                        if match_position_weather.group('comment') else "",
                    })
                    return result

                raise AprsParseError(message)
            elif aprs_type == 'status':
                match_status = re.search(PATTERN_APRS_STATUS, aprs_body)
                if match_status:
                    result.update({
                        'name':
                        match.group('callsign'),
                        'dstcall':
                        match.group('dstcall'),
                        'receiver_name':
                        match.group('receiver'),
                        'timestamp':
                        createTimestamp(match_status.group('time'),
                                        reference_timestamp),
                        'comment':
                        match_status.group('comment')
                        if match_status.group('comment') else ""
                    })
                else:
                    raise NotImplementedError(message)
        else:
            raise AprsParseError(message)

    return result
예제 #13
0
def parse_aprs(message, reference_timestamp=None):
    if reference_timestamp is None:
        reference_timestamp = datetime.utcnow()

    result = {'raw_message': message,
              'reference_timestamp': reference_timestamp}

    if message and message[0] == '#':
        match_server = re.search(PATTERN_SERVER, message)
        if match_server:
            result.update({
                'version': match_server.group('version'),
                'timestamp': datetime.strptime(match_server.group('timestamp'), "%d %b %Y %H:%M:%S %Z"),
                'server': match_server.group('server'),
                'ip_address': match_server.group('ip_address'),
                'port': match_server.group('port'),
                'aprs_type': 'server'})
        else:
            result.update({
                'comment': message,
                'aprs_type': 'comment'})

    else:
        match = re.search(PATTERN_APRS, message)
        if match:
            aprs_type = 'position' if match.group('aprs_type') == '/' else 'status'
            result.update({'aprs_type': aprs_type})
            aprs_body = match.group('aprs_body')
            if aprs_type == 'position':
                match_position = re.search(PATTERN_APRS_POSITION, aprs_body)
                if match_position:
                    result.update({
                        'name': match.group('callsign'),
                        'dstcall': match.group('dstcall'),
                        'relay': match.group('relay') if match.group('relay') else None,
                        'receiver_name': match.group('receiver'),
                        'timestamp': createTimestamp(match_position.group('time'), reference_timestamp),
                        'latitude': parseAngle('0' + match_position.group('latitude') + (match_position.group('latitude_enhancement') or '0')) *
                        (-1 if match_position.group('latitude_sign') == 'S' else 1),
                        'symboltable': match_position.group('symbol_table'),
                        'longitude': parseAngle(match_position.group('longitude') + (match_position.group('longitude_enhancement') or '0')) *
                        (-1 if match_position.group('longitude_sign') == 'W' else 1),
                        'symbolcode': match_position.group('symbol'),
                        'track': int(match_position.group('course')) if match_position.group('course_extension') else None,
                        'ground_speed': int(match_position.group('ground_speed')) * KNOTS_TO_MS / KPH_TO_MS if match_position.group('ground_speed') else None,
                        'altitude': int(match_position.group('altitude')) * FEETS_TO_METER,
                        'comment': match_position.group('comment') if match_position.group('comment') else ""})
                else:
                    raise AprsParseError(message)
            elif aprs_type == 'status':
                match_status = re.search(PATTERN_APRS_STATUS, aprs_body)
                if match_status:
                    result.update({
                        'name': match.group('callsign'),
                        'dstcall': match.group('dstcall'),
                        'receiver_name': match.group('receiver'),
                        'timestamp': createTimestamp(match_status.group('time'), reference_timestamp),
                        'comment': match_status.group('comment') if match_status.group('comment') else ""})
                else:
                    raise AprsParseError(message)
        else:
            raise AprsParseError(message)

    return result