kopia lustrzana https://github.com/glidernet/ogn-python
rodzic
bb129134a8
commit
daf2d81460
|
@ -2,6 +2,7 @@ import os
|
|||
import re
|
||||
from datetime import datetime, timedelta
|
||||
from io import StringIO
|
||||
import gzip
|
||||
|
||||
from flask import current_app
|
||||
from flask.cli import AppGroup
|
||||
|
@ -11,8 +12,8 @@ from mgrs import MGRS
|
|||
|
||||
from ogn.parser import parse, ParseError
|
||||
|
||||
from app.model import AircraftType, Location
|
||||
from app.gateway.process_tools import open_file, create_tables, drop_tables, update_aircraft_beacons_bigdata
|
||||
from app.model import AircraftBeacon, ReceiverBeacon, AircraftType, Location
|
||||
from app.gateway.process_tools import open_file
|
||||
|
||||
from app import db
|
||||
|
||||
|
@ -27,12 +28,14 @@ AIRCRAFT_BEACON_TYPES = ["aprs_aircraft", "flarm", "tracker", "fanet", "lt24", "
|
|||
RECEIVER_BEACON_TYPES = ["aprs_receiver", "receiver"]
|
||||
|
||||
# define fields we want to proceed
|
||||
BEACON_KEY_FIELDS = ["name", "receiver_name", "timestamp"]
|
||||
AIRCRAFT_BEACON_FIELDS = [
|
||||
"location",
|
||||
"altitude",
|
||||
"name",
|
||||
"dstcall",
|
||||
"relay",
|
||||
"receiver_name",
|
||||
"timestamp",
|
||||
"track",
|
||||
"ground_speed",
|
||||
"address_type",
|
||||
|
@ -57,10 +60,14 @@ AIRCRAFT_BEACON_FIELDS = [
|
|||
"location_mgrs_short",
|
||||
"agl",
|
||||
]
|
||||
|
||||
RECEIVER_BEACON_FIELDS = [
|
||||
"location",
|
||||
"altitude",
|
||||
"name",
|
||||
"dstcall",
|
||||
"receiver_name",
|
||||
"timestamp",
|
||||
]
|
||||
|
||||
|
||||
|
@ -81,47 +88,23 @@ def initial_file_scan(file):
|
|||
return row_count, timestamp
|
||||
|
||||
|
||||
class DbFeeder:
|
||||
def __init__(self, postfix, reference_timestamp, auto_update_timestamp):
|
||||
self.postfix = postfix
|
||||
class StringConverter:
|
||||
def __init__(self, reference_timestamp, auto_update_timestamp):
|
||||
self.reference_timestamp = reference_timestamp
|
||||
self.auto_update_timestamp = auto_update_timestamp
|
||||
|
||||
self.last_flush = datetime.utcnow()
|
||||
|
||||
self.aircraft_buffer = StringIO()
|
||||
self.receiver_buffer = StringIO()
|
||||
|
||||
self.connection = db.engine.raw_connection()
|
||||
self.cursor = self.connection.cursor()
|
||||
|
||||
self.mgrs = MGRS()
|
||||
|
||||
create_tables(self.postfix)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
self._flush()
|
||||
update_aircraft_beacons_bigdata(self.postfix)
|
||||
self.connection.commit()
|
||||
pass
|
||||
|
||||
self.cursor.close()
|
||||
self.connection.close()
|
||||
def _convert(self, raw_string):
|
||||
if raw_string.strip() == '':
|
||||
return
|
||||
|
||||
def _flush(self):
|
||||
self.aircraft_buffer.seek(0)
|
||||
self.receiver_buffer.seek(0)
|
||||
|
||||
self.cursor.copy_from(self.aircraft_buffer, "aircraft_beacons_{postfix}".format(postfix=self.postfix), sep=",", columns=BEACON_KEY_FIELDS + AIRCRAFT_BEACON_FIELDS)
|
||||
self.cursor.copy_from(self.receiver_buffer, "receiver_beacons_{postfix}".format(postfix=self.postfix), sep=",", columns=BEACON_KEY_FIELDS + RECEIVER_BEACON_FIELDS)
|
||||
self.connection.commit()
|
||||
|
||||
self.aircraft_buffer = StringIO()
|
||||
self.receiver_buffer = StringIO()
|
||||
|
||||
def add(self, raw_string):
|
||||
try:
|
||||
message = parse(raw_string, reference_timestamp=self.reference_timestamp)
|
||||
except NotImplementedError as e:
|
||||
|
@ -148,15 +131,14 @@ class DbFeeder:
|
|||
latitude = message["latitude"]
|
||||
longitude = message["longitude"]
|
||||
|
||||
location = Location(longitude, latitude)
|
||||
message["location"] = location.to_wkt()
|
||||
message["location"] = "SRID=4326;POINT({} {})".format(longitude, latitude)
|
||||
|
||||
location_mgrs = self.mgrs.toMGRS(latitude, longitude).decode("utf-8")
|
||||
message["location_mgrs"] = location_mgrs
|
||||
message["location_mgrs_short"] = location_mgrs[0:5] + location_mgrs[5:7] + location_mgrs[10:12]
|
||||
|
||||
if "aircraft_type" in message:
|
||||
message["aircraft_type"] = AircraftType(message["aircraft_type"]).name if message["aircraft_type"] in AircraftType.list() else AircraftType.UNKNOWN.name
|
||||
message["aircraft_type"] = AircraftType(message["aircraft_type"]) if message["aircraft_type"] in AircraftType.list() else AircraftType.UNKNOWN
|
||||
|
||||
if "gps_quality" in message:
|
||||
if message["gps_quality"] is not None and "horizontal" in message["gps_quality"]:
|
||||
|
@ -164,26 +146,200 @@ class DbFeeder:
|
|||
message["gps_quality_vertical"] = message["gps_quality"]["vertical"]
|
||||
del message["gps_quality"]
|
||||
|
||||
if message["beacon_type"] in RECEIVER_BEACON_TYPES:
|
||||
complete_message = ",".join([str(message[k]) if k in message and message[k] is not None else "\\N" for k in BEACON_KEY_FIELDS + RECEIVER_BEACON_FIELDS])
|
||||
self.receiver_buffer.write(complete_message)
|
||||
self.receiver_buffer.write("\n")
|
||||
elif message["beacon_type"] in AIRCRAFT_BEACON_TYPES:
|
||||
complete_message = ",".join([str(message[k]) if k in message and message[k] is not None else "\\N" for k in BEACON_KEY_FIELDS + AIRCRAFT_BEACON_FIELDS])
|
||||
self.aircraft_buffer.write(complete_message)
|
||||
self.aircraft_buffer.write("\n")
|
||||
else:
|
||||
current_app.logger.error("Ignore beacon_type: {}".format(message["beacon_type"]))
|
||||
return message
|
||||
|
||||
def _get_aircraft_beacon_csv_string(self, message, none_character=''):
|
||||
csv_string = "{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18},{19},{20},{21},{22},{23},{24},{25},{26},{27},{28},{29}\n".format(
|
||||
message['location'],
|
||||
int(message['altitude']),
|
||||
message['name'],
|
||||
message['dstcall'],
|
||||
message['relay'] if 'relay' in message and message['relay'] else none_character,
|
||||
message['receiver_name'],
|
||||
message['timestamp'],
|
||||
message['track'] if 'track' in message and message['track'] else none_character,
|
||||
message['ground_speed'] if 'ground_speed' in message and message['ground_speed'] else none_character,
|
||||
message['address_type'] if 'address_type' in message and message['address_type'] else none_character,
|
||||
message['aircraft_type'].name if 'aircraft_type' in message and message['aircraft_type'] else AircraftType.UNKNOWN.name,
|
||||
message['stealth'] if 'stealth' in message and message['stealth'] else none_character,
|
||||
message['address'] if 'address' in message and message['address'] else none_character,
|
||||
message['climb_rate'] if 'climb_rate' in message and message['climb_rate'] else none_character,
|
||||
message['turn_rate'] if 'turn_rate' in message and message['turn_rate'] else none_character,
|
||||
message['signal_quality'] if 'signal_quality' in message and message['signal_quality'] else none_character,
|
||||
message['error_count'] if 'error_count' in message and message['error_count'] else none_character,
|
||||
message['frequency_offset'] if 'frequency_offset' in message and message['frequency_offset'] else none_character,
|
||||
message['gps_quality_horizontal'] if 'gps_quality_horizontal' in message and message['gps_quality_horizontal'] else none_character,
|
||||
message['gps_quality_vertical'] if 'gps_quality_vertical' in message and message['gps_quality_vertical'] else none_character,
|
||||
message['software_version'] if 'software_version' in message and message['software_version'] else none_character, #20
|
||||
message['hardware_version'] if 'hardware_version' in message and message['hardware_version'] else none_character,
|
||||
message['real_address'] if 'real_address' in message and message['real_address'] else none_character,
|
||||
message['signal_power'] if 'signal_power' in message and message['signal_power'] else none_character,
|
||||
message['distance'] if 'distance' in message and message['distance'] else none_character,
|
||||
message['radial'] if 'radial' in message and message['radial'] else none_character,
|
||||
message['quality'] if 'quality' in message and message['quality'] else none_character,
|
||||
message['location_mgrs'],
|
||||
message['location_mgrs_short'],
|
||||
message['agl'] if 'agl' in message else none_character, #29
|
||||
)
|
||||
return csv_string
|
||||
|
||||
def _get_receiver_beacon_csv_string(self, message, none_character=''):
|
||||
csv_string = "{0},{1},{2},{3},{4},{5}\n".format(
|
||||
message['location'],
|
||||
int(message['altitude']) if message['altitude'] else none_character,
|
||||
message['name'],
|
||||
message['dstcall'],
|
||||
message['receiver_name'],
|
||||
message['timestamp'],
|
||||
)
|
||||
return csv_string
|
||||
|
||||
|
||||
class FileFeeder(StringConverter):
|
||||
def __init__(self, postfix, reference_timestamp, reference_timestamp_autoupdate):
|
||||
self.reference_timestamp = reference_timestamp
|
||||
self.reference_timestamp_autoupdate = reference_timestamp_autoupdate
|
||||
|
||||
self.aircraft_beacons_file = gzip.open('aircraft_beacons_{}.csv.gz'.format(postfix), 'wt')
|
||||
self.receiver_beacons_file = gzip.open('receiver_beacons_{}.csv.gz'.format(postfix), 'wt')
|
||||
|
||||
super().__init__(reference_timestamp, reference_timestamp_autoupdate)
|
||||
|
||||
def __enter__(self):
|
||||
self.aircraft_beacons_file.write(','.join(AIRCRAFT_BEACON_FIELDS))
|
||||
self.receiver_beacons_file.write(','.join(RECEIVER_BEACON_FIELDS))
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.aircraft_beacons_file.close()
|
||||
self.receiver_beacons_file.close()
|
||||
|
||||
def add(self, raw_string):
|
||||
message = self._convert(raw_string)
|
||||
if message['beacon_type'] in AIRCRAFT_BEACON_TYPES:
|
||||
csv_string = self._get_aircraft_beacon_csv_string(message)
|
||||
self.aircraft_beacons_file.write(csv_string)
|
||||
elif message['beacon_type'] in RECEIVER_BEACON_TYPES:
|
||||
csv_string = self._get_receiver_beacon_csv_string(message)
|
||||
self.receiver_beacons_file.write(csv_string)
|
||||
|
||||
|
||||
class DbFeeder(StringConverter):
|
||||
def __init__(self, reference_timestamp, reference_timestamp_autoupdate):
|
||||
self.reference_timestamp = reference_timestamp
|
||||
self.reference_timestamp_autoupdate = reference_timestamp_autoupdate
|
||||
|
||||
self.aircraft_beacons_buffer = StringIO()
|
||||
self.receiver_beacons_buffer = StringIO()
|
||||
|
||||
self.last_flush = datetime.utcnow()
|
||||
|
||||
super().__init__(reference_timestamp, reference_timestamp_autoupdate)
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.flush()
|
||||
|
||||
def add(self, raw_string):
|
||||
message = self._convert(raw_string)
|
||||
if not message:
|
||||
return
|
||||
|
||||
if datetime.utcnow() - self.last_flush >= timedelta(seconds=5):
|
||||
self._flush()
|
||||
if message['beacon_type'] in AIRCRAFT_BEACON_TYPES:
|
||||
csv_string = self._get_aircraft_beacon_csv_string(message, none_character=r'\N')
|
||||
self.aircraft_beacons_buffer.write(csv_string)
|
||||
elif message['beacon_type'] in RECEIVER_BEACON_TYPES:
|
||||
csv_string = self._get_receiver_beacon_csv_string(message, none_character=r'\N')
|
||||
self.receiver_beacons_buffer.write(csv_string)
|
||||
|
||||
if datetime.utcnow() - self.last_flush >= timedelta(seconds=1):
|
||||
self.flush()
|
||||
self.last_flush = datetime.utcnow()
|
||||
|
||||
def flush(self):
|
||||
connection = db.engine.raw_connection()
|
||||
cursor = connection.cursor()
|
||||
|
||||
self.aircraft_beacons_buffer.seek(0)
|
||||
self.receiver_beacons_buffer.seek(0)
|
||||
|
||||
cursor.execute("CREATE TEMPORARY TABLE aircraft_beacons_temp (LIKE aircraft_beacons) ON COMMIT DROP;")
|
||||
cursor.execute("CREATE TEMPORARY TABLE receiver_beacons_temp (LIKE receiver_beacons) ON COMMIT DROP;")
|
||||
|
||||
cursor.copy_from(file=self.aircraft_beacons_buffer, table="aircraft_beacons_temp", sep=",", columns=AIRCRAFT_BEACON_FIELDS)
|
||||
cursor.copy_from(file=self.receiver_beacons_buffer, table="receiver_beacons_temp", sep=",", columns=RECEIVER_BEACON_FIELDS)
|
||||
|
||||
# Update receivers
|
||||
cursor.execute("""
|
||||
INSERT INTO receivers AS r (name, location, altitude, firstseen, lastseen, timestamp)
|
||||
SELECT DISTINCT ON (rbt.name)
|
||||
rbt.name,
|
||||
rbt.location,
|
||||
rbt.altitude,
|
||||
timezone('utc', NOW()) AS firstseen,
|
||||
timezone('utc', NOW()) AS lastseen,
|
||||
rbt.timestamp
|
||||
FROM receiver_beacons_temp AS rbt,
|
||||
(
|
||||
SELECT
|
||||
rbt.name,
|
||||
MAX(timestamp) AS timestamp
|
||||
FROM receiver_beacons_temp AS rbt
|
||||
GROUP BY rbt.name
|
||||
) AS sq
|
||||
WHERE rbt.name = sq.name AND rbt.timestamp = sq.timestamp
|
||||
ON CONFLICT (name) DO UPDATE
|
||||
SET
|
||||
location = EXCLUDED.location,
|
||||
altitude = EXCLUDED.altitude,
|
||||
lastseen = timezone('utc', NOW()),
|
||||
timestamp = EXCLUDED.timestamp
|
||||
""")
|
||||
|
||||
# Update agl
|
||||
cursor.execute("""
|
||||
UPDATE aircraft_beacons_temp AS abt
|
||||
SET
|
||||
agl = ST_Value(e.rast, abt.location)
|
||||
FROM elevation AS e
|
||||
WHERE ST_Intersects(abt.location, e.rast)
|
||||
""")
|
||||
|
||||
# ... update receiver related attributes: distance, radial, quality
|
||||
cursor.execute("""
|
||||
UPDATE aircraft_beacons_temp AS abt
|
||||
SET
|
||||
distance = CAST(ST_DistanceSphere(r.location, abt.location) AS REAL),
|
||||
radial = CASE WHEN Degrees(ST_Azimuth(r.location, abt.location)) >= 359.5 THEN 0 ELSE CAST(Degrees(ST_Azimuth(r.location, abt.location)) AS INT) END,
|
||||
quality = CASE WHEN ST_DistanceSphere(r.location, abt.location) > 0 THEN CAST(abt.signal_quality + 20.0 * LOG(ST_DistanceSphere(r.location, abt.location) / 10000) AS REAL) ELSE NULL END
|
||||
FROM receivers AS r
|
||||
WHERE abt.receiver_name = r.name
|
||||
""")
|
||||
|
||||
# Insert all the beacons
|
||||
cursor.execute("""
|
||||
INSERT INTO aircraft_beacons
|
||||
SELECT * FROM aircraft_beacons_temp
|
||||
ON CONFLICT DO NOTHING;
|
||||
""")
|
||||
cursor.execute("""
|
||||
INSERT INTO receiver_beacons
|
||||
SELECT * FROM receiver_beacons_temp
|
||||
ON CONFLICT DO NOTHING;
|
||||
""")
|
||||
connection.commit()
|
||||
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
self.aircraft_beacons_buffer = StringIO()
|
||||
self.receiver_beacons_buffer = StringIO()
|
||||
|
||||
|
||||
def convert(sourcefile):
|
||||
print("Fast scan of file '{}'...".format(sourcefile), end='')
|
||||
with open_file(sourcefile) as filehandler:
|
||||
total_lines, reference_timestamp = initial_file_scan(filehandler)
|
||||
print("done")
|
||||
|
||||
if reference_timestamp is not None:
|
||||
auto_update_timestamp = True
|
||||
|
@ -192,15 +348,85 @@ def convert(sourcefile):
|
|||
auto_update_timestamp = False
|
||||
match = re.match(r".*OGN_log\.txt_([0-9]{4}\-[0-9]{2}\-[0-9]{2})\.gz$", sourcefile)
|
||||
if match:
|
||||
reference_timestamp = datetime.strptime(match.group(1), "%Y-%m-%d")
|
||||
reference_timestamp = datetime.strptime(match.group(1), "%Y-%m-%d") + timedelta(hours=12)
|
||||
postfix = reference_timestamp.strftime("%Y_%m_%d")
|
||||
else:
|
||||
current_app.logger.error("No reference time information. Skipping file: {}".format(sourcefile))
|
||||
return
|
||||
|
||||
with open_file(sourcefile) as fin:
|
||||
with DbFeeder(postfix=postfix, reference_timestamp=reference_timestamp, auto_update_timestamp=auto_update_timestamp) as feeder:
|
||||
with FileFeeder(postfix=postfix, reference_timestamp=reference_timestamp, auto_update_timestamp=auto_update_timestamp) as feeder:
|
||||
pbar = tqdm(fin, total=total_lines)
|
||||
for line in pbar:
|
||||
pbar.set_description("Importing {}".format(sourcefile))
|
||||
feeder.add(raw_string=line)
|
||||
|
||||
|
||||
def calculate(ab_filename, rb_filename, target_filename):
|
||||
sql_string = ("""
|
||||
DROP TABLE IF EXISTS tmp_ab;
|
||||
DROP TABLE IF EXISTS tmp_rb;
|
||||
|
||||
CREATE TABLE tmp_ab
|
||||
AS
|
||||
SELECT *
|
||||
FROM aircraft_beacons
|
||||
WITH NO DATA;
|
||||
|
||||
CREATE TABLE tmp_rb
|
||||
AS
|
||||
SELECT *
|
||||
FROM receiver_beacons
|
||||
WITH NO DATA;
|
||||
|
||||
COPY tmp_ab FROM PROGRAM 'gunzip -c {ab_filename}' CSV DELIMITER ',' HEADER;
|
||||
COPY tmp_rb FROM PROGRAM 'gunzip -c {rb_filename}' CSV DELIMITER ',' HEADER;
|
||||
|
||||
COPY (
|
||||
WITH sq AS (
|
||||
SELECT
|
||||
'SRID=4326;' || ST_AsText(ab.location) AS location,
|
||||
ab.altitude,
|
||||
ab.name,
|
||||
ab.dstcall,
|
||||
ab.relay,
|
||||
ab.receiver_name,
|
||||
ab.timestamp,
|
||||
CASE WHEN ab.track = 360 THEN 0 ELSE ab.track END,
|
||||
ab.ground_speed,
|
||||
ab.address_type,
|
||||
ab.aircraft_type,
|
||||
ab.stealth,
|
||||
ab.address,
|
||||
ab.climb_rate,
|
||||
ab.turn_rate,
|
||||
ab.signal_quality,
|
||||
ab.error_count,
|
||||
ab.frequency_offset,
|
||||
ab.gps_quality_horizontal,
|
||||
ab.gps_quality_vertical,
|
||||
ab.software_version,
|
||||
ab.hardware_version,
|
||||
ab.real_address,
|
||||
ab.signal_power,
|
||||
CAST(ST_DistanceSphere(rb.location, ab.location) AS REAL) AS distance,
|
||||
CASE WHEN Degrees(ST_Azimuth(rb.location, ab.location)) >= 359.5 THEN 0 ELSE CAST(Degrees(ST_Azimuth(rb.location, ab.location)) AS INT) END AS radial,
|
||||
CASE WHEN ST_DistanceSphere(rb.location, ab.location) > 0 THEN CAST(ab.signal_quality + 20.0 * LOG(ST_DistanceSphere(rb.location, ab.location) / 10000) AS REAL) ELSE NULL END quality,
|
||||
ab.location_mgrs,
|
||||
ab.location_mgrs_short,
|
||||
ab.altitude - ST_Value(e.rast, ab.location) AS agl
|
||||
FROM tmp_ab AS ab, elevation AS e, (SELECT name, MAX(location) AS location FROM tmp_rb GROUP BY name) AS rb
|
||||
WHERE ab.receiver_name = rb.name AND ST_Intersects(ab.location, e.rast)
|
||||
)
|
||||
|
||||
SELECT DISTINCT ON (name, receiver_name, timestamp) *
|
||||
FROM sq
|
||||
) TO PROGRAM 'gzip > {target_filename}' CSV DELIMITER ',' HEADER;
|
||||
|
||||
COPY (
|
||||
SELECT DISTINCT ON (name, receiver_name, timestamp) *
|
||||
FROM tmp_rb AS rb
|
||||
) TO PROGRAM 'gzip > {rb_filename}2' CSV DELIMITER ',' HEADER;
|
||||
""".format(ab_filename=ab_filename, rb_filename=rb_filename, target_filename=target_filename))
|
||||
|
||||
db.session.execute(sql_string)
|
||||
|
|
|
@ -9,12 +9,19 @@ class TestBaseDB(unittest.TestCase):
|
|||
self.app_context.push()
|
||||
|
||||
db.session.execute("CREATE EXTENSION IF NOT EXISTS postgis;")
|
||||
db.session.commit()
|
||||
db.create_all()
|
||||
db.session.commit()
|
||||
|
||||
db.session.execute("CREATE TABLE IF NOT EXISTS elevation (rast raster);")
|
||||
db.session.commit()
|
||||
|
||||
def tearDown(self):
|
||||
db.session.remove()
|
||||
db.drop_all()
|
||||
|
||||
db.session.execute("DROP TABLE IF EXISTS elevaion;")
|
||||
db.session.commit()
|
||||
|
||||
self.app_context.pop()
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import os
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
from app.model import AircraftBeacon, ReceiverBeacon
|
||||
from app.gateway.bulkimport import DbFeeder
|
||||
|
||||
from tests.base import TestBaseDB, db
|
||||
|
||||
|
||||
class TestDatabase(TestBaseDB):
|
||||
def test_valid_messages(self):
|
||||
"""This test insert all valid beacons. source: https://github.com/glidernet/ogn-aprs-protocol/valid_messages"""
|
||||
|
||||
path = os.path.join(os.path.dirname(__file__), 'valid_messages')
|
||||
with DbFeeder(reference_timestamp=datetime.utcnow(), reference_timestamp_autoupdate=True) as feeder:
|
||||
with os.scandir(path) as it:
|
||||
for entry in it:
|
||||
if entry.name.endswith(".txt") and entry.is_file():
|
||||
print(f"Parsing {entry.name}")
|
||||
with open(entry.path) as file:
|
||||
for line in file:
|
||||
feeder.add(line)
|
||||
feeder.flush()
|
||||
|
||||
@unittest.skip('currently only positions are considered')
|
||||
def test_ognsdr_beacons(self):
|
||||
"""This test tests if status+position is correctly merged."""
|
||||
|
||||
aprs_stream = (
|
||||
"LILH>OGNSDR,TCPIP*,qAC,GLIDERN2:/132201h4457.61NI00900.58E&/A=000423\n"
|
||||
"LILH>OGNSDR,TCPIP*,qAC,GLIDERN2:>132201h v0.2.7.RPI-GPU CPU:0.7 RAM:770.2/968.2MB NTP:1.8ms/-3.3ppm +55.7C 7/8Acfts[1h] RF:+54-1.1ppm/-0.16dB/+7.1dB@10km[19481]/+16.8dB@10km[7/13]"
|
||||
)
|
||||
|
||||
with DbFeeder(reference_timestamp=datetime.utcnow(), reference_timestamp_autoupdate=True) as feeder:
|
||||
for line in aprs_stream.split('\n'):
|
||||
feeder.add(line)
|
||||
|
||||
self.assertEqual(len(db.session.query(ReceiverBeacon).all()), 1)
|
||||
for ab in db.session.query(ReceiverBeacon).all():
|
||||
print(ab)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -0,0 +1,18 @@
|
|||
# The following beacons are example for the (deprecated) APRS format for flarms and ogn trackers
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
# Until OGN software 0.2.6 all beacons (flarms, ogn trackers and receivers) have the dstcall "APRS"
|
||||
# These are example beacons for flarms and ogn trackers
|
||||
#
|
||||
FLRDDA5BA>APRS,qAS,LFMX:/165829h4415.41N/00600.03E'342/049/A=005524 id0ADDA5BA -454fpm -1.1rot 8.8dB 0e +51.2kHz gps4x5
|
||||
ICA4B0E3A>APRS,qAS,Letzi:/165319h4711.75N\00802.59E^327/149/A=006498 id154B0E3A -3959fpm +0.5rot 9.0dB 0e -6.3kHz gps1x3
|
||||
FLRDDB091>APRS,qAS,Letzi:/165831h4740.04N/00806.01EX152/124/A=004881 id06DD8E80 +198fpm +0.0rot 6.5dB 13e +4.0kHz gps3x4
|
||||
FLRDDDD33>APRS,qAS,LFNF:/165341h4344.27N/00547.41E'/A=000886 id06DDDD33 +020fpm +0.0rot 20.8dB 0e -14.3kHz gps3x4
|
||||
FLRDDE026>APRS,qAS,LFNF:/165341h4358.58N/00553.89E'204/055/A=005048 id06DDE026 +257fpm +0.1rot 7.2dB 0e -0.8kHz gps4x7
|
||||
ICA484A9C>APRS,qAS,LFMX:/165341h4403.50N/00559.67E'/A=001460 id05484A9C +000fpm +0.0rot 18.0dB 0e +3.5kHz gps4x7
|
||||
OGNE95A16>APRS,qAS,Sylwek:/165641h5001.94N/01956.91E'270/004/A=000000 id07E95A16 +000fpm +0.1rot 37.8dB 0e -0.4kHz
|
||||
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.6 a aircraft beacon needs just an ID, climb rate and turn rate or just the ID
|
||||
ICA3ECE59>APRS,qAS,GLDRTR:/171254h5144.78N/00616.67E'263/000/A=000075 id093D0930 +000fpm +0.0rot
|
||||
ICA3ECE59>APRS,qAS,GLDRTR:/171254h5144.78N/00616.67E'263/000/A=000075 id053ECE59
|
|
@ -0,0 +1,33 @@
|
|||
# The following beacons are example for the (deprecated) APRS format for ogn receivers
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
# Until OGN software 0.2.6 all beacons (flarms, ogn trackers and receivers) have the dstcall "APRS"
|
||||
# These are example beacons for receivers
|
||||
#
|
||||
Lachens>APRS,TCPIP*,qAC,GLIDERN2:/165334h4344.70NI00639.19E&/A=005435 v0.2.1 CPU:0.3 RAM:1764.4/2121.4MB NTP:2.8ms/+4.9ppm +47.0C RF:+0.70dB
|
||||
LFGU>APRS,TCPIP*,qAC,GLIDERN2:/165556h4907.63NI00706.41E&/A=000833 v0.2.0 CPU:0.9 RAM:281.3/458.9MB NTP:0.5ms/-19.1ppm +53.0C RF:+0.70dB
|
||||
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
|
||||
WolvesSW>APRS,TCPIP*,qAC,GLIDERN2:/165343h5232.23NI00210.91W&/A=000377 CPU:1.5 RAM:159.9/458.7MB NTP:6.6ms/-36.7ppm +45.5C RF:+130-0.4ppm/-0.1dB
|
||||
Oxford>APRS,TCPIP*,qAC,GLIDERN1:/165533h5142.96NI00109.68W&/A=000380 v0.1.3 CPU:0.9 RAM:268.8/458.6MB NTP:0.5ms/-45.9ppm +60.5C RF:+55+2.9ppm/+1.54dB
|
||||
Salland>APRS,TCPIP*,qAC,GLIDERN2:/165426h5227.93NI00620.03E&/A=000049 v0.2.2 CPU:0.7 RAM:659.3/916.9MB NTP:2.5ms/-75.0ppm RF:+0.41dB
|
||||
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
|
||||
#
|
||||
# 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]
|
||||
#
|
||||
# since 0.2.6 the ogn comment of a receiver beacon is just optional, it also can be a user comment
|
||||
Ulrichamn>APRS,TCPIP*,qAC,GLIDERN1:/085616h5747.30NI01324.77E&/A=001322
|
||||
ROBLE3>APRS,TCPIP*,qAC,GLIDERN4:/200022h3258.58SI07100.78W&/A=007229 Contact: achanes@manquehue.net, brito.felipe@gmail.com
|
||||
#
|
||||
# ... and user comment can include a 'id'
|
||||
ALFALFAL>APRS,TCPIP*,qAC,GLIDERN4:/221830h3330.40SI07007.88W&/A=008659 Alfalfal Hidroelectric Plant, Club de Planeadores Vitacurs
|
|
@ -0,0 +1,12 @@
|
|||
# The following beacons are example for the Capture APRS format
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
FLRDDEEF1>OGCAPT,qAS,CAPTURS:/062744h4845.03N/00230.46E'000/000/
|
||||
FLRDDEEF1>OGCAPT,qAS,CAPTURS:/064243h4839.64N/00236.78E'000/085/A=000410
|
||||
FLRDDEEF1>OGCAPT,qAS,CAPTURS:/064548h4838.87N/00234.03E'000/042/A=000377
|
||||
FLRDDEEF1>OGCAPT,qAS,CAPTURS:/064847h4837.95N/00234.36E'000/000/
|
||||
FLRDDEEF1>OGCAPT,qAS,CAPTURS:/065144h4837.56N/00233.80E'000/000/
|
||||
FLRDDEEF1>OGCAPT,qAS,CAPTURS:/065511h4837.63N/00233.79E'000/000/
|
||||
FLRDDEEF1>OGCAPT,qAS,CAPTURS:/070016h4837.63N/00233.77E'000/001/A=000360
|
||||
FLRDDEEF1>OGCAPT,qAS,CAPTURS:/070153h4837.62N/00233.77E'000/001/A=000344
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# The following beacons are example for the Flarm APRS format
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
# With OGN software 0.2.7 flarms have the dstcall "OGFLR"
|
||||
#
|
||||
FLRDD89C9>OGFLR,qAS,LIDH:/115054h4543.22N/01132.84E'260/072/A=002542 !W10! id06DD89C9 +198fpm -0.8rot 7.0dB 0e +0.7kHz gps2x3
|
||||
FLRDD98C6>OGFLR,qAS,LIDH:/115054h4543.21N/01132.80E'255/074/A=002535 !W83! id0ADD98C6 +158fpm -1.8rot 10.5dB 0e -0.8kHz gps2x3 s6.09 h02
|
||||
ICAA8CBA8>OGFLR,qAS,MontCAIO:/231150z4512.12N\01059.03E^192/106/A=009519 !W20! id21A8CBA8 -039fpm +0.0rot 3.5dB 2e -8.7kHz gps1x2 s6.09 h43 rDF0267
|
||||
ICAA8CBA8>OGFLR,qAS,MontCAIO:/114949h4512.44N\01059.12E^190/106/A=009522 !W33! id21A8CBA8 -039fpm +0.1rot 4.5dB 1e -8.7kHz gps1x2 +14.3dBm
|
||||
ICA3D1C35>OGFLR,qAS,Padova:/094220h4552.41N/01202.28E'110/099/A=003982 !W96! id053D1C35 -1187fpm +0.0rot 0.8dB 2e +4.5kHz gps1x2 s6.09 h32 rDD09D0
|
|
@ -0,0 +1,16 @@
|
|||
# The following beacons are example for LiveTrack24 APRS format
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
# the id25387 is the LT24 user ID that is unique.
|
||||
# GPS means that the coordinates are from the GPS unit of the smartphone vs. the GSM network.
|
||||
#
|
||||
FLRDDE48A>OGLT24,qAS,LT24:/102606h4030.47N/00338.38W'000/018/A=002267 id25387 +000fpm GPS
|
||||
FLRDDE48A>OGLT24,qAS,LT24:/102608h4030.47N/00338.38W'044/018/A=002270 id25387 +000fpm GPS
|
||||
FLRDDE48A>OGLT24,qAS,LT24:/102611h4030.47N/00338.38W'108/000/A=002280 id25387 +001fpm GPS
|
||||
FLRDDE48A>OGLT24,qAS,LT24:/102612h4030.47N/00338.38W'000/000/A=002280 id25387 +000fpm GPS
|
||||
FLRDDE48A>OGLT24,qAS,LT24:/102615h4030.47N/00338.39W'224/003/A=002280 id25387 +000fpm GPS
|
||||
FLRDDE48A>OGLT24,qAS,LT24:/102616h4030.47N/00338.38W'028/003/A=002250 id25387 -009fpm GPS
|
||||
FLRDDE48A>OGLT24,qAS,LT24:/102621h4030.47N/00338.38W'142/001/A=002267 id25387 +001fpm GPS
|
||||
FLRDDE48A>OGLT24,qAS,LT24:/102628h4030.47N/00338.38W'034/000/A=002263 id25387 +000fpm GPS
|
||||
FLRDDE48A>OGLT24,qAS,LT24:/102717h4030.47N/00338.38W'000/000/A=002263 id25387 +000fpm GPS
|
||||
FLRDDE48A>OGLT24,qAS,LT24:/110453h4030.47N/00338.38W'154/004/A=002253 id25387 +000fpm GPS
|
|
@ -0,0 +1,7 @@
|
|||
# The following beacons are example for NAVITER's APRS format version OGNAVI-1
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
NAV042121>OGNAVI,qAS,NAVITER:/140648h4550.36N/01314.85E'090/152/A=001086 !W47! id0440042121 +000fpm +0.5rot
|
||||
NAV04220E>OGNAVI,qAS,NAVITER:/140748h4552.27N/01155.61E'090/012/A=006562 !W81! id044004220E +060fpm +1.2rot
|
||||
NAV07220E>OGNAVI,qAS,NAVITER:/125447h4557.77N/01220.19E'258/056/A=006562 !W76! id1C4007220E +180fpm +0.0rot
|
||||
FLRFFFFFF>OGNAVI,NAV07220E*,qAS,NAVITER:/092002h1000.00S/01000.00W'000/000/A=003281 !W00! id2820FFFFFF +300fpm +1.7rot
|
|
@ -0,0 +1,9 @@
|
|||
# The following beacons are example for FANET (Skytraxx) APRS format
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
FNT1103CE>OGNFNT,qAS,FNB1103CE:/183727h5057.94N/00801.00Eg355/002/A=001042 !W10! id1E1103CE +03fpm
|
||||
FNT1103CE>OGNFNT,qAS,FNB1103CE:/183729h5057.94N/00801.00Eg354/001/A=001042 !W10! id1E1103CE +07fpm
|
||||
FNT1103CE>OGNFNT,qAS,FNB1103CE:/183731h5057.94N/00801.00Eg354/001/A=001042 !W10! id1E1103CE +05fpm
|
||||
FNT1103CE>OGNFNT,qAS,FNB1103CE:/183734h5057.94N/00801.00Eg354/001/A=001042 !W30! id1E1103CE -10fpm
|
||||
FNT1103CE>OGNFNT,qAS,FNB1103CE:/183736h5057.94N/00801.00Eg354/001/A=001042 !W40! id1E1103CE -02fpm
|
||||
FNB1103CE>OGNFNT,TCPIP*,qAC,GLIDERN3:/183738h5057.95NI00801.00E&/A=001042
|
|
@ -0,0 +1,19 @@
|
|||
# The following beacons are example for the APRS format for OGN receivers
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
# With OGN software 0.2.7 receivers have the dstcall "OGNSDR"
|
||||
#
|
||||
LILH>OGNSDR,TCPIP*,qAC,GLIDERN2:/132201h4457.61NI00900.58E&/A=000423
|
||||
LILH>OGNSDR,TCPIP*,qAC,GLIDERN2:>132201h v0.2.7.RPI-GPU CPU:0.7 RAM:770.2/968.2MB NTP:1.8ms/-3.3ppm +55.7C 7/8Acfts[1h] RF:+54-1.1ppm/-0.16dB/+7.1dB@10km[19481]/+16.8dB@10km[7/13]
|
||||
MontCAIO>OGNSDR,TCPIP*,qAC,GLIDERN3:/132231h4427.84NI01009.60E&/A=004822
|
||||
MontCAIO>OGNSDR,TCPIP*,qAC,GLIDERN3:>132231h v0.2.7.RPI-GPU CPU:0.8 RAM:747.0/970.5MB NTP:2.8ms/-1.0ppm +73.1C 5/5Acfts[1h] RF:+69+1.3ppm/+3.53dB/+16.9dB@10km[7697]/+23.7dB@10km[3/6]
|
||||
Padova>OGNSDR,TCPIP*,qAC,GLIDERN1:/132326h4525.38NI01156.29E&/A=000069
|
||||
Padova>OGNSDR,TCPIP*,qAC,GLIDERN1:>132326h v0.2.7.RPI-GPU CPU:0.5 RAM:605.1/970.5MB NTP:0.5ms/-2.0ppm +65.5C 1/1Acfts[1h] RF:+0-1.1ppm/+13.97dB/+17.1dB@10km[6524]/+19.9dB@10km[5/9]
|
||||
LIDH>OGNSDR,TCPIP*,qAC,GLIDERN1:/132447h4540.89NI01129.65E&/A=000328
|
||||
LIDH>OGNSDR,TCPIP*,qAC,GLIDERN1:>132447h v0.2.7.RPI-GPU CPU:0.4 RAM:593.4/970.5MB NTP:3.7ms/-7.6ppm +67.7C 5/5Acfts[1h] RF:+61+1.0ppm/+12.63dB/+3.7dB@10km[27143]/+3.3dB@10km[3/6]
|
||||
LZHL>OGNSDR,TCPIP*,qAC,GLIDERN3:/132457h4849.09NI01708.30E&/A=000528
|
||||
LZHL>OGNSDR,TCPIP*,qAC,GLIDERN3:>132457h v0.2.7.arm CPU:0.9 RAM:75.3/253.6MB NTP:2.0ms/-15.2ppm +0.1C 2/2Acfts[1h] RF:+77+1.7ppm/+2.34dB/+6.5dB@10km[5411]/+10.1dB@10km[3/5]
|
||||
BELG>OGNSDR,TCPIP*,qAC,GLIDERN3:/132507h4509.60NI00919.20E&/A=000246
|
||||
BELG>OGNSDR,TCPIP*,qAC,GLIDERN3:>132507h v0.2.7.RPI-GPU CPU:1.2 RAM:35.7/455.2MB NTP:2.5ms/-5.3ppm +67.0C 1/1Acfts[1h] RF:+79+8.8ppm/+4.97dB/-0.0dB@10km[299]/+4.9dB@10km[2/3]
|
||||
Saleve>OGNSDR,TCPIP*,qAC,GLIDERN1:/132624h4607.70NI00610.41E&/A=004198 Antenna: chinese, on a pylon, 20 meter above ground
|
||||
Saleve>OGNSDR,TCPIP*,qAC,GLIDERN1:>132624h v0.2.7.arm CPU:1.7 RAM:812.3/1022.5MB NTP:1.8ms/+4.5ppm 0.000V 0.000A 3/4Acfts[1h] RF:+67+2.9ppm/+4.18dB/+11.7dB@10km[5018]/+17.2dB@10km[8/16]
|
|
@ -0,0 +1,12 @@
|
|||
# The following beacons are example for the APRS format for ogn trackers
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
# With OGN software 0.2.7 ogn tracker have the dstcall "OGNTRK"
|
||||
#
|
||||
OGN3FC859>OGNTRK,qAS,LZHL:>093215h h00 v00 9sat/1 164m 1002.6hPa +20.2degC 0% 3.34V 14/-110.5dBm 1/min
|
||||
OGN2FD00F>OGNTRK,qAS,LZHL:/093213h4848.78N/01708.32E'000/000/A=000538 !W12! id072FD00F -058fpm +0.0rot FL003.12 32.8dB 0e -0.8kHz gps3x5
|
||||
FLRDD9C70>OGNTRK,OGN2FD00F*,qAS,LZHL:/093214h4848.77N/01708.33E'000/000/A=000515 !W56! id06DD9C70 -019fpm +0.0rot 32.2dB 0e -0.8kHz gps2x3
|
||||
FLRDD9C70>OGNTRK,OGN2FD00F*,qAS,LZHL:/093021h4848.77N/01708.33E'000/000/A=000518 !W66! id06DD9C70 -019fpm +0.0rot 29.0dB 0e -0.8kHz gps2x3 s6.09 h03
|
||||
OGN03AF2A>OGNTRK,qAS,LZHL:/092912h4848.77N/01708.33E'000/000/A=000535 !W53! id0703AF2A +000fpm +0.0rot FL003.15 4.5dB 1e -0.1kHz gps4x5 -11.2dBm
|
||||
OGN2FD00F>OGNTRK,qAS,LZHL:>092840h h00 v00 11sat/2 165m 1001.9hPa +27.1degC 0% 3.28V 14/-111.5dBm 127/min
|
||||
FLRDD9C70>OGNTRK,RELAY*,qAS,LZHL:/094124h4848.78N/01708.33E'000/000/A=000397 !W15! id06DD9C70 +099fpm +0.0rot 24.5dB 0e -1.4kHz gps10x15
|
|
@ -0,0 +1,6 @@
|
|||
# The following beacons are example for Skylines (XCsoar) APRS format
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
# The id2816 is the Pilot ID from Skylines (XCsoar) and it is unique within the skyline system
|
||||
#
|
||||
FLRDDDD78>OGSKYL,qAS,SKYLINES:/134403h4225.90N/00144.83E'000/000/A=008438 id2816 +000fpm
|
|
@ -0,0 +1,23 @@
|
|||
# The following beacons are example for Spider APRS format
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
# id3003... is the unique identifier from the SPIDER server
|
||||
# LWE is the registration within the SPIDER system
|
||||
# 3D is the quality of the signal 3D vs. 2D
|
||||
#
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/190930h3322.78S/07034.60W'000/000/A=002263 id300234010617040 +19dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/190930h3322.78S/07034.60W'000/000/A=002263 id300234010617040 +19dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/192430h3322.78S/07034.61W'000/000/A=002250 id300234010617040 +12dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/193930h3322.10S/07034.26W'273/027/A=004071 id300234010617040 +9dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/195430h3322.82S/07034.90W'000/000/A=002217 id300234010617040 +10dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/193930h3322.78S/07034.60W'348/000/A=002286 id300234010617040 +12dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/195430h3323.16S/07037.68W'302/034/A=003316 id300234010617040 +10dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/195430h3323.16S/07037.68W'302/034/A=003316 id300234010617040 +10dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/200930h3319.13S/07036.12W'128/031/A=005482 id300234010617040 +15dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/200930h3319.13S/07036.12W'128/031/A=005482 id300234010617040 +15dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/202430h3314.92S/07032.08W'138/032/A=006453 id300234010617040 +9dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/203930h3321.38S/07027.29W'104/034/A=006272 id300234010617040 +8dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/205430h3322.13S/07033.53W'296/031/A=003927 id300234010617040 +7dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/210930h3322.05S/07035.74W'165/030/A=005187 id300234010617040 +8dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/212430h3322.02S/07036.14W'281/028/A=004550 id300234010617040 +7dB LWE 3D
|
||||
FLRDDF944>OGSPID,qAS,SPIDER:/213930h3322.17S/07033.97W'332/028/A=003428 id300234010617040 +7dB LWE 3D
|
|
@ -0,0 +1,10 @@
|
|||
# The following beacons are example for SPOT APRS format
|
||||
# source: https://github.com/glidernet/ogn-aprs-protocol
|
||||
#
|
||||
# id0-28... is a unique ID within the SPOT system.
|
||||
# SPOT2 is the Spot model
|
||||
# GOOD is the battery status or some other help messages.
|
||||
#
|
||||
ICA3E7540>OGSPOT,qAS,SPOT:/161427h1448.35S/04610.86W'000/000/A=008677 id0-2860357 SPOT3 GOOD
|
||||
ICA3E7540>OGSPOT,qAS,SPOT:/162923h1431.99S/04604.33W'000/000/A=006797 id0-2860357 SPOT3 GOOD
|
||||
ICA3E7540>OGSPOT,qAS,SPOT:/163421h1430.38S/04604.43W'000/000/A=007693 id0-2860357 SPOT3 GOOD
|
Ładowanie…
Reference in New Issue