kopia lustrzana https://github.com/glidernet/python-ogn-client
Merge pull request #15 from Meisterschueler/feature/+protocol_0.2.5
Implemented new receiver protocol for 0.2.5pull/16/head
commit
e3de256060
|
@ -1,6 +1,7 @@
|
||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
- updated the parser for the 0.2.5 protocol
|
||||||
|
|
||||||
## 0.5.0 - 2016-09-29
|
## 0.5.0 - 2016-09-29
|
||||||
- Added aprs destination callsign as `dstcall` to aprs beacon keys (#9)
|
- Added aprs destination callsign as `dstcall` to aprs beacon keys (#9)
|
||||||
|
|
|
@ -2,7 +2,7 @@ import re
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from ogn.parser.utils import createTimestamp, parseAngle, kts2kmh, feet2m, fpm2ms
|
from ogn.parser.utils import createTimestamp, parseAngle, kts2kmh, feet2m, fpm2ms
|
||||||
from ogn.parser.pattern import PATTERN_APRS, PATTERN_RECEIVER_BEACON, PATTERN_AIRCRAFT_BEACON
|
from ogn.parser.pattern import PATTERN_APRS_POSITION, PATTERN_APRS_STATUS, PATTERN_RECEIVER_BEACON, PATTERN_AIRCRAFT_BEACON
|
||||||
from ogn.parser.exceptions import AprsParseError, OgnParseError
|
from ogn.parser.exceptions import AprsParseError, OgnParseError
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,22 +12,30 @@ def parse_aprs(message, reference_date=None, reference_time=None):
|
||||||
reference_date = now.date()
|
reference_date = now.date()
|
||||||
reference_time = now.time()
|
reference_time = now.time()
|
||||||
|
|
||||||
match = re.search(PATTERN_APRS, message)
|
match_position = re.search(PATTERN_APRS_POSITION, message)
|
||||||
if match:
|
if match_position:
|
||||||
return {'name': match.group('callsign'),
|
return {'name': match_position.group('callsign'),
|
||||||
'receiver_name': match.group('receiver'),
|
'receiver_name': match_position.group('receiver'),
|
||||||
'dstcall': match.group('dstcall'),
|
'dstcall': match_position.group('dstcall'),
|
||||||
'timestamp': createTimestamp(match.group('time'), reference_date, reference_time),
|
'timestamp': createTimestamp(match_position.group('time'), reference_date, reference_time),
|
||||||
'latitude': parseAngle('0' + match.group('latitude') + (match.group('latitude_enhancement') or '0')) *
|
'latitude': parseAngle('0' + match_position.group('latitude') + (match_position.group('latitude_enhancement') or '0')) *
|
||||||
(-1 if match.group('latitude_sign') == 'S' else 1),
|
(-1 if match_position.group('latitude_sign') == 'S' else 1),
|
||||||
'symboltable': match.group('symbol_table'),
|
'symboltable': match_position.group('symbol_table'),
|
||||||
'longitude': parseAngle(match.group('longitude') + (match.group('longitude_enhancement') or '0')) *
|
'longitude': parseAngle(match_position.group('longitude') + (match_position.group('longitude_enhancement') or '0')) *
|
||||||
(-1 if match.group('longitude_sign') == 'W' else 1),
|
(-1 if match_position.group('longitude_sign') == 'W' else 1),
|
||||||
'symbolcode': match.group('symbol'),
|
'symbolcode': match_position.group('symbol'),
|
||||||
'track': int(match.group('course')) if match.group('course_extension') else 0,
|
'track': int(match_position.group('course')) if match_position.group('course_extension') else 0,
|
||||||
'ground_speed': int(match.group('ground_speed')) * kts2kmh if match.group('ground_speed') else 0,
|
'ground_speed': int(match_position.group('ground_speed')) * kts2kmh if match_position.group('ground_speed') else 0,
|
||||||
'altitude': int(match.group('altitude')) * feet2m,
|
'altitude': int(match_position.group('altitude')) * feet2m,
|
||||||
'comment': match.group('comment')}
|
'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)
|
raise AprsParseError(message)
|
||||||
|
|
||||||
|
@ -42,13 +50,14 @@ def parse_ogn_aircraft_beacon(aprs_comment):
|
||||||
'climb_rate': int(ac_match.group('climb_rate')) * fpm2ms,
|
'climb_rate': int(ac_match.group('climb_rate')) * fpm2ms,
|
||||||
'turn_rate': float(ac_match.group('turn_rate')),
|
'turn_rate': float(ac_match.group('turn_rate')),
|
||||||
'flightlevel': float(ac_match.group('flight_level')) if ac_match.group('flight_level') else None,
|
'flightlevel': float(ac_match.group('flight_level')) if ac_match.group('flight_level') else None,
|
||||||
'signal_strength': float(ac_match.group('signal')),
|
'signal_quality': float(ac_match.group('signal_quality')),
|
||||||
'error_count': float(ac_match.group('errors')),
|
'error_count': float(ac_match.group('errors')),
|
||||||
'frequency_offset': float(ac_match.group('frequency_offset')),
|
'frequency_offset': float(ac_match.group('frequency_offset')),
|
||||||
'gps_status': ac_match.group('gps_accuracy'),
|
'gps_status': ac_match.group('gps_accuracy'),
|
||||||
'software_version': float(ac_match.group('flarm_software_version')) if ac_match.group('flarm_software_version') else None,
|
'software_version': float(ac_match.group('flarm_software_version')) if ac_match.group('flarm_software_version') else None,
|
||||||
'hardware_version': int(ac_match.group('flarm_hardware_version'), 16) if ac_match.group('flarm_hardware_version') else None,
|
'hardware_version': int(ac_match.group('flarm_hardware_version'), 16) if ac_match.group('flarm_hardware_version') else None,
|
||||||
'real_address': ac_match.group('flarm_id')}
|
'real_address': ac_match.group('flarm_id'),
|
||||||
|
'signal_power': float(ac_match.group('signal_power')) if ac_match.group('signal_power') else None}
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -63,10 +72,19 @@ def parse_ogn_receiver_beacon(aprs_comment):
|
||||||
'total_ram': float(rec_match.group('ram_total')),
|
'total_ram': float(rec_match.group('ram_total')),
|
||||||
'ntp_error': float(rec_match.group('ntp_offset')),
|
'ntp_error': float(rec_match.group('ntp_offset')),
|
||||||
'rt_crystal_correction': float(rec_match.group('ntp_correction')),
|
'rt_crystal_correction': float(rec_match.group('ntp_correction')),
|
||||||
|
'voltage': float(rec_match.group('voltage')) if rec_match.group('voltage') else None,
|
||||||
|
'amperage': float(rec_match.group('amperage')) if rec_match.group('amperage') else None,
|
||||||
'cpu_temp': float(rec_match.group('cpu_temperature')) if rec_match.group('cpu_temperature') else None,
|
'cpu_temp': float(rec_match.group('cpu_temperature')) if rec_match.group('cpu_temperature') else None,
|
||||||
'rec_crystal_correction': int(rec_match.group('manual_correction')) if rec_match.group('manual_correction') else 0,
|
'senders_visible': int(rec_match.group('visible_senders')) if rec_match.group('visible_senders') else None,
|
||||||
'rec_crystal_correction_fine': float(rec_match.group('automatic_correction')) if rec_match.group('automatic_correction') else 0.0,
|
'senders_total': int(rec_match.group('senders')) if rec_match.group('senders') else None,
|
||||||
'rec_input_noise': float(rec_match.group('input_noise')) if rec_match.group('input_noise') else None}
|
'rec_crystal_correction': int(rec_match.group('rf_correction_manual')) if rec_match.group('rf_correction_manual') else 0,
|
||||||
|
'rec_crystal_correction_fine': float(rec_match.group('rf_correction_automatic')) if rec_match.group('rf_correction_automatic') else 0.0,
|
||||||
|
'rec_input_noise': float(rec_match.group('signal')) if rec_match.group('signal') else None,
|
||||||
|
'senders_signal': float(rec_match.group('senders_signal')) if rec_match.group('senders_signal') else None,
|
||||||
|
'senders_messages': float(rec_match.group('senders_messages')) if rec_match.group('senders_messages') else None,
|
||||||
|
'good_senders_signal': float(rec_match.group('good_senders_signal')) if rec_match.group('good_senders_signal') else None,
|
||||||
|
'good_senders': float(rec_match.group('good_senders')) if rec_match.group('good_senders') else None,
|
||||||
|
'good_and_bad_senders': float(rec_match.group('good_and_bad_senders')) if rec_match.group('good_and_bad_senders') else None}
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
PATTERN_APRS = re.compile(r"^(?P<callsign>.+?)>(?P<dstcall>[A-Z0-9]+),.+,(?P<receiver>.+?):/(?P<time>\d{6})+h(?P<latitude>\d{4}\.\d{2})(?P<latitude_sign>N|S)(?P<symbol_table>.)(?P<longitude>\d{5}\.\d{2})(?P<longitude_sign>E|W)(?P<symbol>.)(?P<course_extension>(?P<course>\d{3})/(?P<ground_speed>\d{3}))?/A=(?P<altitude>\d{6})(?P<pos_extension>\s!W((?P<latitude_enhancement>\d)(?P<longitude_enhancement>\d))!)?\s(?P<comment>.*)$")
|
PATTERN_APRS_POSITION = re.compile(r"^(?P<callsign>.+?)>(?P<dstcall>[A-Z0-9]+),.+,(?P<receiver>.+?):/(?P<time>\d{6})+h(?P<latitude>\d{4}\.\d{2})(?P<latitude_sign>N|S)(?P<symbol_table>.)(?P<longitude>\d{5}\.\d{2})(?P<longitude_sign>E|W)(?P<symbol>.)(?P<course_extension>(?P<course>\d{3})/(?P<ground_speed>\d{3}))?/A=(?P<altitude>\d{6})(?P<pos_extension>\s!W((?P<latitude_enhancement>\d)(?P<longitude_enhancement>\d))!)?\s(?P<comment>.*)$")
|
||||||
|
PATTERN_APRS_STATUS = re.compile(r"(?P<callsign>.+?)>(?P<dstcall>[A-Z0-9]+),.+,(?P<receiver>.+?):>(?P<time>\d{6})+h\s(?P<comment>.*)$")
|
||||||
|
|
||||||
# The following regexp patterns are part of the ruby ogn-client.
|
# The following regexp patterns are part of the ruby ogn-client.
|
||||||
# source: https://github.com/svoop/ogn_client-ruby
|
# source: https://github.com/svoop/ogn_client-ruby
|
||||||
|
@ -35,14 +36,19 @@ PATTERN_RECEIVER_BEACON = re.compile(r"""
|
||||||
\s)?
|
\s)?
|
||||||
CPU:(?P<cpu_load>[\d.]+)\s
|
CPU:(?P<cpu_load>[\d.]+)\s
|
||||||
RAM:(?P<ram_free>[\d.]+)\/(?P<ram_total>[\d.]+)MB\s
|
RAM:(?P<ram_free>[\d.]+)\/(?P<ram_total>[\d.]+)MB\s
|
||||||
NTP:(?P<ntp_offset>[\d.]+)ms\/(?P<ntp_correction>[+-][\d.]+)ppm\s?
|
NTP:(?P<ntp_offset>[\d.]+)ms\/(?P<ntp_correction>[+-][\d.]+)ppm\s
|
||||||
|
(?:(?P<voltage>[\d.]+)V\s)?
|
||||||
|
(?:(?P<amperage>[\d.]+)A\s)?
|
||||||
(?:(?P<cpu_temperature>[+-][\d.]+)C\s*)?
|
(?:(?P<cpu_temperature>[+-][\d.]+)C\s*)?
|
||||||
|
(?:(?P<visible_senders>\d+)\/(?P<senders>\d+)Acfts\[1h\]\s*)?
|
||||||
(?:RF:
|
(?:RF:
|
||||||
(?:
|
(?:
|
||||||
(?P<manual_correction>[+-][\d]+)
|
(?P<rf_correction_manual>[+-][\d]+)
|
||||||
(?P<automatic_correction>[+-][\d.]+)ppm\/
|
(?P<rf_correction_automatic>[+-][\d.]+)ppm\/
|
||||||
)?
|
)?
|
||||||
(?P<input_noise>[+-][\d.]+)dB
|
(?P<signal>[+-][\d.]+)dB
|
||||||
|
(?:\/(?P<senders_signal>[+-][\d.]+)dB@10km\[(?P<senders_messages>\d+)\])?
|
||||||
|
(?:\/(?P<good_senders_signal>[+-][\d.]+)dB@10km\[(?P<good_senders>\d+)\/(?P<good_and_bad_senders>\d+)\])?
|
||||||
)?
|
)?
|
||||||
""", re.VERBOSE | re.MULTILINE)
|
""", re.VERBOSE | re.MULTILINE)
|
||||||
|
|
||||||
|
@ -52,12 +58,13 @@ PATTERN_AIRCRAFT_BEACON = re.compile(r"""
|
||||||
(?P<climb_rate>[+-]\d+?)fpm\s
|
(?P<climb_rate>[+-]\d+?)fpm\s
|
||||||
(?P<turn_rate>[+-][\d.]+?)rot\s
|
(?P<turn_rate>[+-][\d.]+?)rot\s
|
||||||
(?:FL(?P<flight_level>[\d.]+)\s)?
|
(?:FL(?P<flight_level>[\d.]+)\s)?
|
||||||
(?P<signal>[\d.]+?)dB\s
|
(?P<signal_quality>[\d.]+?)dB\s
|
||||||
(?P<errors>\d+)e\s
|
(?P<errors>\d+)e\s
|
||||||
(?P<frequency_offset>[+-][\d.]+?)kHz\s?
|
(?P<frequency_offset>[+-][\d.]+?)kHz\s?
|
||||||
(?:gps(?P<gps_accuracy>\d+x\d+)\s?)?
|
(?:gps(?P<gps_accuracy>\d+x\d+)\s?)?
|
||||||
(?:s(?P<flarm_software_version>[\d.]+)\s?)?
|
(?:s(?P<flarm_software_version>[\d.]+)\s?)?
|
||||||
(?:h(?P<flarm_hardware_version>[\dA-F]{2})\s?)?
|
(?:h(?P<flarm_hardware_version>[\dA-F]{2})\s?)?
|
||||||
(?:r(?P<flarm_id>[\dA-F]+)\s?)?
|
(?:r(?P<flarm_id>[\dA-F]+)\s?)?
|
||||||
|
(?:(?P<signal_power>[+-][\d.]+)dBm\s?)?
|
||||||
(?:hear(?P<proximity>.+))?
|
(?:hear(?P<proximity>.+))?
|
||||||
""", re.VERBOSE | re.MULTILINE)
|
""", re.VERBOSE | re.MULTILINE)
|
||||||
|
|
|
@ -43,7 +43,6 @@ class OgnClientTest(unittest.TestCase):
|
||||||
client.sock.shutdown.assert_called_once_with(0)
|
client.sock.shutdown.assert_called_once_with(0)
|
||||||
client.sock.close.assert_called_once_with()
|
client.sock.close.assert_called_once_with()
|
||||||
|
|
||||||
@unittest.skip("messages from rtlsdr_ogn v0.2.5 are not supported yet")
|
|
||||||
def test_50_live_messages(self):
|
def test_50_live_messages(self):
|
||||||
print("Enter")
|
print("Enter")
|
||||||
self.remaining_messages = 50
|
self.remaining_messages = 50
|
||||||
|
|
|
@ -15,7 +15,7 @@ class TestStringMethods(unittest.TestCase):
|
||||||
self.assertEqual(aircraft_beacon['address'], "DDA5BA")
|
self.assertEqual(aircraft_beacon['address'], "DDA5BA")
|
||||||
self.assertAlmostEqual(aircraft_beacon['climb_rate'] * ms2fpm, -454, 2)
|
self.assertAlmostEqual(aircraft_beacon['climb_rate'] * ms2fpm, -454, 2)
|
||||||
self.assertEqual(aircraft_beacon['turn_rate'], -1.1)
|
self.assertEqual(aircraft_beacon['turn_rate'], -1.1)
|
||||||
self.assertEqual(aircraft_beacon['signal_strength'], 8.8)
|
self.assertEqual(aircraft_beacon['signal_quality'], 8.8)
|
||||||
self.assertEqual(aircraft_beacon['error_count'], 0)
|
self.assertEqual(aircraft_beacon['error_count'], 0)
|
||||||
self.assertEqual(aircraft_beacon['frequency_offset'], 51.2)
|
self.assertEqual(aircraft_beacon['frequency_offset'], 51.2)
|
||||||
self.assertEqual(aircraft_beacon['gps_status'], '4x5')
|
self.assertEqual(aircraft_beacon['gps_status'], '4x5')
|
||||||
|
@ -44,6 +44,11 @@ class TestStringMethods(unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual(aircraft_beacon['flightlevel'], 4.43)
|
self.assertEqual(aircraft_beacon['flightlevel'], 4.43)
|
||||||
|
|
||||||
|
def test_v025(self):
|
||||||
|
aircraft_beacon = parse_ogn_aircraft_beacon("id06DDE28D +535fpm +3.8rot 11.5dB 0e -1.0kHz gps2x3 s6.01 h0C +7.4dBm")
|
||||||
|
|
||||||
|
self.assertEqual(aircraft_beacon['signal_power'], 7.4)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -28,12 +28,22 @@ class TestStringMethods(unittest.TestCase):
|
||||||
self.assertEqual(message['comment'], "this is a comment")
|
self.assertEqual(message['comment'], "this is a comment")
|
||||||
|
|
||||||
def test_v024(self):
|
def test_v024(self):
|
||||||
|
# higher precision datum format introduced
|
||||||
raw_message = "FLRDDA5BA>APRS,qAS,LFMX:/160829h4415.41N/00600.03E'342/049/A=005524 !W26! id21400EA9 -2454fpm +0.9rot 19.5dB 0e -6.6kHz gps1x1 s6.02 h44 rDF0C56"
|
raw_message = "FLRDDA5BA>APRS,qAS,LFMX:/160829h4415.41N/00600.03E'342/049/A=005524 !W26! id21400EA9 -2454fpm +0.9rot 19.5dB 0e -6.6kHz gps1x1 s6.02 h44 rDF0C56"
|
||||||
message = parse_aprs(raw_message, reference_date=datetime(2015, 1, 1, 16, 8, 29))
|
message = parse_aprs(raw_message, reference_date=datetime(2015, 1, 1, 16, 8, 29))
|
||||||
|
|
||||||
self.assertAlmostEqual(message['latitude'] - 44.2568 - 1 / 30000, 2 / 1000 / 60, 10)
|
self.assertAlmostEqual(message['latitude'] - 44.2568 - 1 / 30000, 2 / 1000 / 60, 10)
|
||||||
self.assertAlmostEqual(message['longitude'] - 6.0005, 6 / 1000 / 60, 10)
|
self.assertAlmostEqual(message['longitude'] - 6.0005, 6 / 1000 / 60, 10)
|
||||||
|
|
||||||
|
def test_v025(self):
|
||||||
|
# introduced the "aprs status" format where many informations (lat, lon, alt, speed, ...) are just optional
|
||||||
|
raw_message = "EPZR>APRS,TCPIP*,qAC,GLIDERN1:>093456h this is a comment"
|
||||||
|
message = parse_aprs(raw_message)
|
||||||
|
|
||||||
|
self.assertEqual(message['name'], "EPZR")
|
||||||
|
self.assertEqual(message['receiver_name'], "GLIDERN1")
|
||||||
|
self.assertEqual(message['timestamp'].strftime('%H:%M:%S'), "09:34:56")
|
||||||
|
self.assertEqual(message['comment'], "this is a comment")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -7,6 +7,12 @@ class TestStringMethods(unittest.TestCase):
|
||||||
def test_fail_validation(self):
|
def test_fail_validation(self):
|
||||||
self.assertEqual(parse_ogn_receiver_beacon("notAValidToken"), None)
|
self.assertEqual(parse_ogn_receiver_beacon("notAValidToken"), None)
|
||||||
|
|
||||||
|
def test_v021(self):
|
||||||
|
receiver_beacon = parse_ogn_receiver_beacon("v0.2.1 CPU:0.8 RAM:25.6/458.9MB NTP:0.0ms/+0.0ppm +51.9C RF:+26-1.4ppm/-0.25dB")
|
||||||
|
self.assertEqual(receiver_beacon['rec_crystal_correction'], 26)
|
||||||
|
self.assertEqual(receiver_beacon['rec_crystal_correction_fine'], -1.4)
|
||||||
|
self.assertEqual(receiver_beacon['rec_input_noise'], -0.25)
|
||||||
|
|
||||||
def test_v022(self):
|
def test_v022(self):
|
||||||
receiver_beacon = parse_ogn_receiver_beacon("v0.2.2.x86 CPU:0.5 RAM:669.9/887.7MB NTP:1.0ms/+6.2ppm +52.0C RF:+0.06dB")
|
receiver_beacon = parse_ogn_receiver_beacon("v0.2.2.x86 CPU:0.5 RAM:669.9/887.7MB NTP:1.0ms/+6.2ppm +52.0C RF:+0.06dB")
|
||||||
self.assertEqual(receiver_beacon['version'], '0.2.2')
|
self.assertEqual(receiver_beacon['version'], '0.2.2')
|
||||||
|
@ -20,11 +26,21 @@ class TestStringMethods(unittest.TestCase):
|
||||||
self.assertEqual(receiver_beacon['rec_crystal_correction_fine'], 0.0)
|
self.assertEqual(receiver_beacon['rec_crystal_correction_fine'], 0.0)
|
||||||
self.assertEqual(receiver_beacon['rec_input_noise'], 0.06)
|
self.assertEqual(receiver_beacon['rec_input_noise'], 0.06)
|
||||||
|
|
||||||
def test_v021(self):
|
def test_v025(self):
|
||||||
receiver_beacon = parse_ogn_receiver_beacon("v0.2.1 CPU:0.8 RAM:25.6/458.9MB NTP:0.0ms/+0.0ppm +51.9C RF:+26-1.4ppm/-0.25dB")
|
receiver_beacon = parse_ogn_receiver_beacon("v0.2.5.RPI-GPU CPU:0.8 RAM:287.3/458.7MB NTP:1.0ms/-6.4ppm 5.016V 0.534A +51.9C RF:+55+0.4ppm/-0.67dB/+10.8dB@10km[57282]")
|
||||||
self.assertEqual(receiver_beacon['rec_crystal_correction'], 26)
|
self.assertEqual(receiver_beacon['voltage'], 5.016)
|
||||||
self.assertEqual(receiver_beacon['rec_crystal_correction_fine'], -1.4)
|
self.assertEqual(receiver_beacon['amperage'], 0.534)
|
||||||
self.assertEqual(receiver_beacon['rec_input_noise'], -0.25)
|
self.assertEqual(receiver_beacon['senders_signal'], 10.8)
|
||||||
|
self.assertEqual(receiver_beacon['senders_messages'], 57282)
|
||||||
|
|
||||||
|
receiver_beacon = parse_ogn_receiver_beacon("v0.2.5.ARM CPU:0.4 RAM:638.0/970.5MB NTP:0.2ms/-1.1ppm +65.5C 14/16Acfts[1h] RF:+45+0.0ppm/+3.88dB/+24.0dB@10km[143717]/+26.7dB@10km[68/135]")
|
||||||
|
self.assertEqual(receiver_beacon['senders_visible'], 14)
|
||||||
|
self.assertEqual(receiver_beacon['senders_total'], 16)
|
||||||
|
self.assertEqual(receiver_beacon['senders_signal'], 24.0)
|
||||||
|
self.assertEqual(receiver_beacon['senders_messages'], 143717)
|
||||||
|
self.assertEqual(receiver_beacon['good_senders_signal'], 26.7)
|
||||||
|
self.assertEqual(receiver_beacon['good_senders'], 68)
|
||||||
|
self.assertEqual(receiver_beacon['good_and_bad_senders'], 135)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -15,3 +15,14 @@ Salland>APRS,TCPIP*,qAC,GLIDERN2:/165426h5227.93NI00620.03E&/A=000049 v0.2.2 CPU
|
||||||
LSGS>APRS,TCPIP*,qAC,GLIDERN1:/165345h4613.25NI00719.68E&/A=001581 CPU:0.7 RAM:247.9/456.4MB NTP:0.7ms/-11.4ppm +44.4C RF:+53+71.9ppm/+0.4dB
|
LSGS>APRS,TCPIP*,qAC,GLIDERN1:/165345h4613.25NI00719.68E&/A=001581 CPU:0.7 RAM:247.9/456.4MB NTP:0.7ms/-11.4ppm +44.4C RF:+53+71.9ppm/+0.4dB
|
||||||
Drenstein>APRS,TCPIP*,qAC,GLIDERN1:/165011h5147.51NI00744.45E&/A=000213 v0.2.2 CPU:0.8 RAM:695.7/4025.5MB NTP:16000.0ms/+0.0ppm +63.0C
|
Drenstein>APRS,TCPIP*,qAC,GLIDERN1:/165011h5147.51NI00744.45E&/A=000213 v0.2.2 CPU:0.8 RAM:695.7/4025.5MB NTP:16000.0ms/+0.0ppm +63.0C
|
||||||
ZK-GSC>APRS,qAS,Omarama:/165202h4429.25S/16959.33E'/A=001407 id05C821EA +020fpm +0.0rot 16.8dB 0e -3.1kHz gps1x3 hear1084 hearB597 hearB598
|
ZK-GSC>APRS,qAS,Omarama:/165202h4429.25S/16959.33E'/A=001407 id05C821EA +020fpm +0.0rot 16.8dB 0e -3.1kHz gps1x3 hear1084 hearB597 hearB598
|
||||||
|
# since 0.2.5 for receiver information not only the "aprs position" format is used but also the "aprs status" format (without lat/lon/alt informations)
|
||||||
|
Cordoba>APRS,TCPIP*,qAC,GLIDERN3:/194847h3112.85SI06409.56W&/A=001712 v0.2.5.ARM CPU:0.4 RAM:755.4/970.8MB NTP:6.7ms/-0.1ppm +45.5C RF:+48+18.3ppm/+3.45dB
|
||||||
|
Cordoba>APRS,TCPIP*,qAC,GLIDERN3:>194847h v0.2.5.ARM CPU:0.4 RAM:755.4/970.8MB NTP:6.7ms/-0.1ppm +45.5C 0/0Acfts[1h] RF:+48+18.3ppm/+3.45dB/+0.4dB@10km[71]/+0.4dB@10km[1/1]
|
||||||
|
VITACURA1>APRS,TCPIP*,qAC,GLIDERN3:/042149h3322.81SI07034.95W&/A=002345 v0.2.5.ARM CPU:0.6 RAM:694.4/970.5MB NTP:0.8ms/-7.5ppm +54.8C RF:+0-0.2ppm/+3.81dB
|
||||||
|
VITACURA1>APRS,TCPIP*,qAC,GLIDERN3:>042149h v0.2.5.ARM CPU:0.6 RAM:694.4/970.5MB NTP:0.8ms/-7.5ppm +54.8C 0/0Acfts[1h] RF:+0-0.2ppm/+3.81dB/+1.3dB@10km[132205]/+6.6dB@10km[10/20]
|
||||||
|
Arnsberg>APRS,TCPIP*,qAC,GLIDERN1:/042146h5123.04NI00803.77E&/A=000623 v0.2.5.ARM CPU:0.4 RAM:765.1/970.8MB NTP:0.4ms/-1.7ppm +62.3C RF:+27+1.1ppm/+3.17dB
|
||||||
|
Arnsberg>APRS,TCPIP*,qAC,GLIDERN1:>042146h v0.2.5.ARM CPU:0.4 RAM:764.9/970.8MB NTP:0.4ms/-1.7ppm +62.3C 0/0Acfts[1h] RF:+27+1.1ppm/+3.17dB/+9.2dB@10km[44487]/+12.1dB@10km[20/40]
|
||||||
|
CNF3a>APRS,TCPIP*,qAC,GLIDERN3:/042143h4529.25NI07505.65W&/A=000259 v0.2.5.ARM CPU:0.6 RAM:514.6/970.8MB NTP:4.5ms/-1.5ppm +27.2C RF:+0-0.4ppm/+18.69dB
|
||||||
|
CNF3a>APRS,TCPIP*,qAC,GLIDERN3:>042143h v0.2.5.ARM CPU:0.6 RAM:514.6/970.8MB NTP:4.5ms/-1.5ppm +27.2C 0/0Acfts[1h] RF:+0-0.4ppm/+18.69dB/+13.0dB@10km[104282]/+9.7dB@10km[2/3]
|
||||||
|
VITACURA2>APRS,TCPIP*,qAC,GLIDERN3:/042136h3322.81SI07034.95W&/A=002345 v0.2.5.ARM CPU:0.3 RAM:695.0/970.5MB NTP:0.6ms/-5.7ppm +51.5C RF:+0-0.0ppm/+1.32dB
|
||||||
|
VITACURA2>APRS,TCPIP*,qAC,GLIDERN3:>042136h v0.2.5.ARM CPU:0.3 RAM:695.0/970.5MB NTP:0.6ms/-5.7ppm +52.1C 0/0Acfts[1h] RF:+0-0.0ppm/+1.32dB/+2.1dB@10km[193897]/+9.0dB@10km[10/20]
|
Ładowanie…
Reference in New Issue