diff --git a/README.md b/README.md index 74cfd5b..919604f 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,7 @@ A database backend for the [Open Glider Network](http://wiki.glidernet.org/). The ogn-python module saves all received beacons into a database with [SQLAlchemy](http://www.sqlalchemy.org/). It connects to the OGN aprs servers with [python-ogn-client](https://github.com/glidernet/python-ogn-client). -It requires [PostgreSQL](http://www.postgresql.org/) and [PostGIS](http://www.postgis.net/). -For best performance you should use [TimescaleDB](https://www.timescale.com), which is based on PostgreSQL. +It requires [PostgreSQL](http://www.postgresql.org/), [PostGIS](http://www.postgis.net/) and [TimescaleDB](https://www.timescale.com). [Examples](https://github.com/glidernet/ogn-python/wiki/Examples) @@ -25,7 +24,7 @@ For best performance you should use [TimescaleDB](https://www.timescale.com), wh pip install -r requirements.txt ``` -3. Install [PostgreSQL](http://www.postgresql.org/) with [PostGIS](http://www.postgis.net/) Extension. +3. Install [PostgreSQL](http://www.postgresql.org/) with [PostGIS](http://www.postgis.net/) and [TimescaleDB](https://www.timescale.com) Extension. Create a database (use "ogn" as default, otherwise you have to modify the configuration, see below) 4. Optional: Install redis for asynchronous tasks (like takeoff/landing-detection) diff --git a/app/collect/ognrange.py b/app/collect/ognrange.py index cb1bcc2..bca7ab4 100644 --- a/app/collect/ognrange.py +++ b/app/collect/ognrange.py @@ -3,7 +3,7 @@ from sqlalchemy import and_, insert, update, exists, between from sqlalchemy.sql import func, null from flask import current_app -from app.model import AircraftBeacon, ReceiverCoverage +from app.model import AircraftBeacon, Receiver, ReceiverCoverage from app.utils import date_to_timestamps @@ -19,38 +19,54 @@ def update_entries(session, date, logger=None): # Filter aircraft beacons sq = ( - session.query(AircraftBeacon.location_mgrs_short, AircraftBeacon.receiver_id, AircraftBeacon.signal_quality, AircraftBeacon.altitude, AircraftBeacon.device_id) - .filter(and_(between(AircraftBeacon.timestamp, start, end), AircraftBeacon.location_mgrs_short != null(), AircraftBeacon.receiver_id != null(), AircraftBeacon.device_id != null())) + session.query(AircraftBeacon.location_mgrs_short, AircraftBeacon.receiver_name, AircraftBeacon.signal_quality, AircraftBeacon.altitude, AircraftBeacon.address) + .filter(and_(between(AircraftBeacon.timestamp, start, end), AircraftBeacon.location_mgrs_short != null(), AircraftBeacon.receiver_name != null(), AircraftBeacon.address != null())) .subquery() ) # ... and group them by reduced MGRS, receiver and date - query = ( + sq2 = ( session.query( sq.c.location_mgrs_short, - sq.c.receiver_id, + sq.c.receiver_name, func.cast(date, Date).label("date"), func.max(sq.c.signal_quality).label("max_signal_quality"), func.min(sq.c.altitude).label("min_altitude"), func.max(sq.c.altitude).label("max_altitude"), func.count(sq.c.altitude).label("aircraft_beacon_count"), - func.count(func.distinct(sq.c.device_id)).label("device_count"), + func.count(func.distinct(sq.c.address)).label("device_count"), ) - .group_by(sq.c.location_mgrs_short, sq.c.receiver_id) + .group_by(sq.c.location_mgrs_short, sq.c.receiver_name) + .subquery() + ) + + # Replace receiver_name with receiver_id + sq3 = ( + session.query( + sq2.c.location_mgrs_short, + Receiver.id.label("receiver_id"), + sq2.c.date, + sq2.c.max_signal_quality, + sq2.c.min_altitude, + sq2.c.max_altitude, + sq2.c.aircraft_beacon_count, + sq2.c.device_count, + ) + .filter(sq2.c.receiver_name == Receiver.name) .subquery() ) # if a receiver coverage entry exist --> update it upd = ( update(ReceiverCoverage) - .where(and_(ReceiverCoverage.location_mgrs_short == query.c.location_mgrs_short, ReceiverCoverage.receiver_id == query.c.receiver_id, ReceiverCoverage.date == date)) + .where(and_(ReceiverCoverage.location_mgrs_short == sq3.c.location_mgrs_short, ReceiverCoverage.receiver_id == sq3.c.receiver_id, ReceiverCoverage.date == date)) .values( { - "max_signal_quality": query.c.max_signal_quality, - "min_altitude": query.c.min_altitude, - "max_altitude": query.c.max_altitude, - "aircraft_beacon_count": query.c.aircraft_beacon_count, - "device_count": query.c.device_count, + "max_signal_quality": sq3.c.max_signal_quality, + "min_altitude": sq3.c.min_altitude, + "max_altitude": sq3.c.max_altitude, + "aircraft_beacon_count": sq3.c.aircraft_beacon_count, + "device_count": sq3.c.device_count, } ) ) @@ -61,8 +77,8 @@ def update_entries(session, date, logger=None): logger.debug("Updated receiver coverage entries: {}".format(update_counter)) # if a receiver coverage entry doesnt exist --> insert it - new_coverage_entries = session.query(query).filter( - ~exists().where(and_(ReceiverCoverage.location_mgrs_short == query.c.location_mgrs_short, ReceiverCoverage.receiver_id == query.c.receiver_id, ReceiverCoverage.date == date)) + new_coverage_entries = session.query(sq3).filter( + ~exists().where(and_(ReceiverCoverage.location_mgrs_short == sq3.c.location_mgrs_short, ReceiverCoverage.receiver_id == sq3.c.receiver_id, ReceiverCoverage.date == date)) ) ins = insert(ReceiverCoverage).from_select( diff --git a/app/collect/takeoff_landings.py b/app/collect/takeoff_landings.py index 996a4b7..d60486d 100644 --- a/app/collect/takeoff_landings.py +++ b/app/collect/takeoff_landings.py @@ -5,7 +5,7 @@ from sqlalchemy import and_, or_, insert, between, exists from sqlalchemy.sql import func, null from sqlalchemy.sql.expression import case -from app.model import AircraftBeacon, TakeoffLanding, Airport +from app.model import AircraftBeacon, Device, TakeoffLanding, Airport def update_entries(session, start, end, logger=None): @@ -38,11 +38,11 @@ def update_entries(session, start, end, logger=None): radius = 5000 # the points must not exceed this radius around the 2nd point max_agl = 200 # takeoff / landing must not exceed this altitude AGL - # get beacons for selected time range, one per device_id and timestamp + # get beacons for selected time range, one per address and timestamp sq = ( session.query(AircraftBeacon) - .distinct(AircraftBeacon.device_id, AircraftBeacon.timestamp) - .order_by(AircraftBeacon.device_id, AircraftBeacon.timestamp, AircraftBeacon.error_count) + .distinct(AircraftBeacon.address, AircraftBeacon.timestamp) + .order_by(AircraftBeacon.address, AircraftBeacon.timestamp, AircraftBeacon.error_count) .filter(AircraftBeacon.agl < max_agl) .filter(between(AircraftBeacon.timestamp, start, end)) .subquery() @@ -50,33 +50,33 @@ def update_entries(session, start, end, logger=None): # make a query with current, previous and next position sq2 = session.query( - sq.c.device_id, - func.lag(sq.c.device_id).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("device_id_prev"), - func.lead(sq.c.device_id).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("device_id_next"), + sq.c.address, + func.lag(sq.c.address).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("address_prev"), + func.lead(sq.c.address).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("address_next"), sq.c.timestamp, - func.lag(sq.c.timestamp).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("timestamp_prev"), - func.lead(sq.c.timestamp).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("timestamp_next"), + func.lag(sq.c.timestamp).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("timestamp_prev"), + func.lead(sq.c.timestamp).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("timestamp_next"), sq.c.location, - func.lag(sq.c.location).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("location_wkt_prev"), - func.lead(sq.c.location).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("location_wkt_next"), + func.lag(sq.c.location).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("location_wkt_prev"), + func.lead(sq.c.location).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("location_wkt_next"), sq.c.track, - func.lag(sq.c.track).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("track_prev"), - func.lead(sq.c.track).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("track_next"), + func.lag(sq.c.track).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("track_prev"), + func.lead(sq.c.track).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("track_next"), sq.c.ground_speed, - func.lag(sq.c.ground_speed).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("ground_speed_prev"), - func.lead(sq.c.ground_speed).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("ground_speed_next"), + func.lag(sq.c.ground_speed).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("ground_speed_prev"), + func.lead(sq.c.ground_speed).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("ground_speed_next"), sq.c.altitude, - func.lag(sq.c.altitude).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("altitude_prev"), - func.lead(sq.c.altitude).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("altitude_next"), + func.lag(sq.c.altitude).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("altitude_prev"), + func.lead(sq.c.altitude).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("altitude_next"), sq.c.climb_rate, - func.lag(sq.c.climb_rate).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("climb_rate_prev"), - func.lead(sq.c.climb_rate).over(partition_by=sq.c.device_id, order_by=sq.c.timestamp).label("climb_rate_next"), + func.lag(sq.c.climb_rate).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("climb_rate_prev"), + func.lead(sq.c.climb_rate).over(partition_by=sq.c.address, order_by=sq.c.timestamp).label("climb_rate_next"), ).subquery() # consider only positions with predecessor and successor and limit distance and duration between points sq3 = ( session.query(sq2) - .filter(and_(sq2.c.device_id_prev != null(), sq2.c.device_id_next != null())) + .filter(and_(sq2.c.address_prev != null(), sq2.c.address_next != null())) .filter(and_(func.ST_DistanceSphere(sq2.c.location, sq2.c.location_wkt_prev) < radius, func.ST_DistanceSphere(sq2.c.location, sq2.c.location_wkt_next) < radius)) .filter(sq2.c.timestamp_next - sq2.c.timestamp_prev < timedelta(seconds=duration)) .subquery() @@ -98,7 +98,7 @@ def update_entries(session, start, end, logger=None): sq3.c.ground_speed, sq3.c.altitude, case([(sq3.c.ground_speed > takeoff_speed, True), (sq3.c.ground_speed < landing_speed, False)]).label("is_takeoff"), - sq3.c.device_id, + sq3.c.address, ) .filter( or_( @@ -109,12 +109,14 @@ def update_entries(session, start, end, logger=None): .subquery() ) - # consider them if the are near airports ... + # get the device id instead of the address and consider them if the are near airports ... sq5 = ( session.query( - sq4.c.timestamp, sq4.c.track, sq4.c.is_takeoff, sq4.c.device_id, Airport.id.label("airport_id"), func.ST_DistanceSphere(sq4.c.location, Airport.location_wkt).label("airport_distance") + sq4.c.timestamp, sq4.c.track, sq4.c.is_takeoff, Device.id.label("device_id"), Airport.id.label("airport_id"), func.ST_DistanceSphere(sq4.c.location, Airport.location_wkt).label("airport_distance") ) - .filter(and_(func.ST_Within(sq4.c.location, Airport.border), between(Airport.style, 2, 5))) + .filter(and_(sq4.c.address == Device.address, + func.ST_Within(sq4.c.location, Airport.border), + between(Airport.style, 2, 5))) .subquery() ) diff --git a/app/commands/database.py b/app/commands/database.py index 96440b8..9f1c550 100644 --- a/app/commands/database.py +++ b/app/commands/database.py @@ -52,8 +52,6 @@ def init(): db.session.commit() db.create_all() - # alembic_cfg = Config(ALEMBIC_CONFIG_FILE) - # command.stamp(alembic_cfg, "head") print("Done.") @@ -62,20 +60,11 @@ def init_timescaledb(): """Initialize TimescaleDB features.""" db.session.execute("CREATE EXTENSION IF NOT EXISTS timescaledb;") - db.session.execute("SELECT create_hypertable('aircraft_beacons', 'timestamp', chunk_target_size => '2GB', if_not_exists => TRUE);") - db.session.execute("SELECT create_hypertable('receiver_beacons', 'timestamp', chunk_target_size => '2GB', if_not_exists => TRUE);") + db.session.execute("SELECT create_hypertable('aircraft_beacons', 'timestamp', chunk_time_interval => interval '6 hours', if_not_exists => TRUE);") + db.session.execute("SELECT create_hypertable('receiver_beacons', 'timestamp', chunk_time_interval => interval '6 hours', if_not_exists => TRUE);") db.session.commit() - -@user_cli.command("upgrade") -def upgrade(): - """Upgrade database to the latest version.""" - - from alembic.config import Config - from alembic import command - - alembic_cfg = Config(ALEMBIC_CONFIG_FILE) - command.upgrade(alembic_cfg, "head") + print("Done.") @user_cli.command("drop") diff --git a/app/commands/gateway.py b/app/commands/gateway.py index 7d942e3..7691e0a 100644 --- a/app/commands/gateway.py +++ b/app/commands/gateway.py @@ -1,8 +1,13 @@ +import os +import datetime + from flask import current_app from flask.cli import AppGroup +import click from ogn.client import AprsClient -from app.gateway.bulkimport import ContinuousDbFeeder + +from app.gateway.bulkimport import convert, DbFeeder user_cli = AppGroup("gateway") user_cli.help = "Connection to APRS servers." @@ -10,9 +15,7 @@ user_cli.help = "Connection to APRS servers." @user_cli.command("run") def run(aprs_user="anon-dev"): - """Run the aprs client.""" - - saver = ContinuousDbFeeder() + """Run the aprs client and feed the DB with incoming data.""" # User input validation if len(aprs_user) < 3 or len(aprs_user) > 9: @@ -23,10 +26,24 @@ def run(aprs_user="anon-dev"): client = AprsClient(aprs_user) client.connect() - try: - client.run(callback=saver.add, autoreconnect=True) - except KeyboardInterrupt: - current_app.logger.warning("\nStop ogn gateway") + with DbFeeder(prefix='continuous_import', reference_timestamp=datetime.utcnow, reference_timestamp_autoupdate=True) as feeder: + try: + client.run(callback=lambda x: feeder.add(x), autoreconnect=True) + except KeyboardInterrupt: + current_app.logger.warning("\nStop ogn gateway") - saver.flush() client.disconnect() + + +@user_cli.command("convert") +@click.argument("path") +def file_import(path): + """Convert APRS logfiles into csv files for fast bulk import.""" + + logfiles = [] + for (root, dirs, files) in os.walk(path): + for file in sorted(files): + logfiles.append(os.path.join(root, file)) + + for logfile in logfiles: + convert(logfile) diff --git a/app/config/test.py b/app/config/test.py index 8bea0a8..7024064 100644 --- a/app/config/test.py +++ b/app/config/test.py @@ -1,5 +1,6 @@ SQLALCHEMY_DATABASE_URI = "postgresql://postgres@localhost:5432/ogn_test" SQLALCHEMY_TRACK_MODIFICATIONS = False +SQLALCHEMY_ECHO = True # Celery stuff CELERY_BROKER_URL = "redis://localhost:6379/0" diff --git a/app/gateway/bulkimport.py b/app/gateway/bulkimport.py index 6c05d72..4e0a88f 100644 --- a/app/gateway/bulkimport.py +++ b/app/gateway/bulkimport.py @@ -1,3 +1,5 @@ +import os +import re from datetime import datetime, timedelta from io import StringIO @@ -9,9 +11,8 @@ from mgrs import MGRS from ogn.parser import parse, ParseError -from app.model import AircraftBeacon, ReceiverBeacon, Location -from app.utils import open_file -from app.gateway.process_tools import create_indices, add_missing_devices, add_missing_receivers, update_aircraft_beacons, update_receiver_beacons, update_receiver_location, transfer_aircraft_beacons, transfer_receiver_beacons, delete_aircraft_beacons, delete_receiver_beacons, update_aircraft_beacons_bigdata, update_receiver_beacons_bigdata, create_tables +from app.model import AircraftType, Location +from app.gateway.process_tools import open_file, create_tables, drop_tables, update_aircraft_beacons_bigdata from app import db @@ -19,6 +20,8 @@ user_cli = AppGroup("bulkimport") user_cli.help = "Tools for accelerated data import." +basepath = os.path.dirname(os.path.realpath(__file__)) + # define message types we want to proceed AIRCRAFT_BEACON_TYPES = ["aprs_aircraft", "flarm", "tracker", "fanet", "lt24", "naviter", "skylines", "spider", "spot", "flymaster"] RECEIVER_BEACON_TYPES = ["aprs_receiver", "receiver"] @@ -53,358 +56,151 @@ AIRCRAFT_BEACON_FIELDS = [ "location_mgrs", "location_mgrs_short", "agl", - "receiver_id", - "device_id", ] RECEIVER_BEACON_FIELDS = [ "location", "altitude", "dstcall", - "relay", - "version", - "platform", - "cpu_load", - "free_ram", - "total_ram", - "ntp_error", - "rt_crystal_correction", - "voltage", - "amperage", - "cpu_temp", - "senders_visible", - "senders_total", - "rec_input_noise", - "senders_signal", - "senders_messages", - "good_senders_signal", - "good_senders", - "good_and_bad_senders", ] -myMGRS = MGRS() +def initial_file_scan(file): + """Scan file and get rowcount and first server timestamp.""" + + row_count = 0 + timestamp = None + + for row in file: + row_count += 1 + if timestamp is None and row[0] == '#': + message = parse(row) + if message['aprs_type'] == 'server': + timestamp = message['timestamp'] + + file.seek(0) + return row_count, timestamp -def string_to_message(raw_string, reference_date): - global receivers +class DbFeeder: + def __init__(self, postfix, reference_timestamp, auto_update_timestamp): + self.postfix = postfix + self.reference_timestamp = reference_timestamp + self.auto_update_timestamp = auto_update_timestamp - try: - message = parse(raw_string, reference_date) - except NotImplementedError as e: - current_app.logger.error("No parser implemented for message: {}".format(raw_string)) - return None - except ParseError as e: - current_app.logger.error("Parsing error with message: {}".format(raw_string)) - return None - except TypeError as e: - current_app.logger.error("TypeError with message: {}".format(raw_string)) - return None - except Exception as e: - current_app.logger.error("Other Exception with string: {}".format(raw_string)) - return None + self.last_flush = datetime.utcnow() - # update reference receivers and distance to the receiver - if message["aprs_type"] == "position": - if message["beacon_type"] in AIRCRAFT_BEACON_TYPES + RECEIVER_BEACON_TYPES: + 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() + + self.cursor.close() + self.connection.close() + + 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: + current_app.logger.error("No parser implemented for message: {}".format(raw_string)) + return + except ParseError as e: + current_app.logger.error("Parsing error with message: {}".format(raw_string)) + return + except TypeError as e: + current_app.logger.error("TypeError with message: {}".format(raw_string)) + return + except Exception as e: + current_app.logger.error("Other Exception with string: {}".format(raw_string)) + return + + if message['aprs_type'] not in ('server', 'position'): + return + + elif message['aprs_type'] == 'server' and self.auto_update_timestamp is True: + self.reference_timestamp = message['timestamp'] + return + + elif message['aprs_type'] == 'position': latitude = message["latitude"] longitude = message["longitude"] location = Location(longitude, latitude) message["location"] = location.to_wkt() - location_mgrs = myMGRS.toMGRS(latitude, longitude).decode("utf-8") + + 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 message["beacon_type"] in AIRCRAFT_BEACON_TYPES and "gps_quality" in message: - if message["gps_quality"] is not None and "horizontal" in message["gps_quality"]: - message["gps_quality_horizontal"] = message["gps_quality"]["horizontal"] - message["gps_quality_vertical"] = message["gps_quality"]["vertical"] - del message["gps_quality"] + if "aircraft_type" in message: + message["aircraft_type"] = AircraftType(message["aircraft_type"]).name if message["aircraft_type"] in AircraftType.list() else AircraftType.UNKNOWN.name - # TODO: Fix python-ogn-client 0.91 - if "senders_messages" in message and message["senders_messages"] is not None: - message["senders_messages"] = int(message["senders_messages"]) - if "good_senders" in message and message["good_senders"] is not None: - message["good_senders"] = int(message["good_senders"]) - if "good_and_bad_senders" in message and message["good_and_bad_senders"] is not None: - message["good_and_bad_senders"] = int(message["good_and_bad_senders"]) + if "gps_quality" in message: + if message["gps_quality"] is not None and "horizontal" in message["gps_quality"]: + message["gps_quality_horizontal"] = message["gps_quality"]["horizontal"] + message["gps_quality_vertical"] = message["gps_quality"]["vertical"] + del message["gps_quality"] - return message - - -class ContinuousDbFeeder: - def __init__(self,): - self.postfix = "continuous_import" - self.last_flush = datetime.utcnow() - self.last_add_missing = datetime.utcnow() - self.last_transfer = datetime.utcnow() - - self.aircraft_buffer = StringIO() - self.receiver_buffer = StringIO() - - create_tables(self.postfix) - create_indices(self.postfix) - - def add(self, raw_string): - message = string_to_message(raw_string, reference_date=datetime.utcnow()) - - if message is None or ("raw_message" in message and message["raw_message"][0] == "#") or "beacon_type" not in message: - return - - if 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") - elif message["beacon_type"] in RECEIVER_BEACON_TYPES: + 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 - if datetime.utcnow() - self.last_flush >= timedelta(seconds=20): - self.flush() - self.prepare() - - self.aircraft_buffer = StringIO() - self.receiver_buffer = StringIO() - + if datetime.utcnow() - self.last_flush >= timedelta(seconds=5): + self._flush() self.last_flush = datetime.utcnow() - if datetime.utcnow() - self.last_add_missing >= timedelta(seconds=60): - self.add_missing() - self.last_add_missing = datetime.utcnow() - if datetime.utcnow() - self.last_transfer >= timedelta(seconds=30): - self.transfer() - self.delete_beacons() - self.last_transfer = datetime.utcnow() +def convert(sourcefile): + with open_file(sourcefile) as filehandler: + total_lines, reference_timestamp = initial_file_scan(filehandler) - def flush(self): - self.aircraft_buffer.seek(0) - self.receiver_buffer.seek(0) - - connection = db.engine.raw_connection() - cursor = connection.cursor() - cursor.copy_from(self.aircraft_buffer, "aircraft_beacons_{0}".format(self.postfix), sep=",", columns=BEACON_KEY_FIELDS + AIRCRAFT_BEACON_FIELDS) - cursor.copy_from(self.receiver_buffer, "receiver_beacons_{0}".format(self.postfix), sep=",", columns=BEACON_KEY_FIELDS + RECEIVER_BEACON_FIELDS) - connection.commit() - - self.aircraft_buffer = StringIO() - self.receiver_buffer = StringIO() - - def add_missing(self): - add_missing_receivers(self.postfix) - add_missing_devices(self.postfix) - - def prepare(self): - # make receivers complete - update_receiver_beacons(self.postfix) - update_receiver_location(self.postfix) - - # make devices complete - update_aircraft_beacons(self.postfix) - - def transfer(self): - # tranfer beacons - transfer_aircraft_beacons(self.postfix) - transfer_receiver_beacons(self.postfix) - - def delete_beacons(self): - # delete already transfered beacons - delete_receiver_beacons(self.postfix) - delete_aircraft_beacons(self.postfix) - - -class FileDbFeeder: - def __init__(self): - self.postfix = "continuous_import" - self.last_flush = datetime.utcnow() - - self.aircraft_buffer = StringIO() - self.receiver_buffer = StringIO() - - create_tables(self.postfix) - create_indices(self.postfix) - - def add(self, raw_string): - message = string_to_message(raw_string, reference_date=datetime.utcnow()) - - if message is None or ("raw_message" in message and message["raw_message"][0] == "#") or "beacon_type" not in message: - return - - if 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") - elif 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") + if reference_timestamp is not None: + auto_update_timestamp = True + postfix = str(reference_timestamp.total_seconds()) + else: + 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") + postfix = reference_timestamp.strftime("%Y_%m_%d") else: - current_app.logger.error("Ignore beacon_type: {}".format(message["beacon_type"])) + current_app.logger.error("No reference time information. Skipping file: {}".format(sourcefile)) return - def prepare(self): - # make receivers complete - add_missing_receivers(self.postfix) - update_receiver_location(self.postfix) - - # make devices complete - add_missing_devices(self.postfix) - - # prepare beacons for transfer - create_indices(self.postfix) - update_receiver_beacons_bigdata(self.postfix) - update_aircraft_beacons_bigdata(self.postfix) - - -def get_aircraft_beacons_postfixes(): - """Get the postfixes from imported aircraft_beacons logs.""" - - postfixes = db.session.execute( - r""" - SELECT DISTINCT(RIGHT(tablename, 8)) - FROM pg_catalog.pg_tables - WHERE schemaname = 'public' AND tablename LIKE 'aircraft\_beacons\_20______' - ORDER BY RIGHT(tablename, 10); - """ - ).fetchall() - - return [postfix for postfix in postfixes] - - -def export_to_path(postfix): - import os - import gzip - - pass # wtf is this? - # aircraft_beacons_file = os.path.join(path, "aircraft_beacons_{0}.csv.gz".format(postfix)) - # with gzip.open(aircraft_beacons_file, "wt", encoding="utf-8") as gzip_file: - # self.cur.copy_expert("COPY ({}) TO STDOUT WITH (DELIMITER ',', FORMAT CSV, HEADER, ENCODING 'UTF-8');".format(self.get_merged_aircraft_beacons_subquery()), gzip_file) - # receiver_beacons_file = os.path.join(path, "receiver_beacons_{0}.csv.gz".format(postfix)) - # with gzip.open(receiver_beacons_file, "wt") as gzip_file: - # self.cur.copy_expert("COPY ({}) TO STDOUT WITH (DELIMITER ',', FORMAT CSV, HEADER, ENCODING 'UTF-8');".format(self.get_merged_receiver_beacons_subquery()), gzip_file) - - -def convert(sourcefile, datestr, saver): - from app.gateway.process import string_to_message - from app.gateway.process_tools import AIRCRAFT_BEACON_TYPES, RECEIVER_BEACON_TYPES - from datetime import datetime - - fin = open_file(sourcefile) - - # get total lines of the input file - total_lines = 0 - for line in fin: - total_lines += 1 - fin.seek(0) - - current_line = 0 - steps = 100000 - reference_date = datetime.strptime(datestr + " 12:00:00", "%Y-%m-%d %H:%M:%S") - - pbar = tqdm(fin, total=total_lines) - for line in pbar: - pbar.set_description("Importing {}".format(sourcefile)) - - current_line += 1 - if current_line % steps == 0: - saver.flush() - - message = string_to_message(line.strip(), reference_date=reference_date) - if message is None: - continue - - def dictfilt(x, y): - return dict([(i, x[i]) for i in x if i in set(y)]) - - try: - if message["beacon_type"] in AIRCRAFT_BEACON_TYPES: - message = dictfilt( - message, - ( - "beacon_type", - "aprs_type", - "location_wkt", - "altitude", - "name", - "dstcall", - "relay", - "receiver_name", - "timestamp", - "track", - "ground_speed", - "address_type", - "aircraft_type", - "stealth", - "address", - "climb_rate", - "turn_rate", - "signal_quality", - "error_count", - "frequency_offset", - "gps_quality_horizontal", - "gps_quality_vertical", - "software_version", - "hardware_version", - "real_address", - "signal_power", - "distance", - "radial", - "quality", - "agl", - "location_mgrs", - "location_mgrs_short", - "receiver_id", - "device_id", - ), - ) - - beacon = AircraftBeacon(**message) - elif message["beacon_type"] in RECEIVER_BEACON_TYPES: - if "rec_crystal_correction" in message: - del message["rec_crystal_correction"] - del message["rec_crystal_correction_fine"] - beacon = ReceiverBeacon(**message) - saver.add(beacon) - except Exception as e: - print(e) - - saver.flush() - fin.close() - - -@user_cli.command("file_import") -@click.argument("path") -def file_import(path): - """Import APRS logfiles into separate logfile tables.""" - - import os - import re - - # Get Filepaths and dates to import - results = list() - for (root, dirs, files) in os.walk(path): - for file in sorted(files): - match = re.match(r"OGN_log\.txt_([0-9]{4}\-[0-9]{2}\-[0-9]{2})\.gz$", file) - if match: - results.append({"filepath": os.path.join(root, file), "datestr": match.group(1)}) - - with LogfileDbSaver() as saver: # noqa: F821 - already_imported = saver.get_datestrs() - - results = list(filter(lambda x: x["datestr"] not in already_imported, results)) - - pbar = tqdm(results) - for result in pbar: - filepath = result["filepath"] - datestr = result["datestr"] - pbar.set_description("Importing data for {}".format(datestr)) - - saver.set_datestr(datestr) - saver.create_tables() - convert(filepath, datestr, saver) - saver.add_missing_devices() - saver.add_missing_receivers() + with open_file(sourcefile) as fin: + with DbFeeder(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) diff --git a/app/gateway/process_tools.py b/app/gateway/process_tools.py index 4e9d927..9cc46f0 100644 --- a/app/gateway/process_tools.py +++ b/app/gateway/process_tools.py @@ -1,184 +1,69 @@ +import os +import gzip +import time +from contextlib import contextmanager + +from flask import current_app from app import db +@contextmanager +def open_file(filename): + """Opens a regular OR gzipped textfile for reading.""" + + file = open(filename, "rb") + a = file.read(2) + file.close() + if a == b"\x1f\x8b": + file = gzip.open(filename, "rt", encoding="latin-1") + else: + file = open(filename, "rt", encoding="latin-1") + + try: + yield file + finally: + file.close() + + +class Timer(object): + def __init__(self, name=None): + self.name = name + + def __enter__(self): + self.tstart = time.time() + + def __exit__(self, type, value, traceback): + if self.name: + print("[{}]".format(self.name)) + print("Elapsed: {}".format(time.time() - self.tstart)) + + +def drop_tables(postfix): + """Drop tables for log file import.""" + + db.session.execute(""" + DROP TABLE IF EXISTS "aircraft_beacons_{postfix}"; + DROP TABLE IF EXISTS "receiver_beacons_{postfix}"; + """.format(postfix=postfix)) + db.session.commit() + + def create_tables(postfix): """Create tables for log file import.""" - db.session.execute('DROP TABLE IF EXISTS "aircraft_beacons_{0}"; CREATE TABLE aircraft_beacons_{0} AS TABLE aircraft_beacons WITH NO DATA;'.format(postfix)) - db.session.execute('DROP TABLE IF EXISTS "receiver_beacons_{0}"; CREATE TABLE receiver_beacons_{0} AS TABLE receiver_beacons WITH NO DATA;'.format(postfix)) - db.session.commit() - - -def create_indices(postfix): - """Creates indices for aircraft- and receiver-beacons.""" - - db.session.execute( - """ - CREATE INDEX IF NOT EXISTS ix_aircraft_beacons_{0}_device_id ON "aircraft_beacons_{0}" (device_id NULLS FIRST); - CREATE INDEX IF NOT EXISTS ix_aircraft_beacons_{0}_receiver_id ON "aircraft_beacons_{0}" (receiver_id NULLS FIRST); - CREATE INDEX IF NOT EXISTS ix_aircraft_beacons_{0}_timestamp_name_receiver_name ON "aircraft_beacons_{0}" (timestamp, name, receiver_name); - CREATE INDEX IF NOT EXISTS ix_receiver_beacons_{0}_timestamp_name_receiver_name ON "receiver_beacons_{0}" (timestamp, name, receiver_name); - """.format( - postfix - ) - ) - db.session.commit() - - -def create_indices_bigdata(postfix): - """Creates indices for aircraft- and receiver-beacons.""" - - db.session.execute( - """ - CREATE INDEX IF NOT EXISTS ix_aircraft_beacons_{0}_timestamp_name_receiver_name ON "aircraft_beacons_{0}" (timestamp, name, receiver_name); - CREATE INDEX IF NOT EXISTS ix_receiver_beacons_{0}_timestamp_name_receiver_name ON "receiver_beacons_{0}" (timestamp, name, receiver_name); - """.format( - postfix - ) - ) - db.session.commit() - - -def add_missing_devices(postfix): - """Add missing devices.""" - - db.session.execute( - """ - INSERT INTO devices(address) - SELECT DISTINCT (ab.address) - FROM "aircraft_beacons_{0}" AS ab - WHERE ab.address IS NOT NULL AND NOT EXISTS (SELECT 1 FROM devices AS d WHERE d.address = ab.address) - ORDER BY ab.address; - """.format( - postfix - ) - ) - db.session.commit() - - -def add_missing_receivers(postfix): - """Add missing receivers.""" - - db.session.execute( - """ - INSERT INTO receivers(name) - SELECT DISTINCT (rb.name) - FROM "receiver_beacons_{0}" AS rb - WHERE NOT EXISTS (SELECT 1 FROM receivers AS r WHERE r.name = rb.name) - ORDER BY rb.name; - - INSERT INTO receivers(name) - SELECT DISTINCT (ab.receiver_name) - FROM "aircraft_beacons_{0}" AS ab - WHERE NOT EXISTS (SELECT 1 FROM receivers AS r WHERE r.name = ab.receiver_name) - ORDER BY ab.receiver_name; - """.format( - postfix - ) - ) - db.session.commit() - - -def update_receiver_location(postfix): - """Updates the receiver location. We need this because we want the actual location for distance calculations.""" - - db.session.execute( - """ - UPDATE receivers AS r - SET - location = sq.location, - altitude = sq.altitude - FROM ( - SELECT DISTINCT ON (rb.receiver_id) rb.receiver_id, rb.location, rb.altitude - FROM "receiver_beacons_{0}" AS rb - WHERE rb.location IS NOT NULL - ORDER BY rb.receiver_id, rb.timestamp - ) AS sq - WHERE r.id = sq.receiver_id; - """.format( - postfix - ) - ) - db.session.commit() - - -def update_receiver_beacons(postfix): - """Updates the foreign keys.""" - - db.session.execute( - """ - UPDATE receiver_beacons_{0} AS rb - SET receiver_id = r.id - FROM receivers AS r - WHERE rb.receiver_id IS NULL AND rb.name = r.name; - """.format( - postfix - ) - ) - db.session.commit() - - -def update_receiver_beacons_bigdata(postfix): - """Updates the foreign keys. - Due to performance reasons we use a new table instead of updating the old.""" - - db.session.execute( - """ - SELECT - rb.location, rb.altitude, rb.name, rb.receiver_name, rb.dstcall, rb.timestamp, - - rb.version, rb.platform, rb.cpu_load, rb.free_ram, rb.total_ram, rb.ntp_error, rb.rt_crystal_correction, rb.voltage, rb.amperage, - rb.cpu_temp, rb.senders_visible, rb.senders_total, rb.rec_input_noise, rb.senders_signal, rb.senders_messages, rb.good_senders_signal, - rb.good_senders, rb.good_and_bad_senders, - - r.id AS receiver_id - INTO "receiver_beacons_{0}_temp" - FROM "receiver_beacons_{0}" AS rb, receivers AS r - WHERE rb.name = r.name; - - DROP TABLE IF EXISTS "receiver_beacons_{0}"; - ALTER TABLE "receiver_beacons_{0}_temp" RENAME TO "receiver_beacons_{0}"; - """.format( - postfix - ) - ) - db.session.commit() - - -def update_aircraft_beacons(postfix): - """Updates the foreign keys and calculates distance/radial and quality and computes the altitude above ground level. - Elevation data has to be in the table 'elevation' with srid 4326.""" - - db.session.execute( - """ - UPDATE aircraft_beacons_{0} AS ab - SET - device_id = d.id, - receiver_id = r.id, - distance = CASE WHEN ab.location IS NOT NULL AND r.location IS NOT NULL THEN CAST(ST_DistanceSphere(ab.location, r.location) AS REAL) ELSE NULL END, - radial = CASE WHEN ab.location IS NOT NULL AND r.location IS NOT NULL THEN CAST(degrees(ST_Azimuth(ab.location, r.location)) AS SMALLINT) ELSE NULL END, - quality = CASE WHEN ab.location IS NOT NULL AND r.location IS NOT NULL AND ST_DistanceSphere(ab.location, r.location) > 0 AND ab.signal_quality IS NOT NULL - THEN CAST(signal_quality + 20*log(ST_DistanceSphere(ab.location, r.location)/10000) AS REAL) - ELSE NULL - END, - agl = CAST(ab.altitude - ST_Value(e.rast, ab.location) AS REAL) - - FROM devices AS d, receivers AS r, elevation AS e - WHERE ab.device_id IS NULL and ab.receiver_id IS NULL AND ab.address = d.address AND ab.receiver_name = r.name AND ST_Intersects(e.rast, ab.location); - """.format( - postfix - ) - ) + drop_tables(postfix) + db.session.execute(""" + CREATE TABLE aircraft_beacons_{postfix} AS TABLE aircraft_beacons WITH NO DATA; + CREATE TABLE receiver_beacons_{postfix} AS TABLE receiver_beacons WITH NO DATA; + """.format(postfix=postfix)) db.session.commit() def update_aircraft_beacons_bigdata(postfix): - """Updates the foreign keys and calculates distance/radial and quality and computes the altitude above ground level. - Elevation data has to be in the table 'elevation' with srid 4326. + """Calculates distance/radial and quality and computes the altitude above ground level. Due to performance reasons we use a new table instead of updating the old.""" - db.session.execute( - """ + db.session.execute(""" SELECT ab.location, ab.altitude, ab.name, ab.dstcall, ab.relay, ab.receiver_name, ab.timestamp, ab.track, ab.ground_speed, @@ -188,189 +73,38 @@ def update_aircraft_beacons_bigdata(postfix): ab.location_mgrs, ab.location_mgrs_short, - d.id AS device_id, - r.id AS receiver_id, CASE WHEN ab.location IS NOT NULL AND r.location IS NOT NULL THEN CAST(ST_DistanceSphere(ab.location, r.location) AS REAL) ELSE NULL END AS distance, - CASE WHEN ab.location IS NOT NULL AND r.location IS NOT NULL THEN CAST(degrees(ST_Azimuth(ab.location, r.location)) AS SMALLINT) ELSE NULL END AS radial, + CASE WHEN ab.location IS NOT NULL AND r.location IS NOT NULL THEN CAST(degrees(ST_Azimuth(ab.location, r.location)) AS SMALLINT) % 360 ELSE NULL END AS radial, CASE WHEN ab.location IS NOT NULL AND r.location IS NOT NULL AND ST_DistanceSphere(ab.location, r.location) > 0 AND ab.signal_quality IS NOT NULL THEN CAST(signal_quality + 20*log(ST_DistanceSphere(ab.location, r.location)/10000) AS REAL) ELSE NULL END AS quality, - CAST(ab.altitude - ST_Value(e.rast, ab.location) AS REAL) AS agl + CAST((ab.altitude - subtable.elev_m) AS REAL) AS agl + INTO aircraft_beacons_{postfix}_temp + FROM + aircraft_beacons_{postfix} AS ab + JOIN LATERAL ( + SELECT ab.location, MAX(ST_NearestValue(e.rast, ab.location)) as elev_m + FROM elevation e + WHERE ST_Intersects(ab.location, e.rast) + GROUP BY ab.location + ) AS subtable ON TRUE, + (SELECT name, last(location, timestamp) AS location FROM receiver_beacons_{postfix} GROUP BY name) AS r + WHERE ab.receiver_name = r.name; - INTO "aircraft_beacons_{0}_temp" - FROM "aircraft_beacons_{0}" AS ab, devices AS d, receivers AS r, elevation AS e - WHERE ab.address = d.address AND receiver_name = r.name AND ST_Intersects(e.rast, ab.location); - - DROP TABLE IF EXISTS "aircraft_beacons_{0}"; - ALTER TABLE "aircraft_beacons_{0}_temp" RENAME TO "aircraft_beacons_{0}"; - """.format( - postfix - ) - ) - db.session.commit() + DROP TABLE IF EXISTS "aircraft_beacons_{postfix}"; + ALTER TABLE "aircraft_beacons_{postfix}_temp" RENAME TO "aircraft_beacons_{postfix}"; + """.format(postfix=postfix)) -def delete_receiver_beacons(postfix): - """Delete beacons from table.""" +def export_to_path(postfix, path): + connection = db.engine.raw_connection() + cursor = connection.cursor() - db.session.execute( - """ - DELETE FROM receiver_beacons_continuous_import AS rb - USING ( - SELECT name, receiver_name, timestamp - FROM receiver_beacons_continuous_import - WHERE receiver_id IS NOT NULL - ) AS sq - WHERE rb.name = sq.name AND rb.receiver_name = sq.receiver_name AND rb.timestamp = sq.timestamp - """.format( - postfix - ) - ) - db.session.commit() + aircraft_beacons_file = os.path.join(path, "aircraft_beacons_{postfix}.csv.gz".format(postfix=postfix)) + with gzip.open(aircraft_beacons_file, "wt", encoding="utf-8") as gzip_file: + cursor.copy_expert("COPY ({}) TO STDOUT WITH (DELIMITER ',', FORMAT CSV, HEADER, ENCODING 'UTF-8');".format("SELECT * FROM aircraft_beacons_{postfix}".format(postfix=postfix)), gzip_file) - -def delete_aircraft_beacons(postfix): - """Delete beacons from table.""" - - db.session.execute( - """ - DELETE FROM aircraft_beacons_continuous_import AS ab - USING ( - SELECT name, receiver_name, timestamp - FROM aircraft_beacons_continuous_import - WHERE receiver_id IS NOT NULL and device_id IS NOT NULL - ) AS sq - WHERE ab.name = sq.name AND ab.receiver_name = sq.receiver_name AND ab.timestamp = sq.timestamp - """.format( - postfix - ) - ) - db.session.commit() - - -def get_merged_aircraft_beacons_subquery(postfix): - """Some beacons are split into position and status beacon. With this query we merge them into one beacon.""" - - return """ - SELECT - ST_AsEWKT(MAX(location)) AS location, - MAX(altitude) AS altitude, - name, - MAX(dstcall) AS dstcall, - MAX(relay) AS relay, - receiver_name, - timestamp, - MAX(track) AS track, - MAX(ground_speed) AS ground_speed, - - MAX(address_type) AS address_type, - MAX(aircraft_type) AS aircraft_type, - CAST(MAX(CAST(stealth AS int)) AS boolean) AS stealth, - MAX(address) AS address, - MAX(climb_rate) AS climb_rate, - MAX(turn_rate) AS turn_rate, - MAX(signal_quality) AS signal_quality, - MAX(error_count) AS error_count, - MAX(frequency_offset) AS frequency_offset, - MAX(gps_quality_horizontal) AS gps_quality_horizontal, - MAX(gps_quality_vertical) AS gps_quality_vertical, - MAX(software_version) AS software_version, - MAX(hardware_version) AS hardware_version, - MAX(real_address) AS real_address, - MAX(signal_power) AS signal_power, - - CAST(MAX(distance) AS REAL) AS distance, - CAST(MAX(radial) AS REAL) AS radial, - CAST(MAX(quality) AS REAL) AS quality, - CAST(MAX(agl) AS REAL) AS agl, - MAX(location_mgrs) AS location_mgrs, - MAX(location_mgrs_short) AS location_mgrs_short, - - MAX(receiver_id) AS receiver_id, - MAX(device_id) AS device_id - FROM "aircraft_beacons_{0}" AS ab - GROUP BY timestamp, name, receiver_name - ORDER BY timestamp, name, receiver_name - """.format( - postfix - ) - - -def get_merged_receiver_beacons_subquery(postfix): - """Some beacons are split into position and status beacon. With this query we merge them into one beacon.""" - - return """ - SELECT - ST_AsEWKT(MAX(location)) AS location, - MAX(altitude) AS altitude, - name, - receiver_name, - MAX(dstcall) AS dstcall, - timestamp, - - MAX(version) AS version, - MAX(platform) AS platform, - MAX(cpu_load) AS cpu_load, - MAX(free_ram) AS free_ram, - MAX(total_ram) AS total_ram, - MAX(ntp_error) AS ntp_error, - MAX(rt_crystal_correction) AS rt_crystal_correction, - MAX(voltage) AS voltage, - MAX(amperage) AS amperage, - MAX(cpu_temp) AS cpu_temp, - MAX(senders_visible) AS senders_visible, - MAX(senders_total) AS senders_total, - MAX(rec_input_noise) AS rec_input_noise, - MAX(senders_signal) AS senders_signal, - MAX(senders_messages) AS senders_messages, - MAX(good_senders_signal) AS good_senders_signal, - MAX(good_senders) AS good_senders, - MAX(good_and_bad_senders) AS good_and_bad_senders, - - MAX(receiver_id) AS receiver_id - FROM "receiver_beacons_{0}" AS rb - GROUP BY timestamp, name, receiver_name - ORDER BY timestamp, name, receiver_name - """.format( - postfix - ) - - -def transfer_aircraft_beacons(postfix): - query = """ - INSERT INTO aircraft_beacons(location, altitude, name, dstcall, relay, receiver_name, timestamp, track, ground_speed, - address_type, aircraft_type, stealth, address, climb_rate, turn_rate, signal_quality, error_count, frequency_offset, gps_quality_horizontal, gps_quality_vertical, software_version, hardware_version, real_address, signal_power, - distance, radial, quality, agl, location_mgrs, location_mgrs_short, - receiver_id, device_id) - SELECT sq.* - FROM ({}) sq - WHERE sq.receiver_id IS NOT NULL AND sq.device_id IS NOT NULL - ON CONFLICT DO NOTHING; - """.format( - get_merged_aircraft_beacons_subquery(postfix) - ) - - db.session.execute(query) - db.session.commit() - - -def transfer_receiver_beacons(postfix): - query = """ - INSERT INTO receiver_beacons(location, altitude, name, receiver_name, dstcall, timestamp, - - version, platform, cpu_load, free_ram, total_ram, ntp_error, rt_crystal_correction, voltage, - amperage, cpu_temp, senders_visible, senders_total, rec_input_noise, senders_signal, - senders_messages, good_senders_signal, good_senders, good_and_bad_senders, - - receiver_id) - SELECT sq.* - FROM ({}) sq - WHERE sq.receiver_id IS NOT NULL - ON CONFLICT DO NOTHING; - """.format( - get_merged_receiver_beacons_subquery(postfix) - ) - - db.session.execute(query) - db.session.commit() + receiver_beacons_file = os.path.join(path, "receiver_beacons_{postfix}.csv.gz".format(postfix=postfix)) + with gzip.open(receiver_beacons_file, "wt") as gzip_file: + cursor.copy_expert("COPY ({}) TO STDOUT WITH (DELIMITER ',', FORMAT CSV, HEADER, ENCODING 'UTF-8');".format("SELECT * FROM receiver_beacons_{postfix}".format(postfix=postfix)), gzip_file) diff --git a/app/model/aircraft_beacon.py b/app/model/aircraft_beacon.py index 4fd0f26..abfbe67 100644 --- a/app/model/aircraft_beacon.py +++ b/app/model/aircraft_beacon.py @@ -1,15 +1,16 @@ from sqlalchemy.sql import func -from .beacon import Beacon - from app import db +from .beacon import Beacon +from .aircraft_type import AircraftType + class AircraftBeacon(Beacon): __tablename__ = "aircraft_beacons" # Flarm specific data address_type = db.Column(db.SmallInteger) - aircraft_type = db.Column(db.SmallInteger) + aircraft_type = db.Column(db.Enum(AircraftType), nullable=False, default=AircraftType.UNKNOWN) stealth = db.Column(db.Boolean) address = db.Column(db.String) climb_rate = db.Column(db.Float(precision=2)) @@ -33,17 +34,6 @@ class AircraftBeacon(Beacon): location_mgrs_short = db.Column(db.String(9)) # reduced mgrs (9 chars), e.g. used for melissas range tool agl = db.Column(db.Float(precision=2)) - # Relations - receiver_id = db.Column(db.Integer, db.ForeignKey("receivers.id", ondelete="SET NULL")) - receiver = db.relationship("Receiver", foreign_keys=[receiver_id], backref="aircraft_beacons") - - device_id = db.Column(db.Integer, db.ForeignKey("devices.id", ondelete="SET NULL")) - device = db.relationship("Device", foreign_keys=[device_id], backref="aircraft_beacons") - - # Multi-column indices - db.Index("ix_aircraft_beacons_receiver_id_distance", "receiver_id", "distance") - db.Index("ix_aircraft_beacons_device_id_timestamp", "device_id", "timestamp") - def __repr__(self): return "" % ( self.address_type, @@ -138,7 +128,3 @@ class AircraftBeacon(Beacon): self.location_mgrs, self.location_mgrs_short, ] - - -db.Index("ix_aircraft_beacons_date_device_id_address", func.date(AircraftBeacon.timestamp), AircraftBeacon.device_id, AircraftBeacon.address) -db.Index("ix_aircraft_beacons_date_receiver_id_distance", func.date(AircraftBeacon.timestamp), AircraftBeacon.receiver_id, AircraftBeacon.distance) diff --git a/app/model/aircraft_type.py b/app/model/aircraft_type.py index 563704e..7ec95cb 100644 --- a/app/model/aircraft_type.py +++ b/app/model/aircraft_type.py @@ -1,16 +1,23 @@ -class AircraftType: - unknown = 0 - glider_or_motor_glider = 1 - tow_tug_plane = 2 - helicopter_rotorcraft = 3 - parachute = 4 - drop_plane = 5 - hang_glider = 6 - para_glider = 7 - powered_aircraft = 8 - jet_aircraft = 9 - flying_saucer = 10 - balloon = 11 - airship = 12 - unmanned_aerial_vehicle = 13 - static_object = 15 +import enum + + +class AircraftType(enum.Enum): + UNKNOWN = 0 + GLIDER_OR_MOTOR_GLIDER = 1 + TOW_TUG_PLANE = 2 + HELICOPTER_ROTORCRAFT = 3 + PARACHUTE = 4 + DROP_PLANE = 5 + HANG_GLIDER = 6 + PARA_GLIDER = 7 + POWERED_AIRCRAFT = 8 + JET_AIRCRAFT = 9 + FLYING_SAUCER = 10 + BALLOON = 11 + AIRSHIP = 12 + UNMANNED_AERIAL_VEHICLE = 13 + STATIC_OBJECT = 15 + + @staticmethod + def list(): + return list(map(lambda c: c.value, AircraftType)) diff --git a/app/model/device.py b/app/model/device.py index 4200d03..e83f2fd 100644 --- a/app/model/device.py +++ b/app/model/device.py @@ -4,6 +4,7 @@ from sqlalchemy.ext.hybrid import hybrid_property from app import db from .device_info import DeviceInfo +from app.model.aircraft_type import AircraftType class Device(db.Model): @@ -16,7 +17,7 @@ class Device(db.Model): address = db.Column(db.String, index=True) firstseen = db.Column(db.DateTime, index=True) lastseen = db.Column(db.DateTime, index=True) - aircraft_type = db.Column(db.SmallInteger, index=True) + aircraft_type = db.Column(db.Enum(AircraftType), nullable=False, default=AircraftType.UNKNOWN) stealth = db.Column(db.Boolean) software_version = db.Column(db.Float(precision=2)) hardware_version = db.Column(db.SmallInteger) diff --git a/app/model/device_info.py b/app/model/device_info.py index d721a20..7b480c7 100644 --- a/app/model/device_info.py +++ b/app/model/device_info.py @@ -1,5 +1,6 @@ from app import db from .device_info_origin import DeviceInfoOrigin +from .aircraft_type import AircraftType class DeviceInfo(db.Model): @@ -14,7 +15,7 @@ class DeviceInfo(db.Model): competition = db.Column(db.String(3)) tracked = db.Column(db.Boolean) identified = db.Column(db.Boolean) - aircraft_type = db.Column(db.SmallInteger) + aircraft_type = db.Column(db.Enum(AircraftType), nullable=False, default=AircraftType.UNKNOWN) address_origin = db.Column(db.Enum(DeviceInfoOrigin), nullable=False, default=DeviceInfoOrigin.UNKNOWN) diff --git a/app/model/device_stats.py b/app/model/device_stats.py index 5c3ac00..378be1e 100644 --- a/app/model/device_stats.py +++ b/app/model/device_stats.py @@ -1,5 +1,7 @@ from app import db +from .aircraft_type import AircraftType + class DeviceStats(db.Model): __tablename__ = "device_stats" @@ -12,7 +14,7 @@ class DeviceStats(db.Model): name = db.Column(db.String) firstseen = db.Column(db.DateTime) lastseen = db.Column(db.DateTime) - aircraft_type = db.Column(db.SmallInteger) + aircraft_type = db.Column(db.Enum(AircraftType), nullable=False, default=AircraftType.UNKNOWN) stealth = db.Column(db.Boolean) software_version = db.Column(db.Float(precision=2)) hardware_version = db.Column(db.SmallInteger) diff --git a/app/model/receiver_beacon.py b/app/model/receiver_beacon.py index 45f1901..5aad4cb 100644 --- a/app/model/receiver_beacon.py +++ b/app/model/receiver_beacon.py @@ -1,66 +1,22 @@ -from sqlalchemy.sql import func from .beacon import Beacon -from app import db - class ReceiverBeacon(Beacon): __tablename__ = "receiver_beacons" # disable irrelevant aprs fields + relay = None track = None ground_speed = None - # ReceiverBeacon specific data - version = db.Column(db.String) - platform = db.Column(db.String) - cpu_load = db.Column(db.Float(precision=2)) - free_ram = db.Column(db.Float(precision=2)) - total_ram = db.Column(db.Float(precision=2)) - ntp_error = db.Column(db.Float(precision=2)) - rt_crystal_correction = db.Column(db.Float(precision=2)) - voltage = db.Column(db.Float(precision=2)) - amperage = db.Column(db.Float(precision=2)) - cpu_temp = db.Column(db.Float(precision=2)) - senders_visible = db.Column(db.Integer) - senders_total = db.Column(db.Integer) - rec_input_noise = db.Column(db.Float(precision=2)) - senders_signal = db.Column(db.Float(precision=2)) - senders_messages = db.Column(db.Integer) - good_senders_signal = db.Column(db.Float(precision=2)) - good_senders = db.Column(db.Integer) - good_and_bad_senders = db.Column(db.Integer) - - # User comment: used for additional information like hardware configuration, web site, email address, ... - user_comment = None - - # Relations - receiver_id = db.Column(db.Integer, db.ForeignKey("receivers.id", ondelete="SET NULL")) - receiver = db.relationship("Receiver", foreign_keys=[receiver_id], backref="receiver_beacons") - - # Multi-column indices - db.Index("ix_receiver_beacons_receiver_id_name", "receiver_id", "name") - def __repr__(self): - return "" % ( - self.version, - self.platform, - self.cpu_load, - self.free_ram, - self.total_ram, - self.ntp_error, - self.rt_crystal_correction, - self.voltage, - self.amperage, - self.cpu_temp, - self.senders_visible, - self.senders_total, - self.rec_input_noise, - self.senders_signal, - self.senders_messages, - self.good_senders_signal, - self.good_senders, - self.good_and_bad_senders, + return "" % ( + self.name, + self.location, + self.altitude, + self.dstcall, + self.receiver_name, + self.timestamp, ) @classmethod @@ -74,24 +30,6 @@ class ReceiverBeacon(Beacon): "timestamp", # 'raw_message', # 'reference_timestamp', - "version", - "platform", - "cpu_load", - "free_ram", - "total_ram", - "ntp_error", - "rt_crystal_correction", - "voltage", - "amperage", - "cpu_temp", - "senders_visible", - "senders_total", - "rec_input_noise", - "senders_signal", - "senders_messages", - "good_senders_signal", - "good_senders", - "good_and_bad_senders", ] def get_values(self): @@ -104,25 +42,4 @@ class ReceiverBeacon(Beacon): self.timestamp, # self.raw_message, # self.reference_timestamp, - self.version, - self.platform, - self.cpu_load, - self.free_ram, - self.total_ram, - self.ntp_error, - self.rt_crystal_correction, - self.voltage, - self.amperage, - self.cpu_temp, - int(self.senders_visible) if self.senders_visible else None, - int(self.senders_total) if self.senders_visible else None, - self.rec_input_noise, - self.senders_signal, - int(self.senders_messages) if self.senders_messages else None, - self.good_senders_signal, - int(self.good_senders) if self.good_senders else None, - int(self.good_and_bad_senders) if self.good_and_bad_senders else None, ] - - -db.Index("ix_receiver_beacons_date_receiver_id", func.date(ReceiverBeacon.timestamp), ReceiverBeacon.receiver_id) diff --git a/app/utils.py b/app/utils.py index 69bc235..039c793 100644 --- a/app/utils.py +++ b/app/utils.py @@ -7,7 +7,7 @@ from aerofiles.seeyou import Reader from ogn.parser.utils import FEETS_TO_METER import requests -from .model import DeviceInfoOrigin, DeviceInfo, Airport, Location +from .model import AircraftType, DeviceInfoOrigin, DeviceInfo, Airport, Location DDB_URL = "http://ddb.glidernet.org/download/?t=1" @@ -51,7 +51,7 @@ def get_ddb(csv_file=None, address_origin=DeviceInfoOrigin.UNKNOWN): device_info.competition = row[4] device_info.tracked = row[5] == "Y" device_info.identified = row[6] == "Y" - device_info.aircraft_type = int(row[7]) + device_info.aircraft_type = AircraftType(int(row[7])) device_info.address_origin = address_origin device_infos.append(device_info) diff --git a/migrations/versions/079fe885ae20_remove_non_position_fields_from_.py b/migrations/versions/079fe885ae20_remove_non_position_fields_from_.py new file mode 100644 index 0000000..23bd12b --- /dev/null +++ b/migrations/versions/079fe885ae20_remove_non_position_fields_from_.py @@ -0,0 +1,76 @@ +"""Remove non position fields from AircraftBeacon and ReceiverBeacon + +Revision ID: 079fe885ae20 +Revises: 6c19cedf5fa7 +Create Date: 2019-09-25 21:42:34.924732 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '079fe885ae20' +down_revision = '6c19cedf5fa7' +branch_labels = None +depends_on = None + + +def upgrade(): + op.drop_constraint('aircraft_beacons_receiver_id_fkey', 'aircraft_beacons', type_='foreignkey') + op.drop_constraint('aircraft_beacons_device_id_fkey', 'aircraft_beacons', type_='foreignkey') + op.drop_column('aircraft_beacons', 'device_id') + op.drop_column('aircraft_beacons', 'receiver_id') + + op.drop_constraint('receiver_beacons_receiver_id_fkey', 'receiver_beacons', type_='foreignkey') + op.drop_column('receiver_beacons', 'receiver_id') + + op.drop_column('receiver_beacons', 'total_ram') + op.drop_column('receiver_beacons', 'senders_visible') + op.drop_column('receiver_beacons', 'senders_messages') + op.drop_column('receiver_beacons', 'cpu_temp') + op.drop_column('receiver_beacons', 'platform') + op.drop_column('receiver_beacons', 'rec_input_noise') + op.drop_column('receiver_beacons', 'ntp_error') + op.drop_column('receiver_beacons', 'good_senders') + op.drop_column('receiver_beacons', 'senders_total') + op.drop_column('receiver_beacons', 'cpu_load') + op.drop_column('receiver_beacons', 'free_ram') + op.drop_column('receiver_beacons', 'good_and_bad_senders') + op.drop_column('receiver_beacons', 'amperage') + op.drop_column('receiver_beacons', 'voltage') + op.drop_column('receiver_beacons', 'senders_signal') + op.drop_column('receiver_beacons', 'version') + op.drop_column('receiver_beacons', 'relay') + op.drop_column('receiver_beacons', 'rt_crystal_correction') + op.drop_column('receiver_beacons', 'good_senders_signal') + + +def downgrade(): + op.add_column('receiver_beacons', sa.Column('receiver_id', sa.INTEGER(), autoincrement=False, nullable=True)) + op.create_foreign_key('receiver_beacons_receiver_id_fkey', 'receiver_beacons', 'receivers', ['receiver_id'], ['id'], ondelete='SET NULL') + + op.add_column('receiver_beacons', sa.Column('good_senders_signal', sa.REAL(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('rt_crystal_correction', sa.REAL(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('relay', sa.VARCHAR(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('version', sa.VARCHAR(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('senders_signal', sa.REAL(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('voltage', sa.REAL(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('amperage', sa.REAL(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('good_and_bad_senders', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('free_ram', sa.REAL(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('cpu_load', sa.REAL(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('senders_total', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('good_senders', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('ntp_error', sa.REAL(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('rec_input_noise', sa.REAL(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('platform', sa.VARCHAR(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('cpu_temp', sa.REAL(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('senders_messages', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('senders_visible', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('receiver_beacons', sa.Column('total_ram', sa.REAL(), autoincrement=False, nullable=True)) + + op.add_column('aircraft_beacons', sa.Column('receiver_id', sa.INTEGER(), autoincrement=False, nullable=True)) + op.add_column('aircraft_beacons', sa.Column('device_id', sa.INTEGER(), autoincrement=False, nullable=True)) + op.create_foreign_key('aircraft_beacons_device_id_fkey', 'aircraft_beacons', 'devices', ['device_id'], ['id'], ondelete='SET NULL') + op.create_foreign_key('aircraft_beacons_receiver_id_fkey', 'aircraft_beacons', 'receivers', ['receiver_id'], ['id'], ondelete='SET NULL') diff --git a/migrations/versions/6c19cedf5fa7_use_enum_for_aircrafttype.py b/migrations/versions/6c19cedf5fa7_use_enum_for_aircrafttype.py new file mode 100644 index 0000000..af11149 --- /dev/null +++ b/migrations/versions/6c19cedf5fa7_use_enum_for_aircrafttype.py @@ -0,0 +1,76 @@ +"""Use Enum for AircraftType + +Revision ID: 6c19cedf5fa7 +Revises: be9a6dad551e +Create Date: 2019-09-24 18:37:40.224279 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '6c19cedf5fa7' +down_revision = 'be9a6dad551e' +branch_labels = None +depends_on = None + + +aircrafttype = postgresql.ENUM('UNKNOWN', 'GLIDER_OR_MOTOR_GLIDER', 'TOW_TUG_PLANE', 'HELICOPTER_ROTORCRAFT', + 'PARACHUTE', 'DROP_PLANE', 'HANG_GLIDER', 'PARA_GLIDER', 'POWERED_AIRCRAFT', + 'JET_AIRCRAFT', 'FLYING_SAUCER', 'BALLOON', 'AIRSHIP', 'UNMANNED_AERIAL_VEHICLE', + 'STATIC_OBJECT', name='aircrafttype') + +def upgrade(): + aircrafttype.create(op.get_bind()) + + for table in ['aircraft_beacons', 'devices']: + op.add_column(table, sa.Column('aircraft_type_enum', sa.Enum( + 'UNKNOWN', 'GLIDER_OR_MOTOR_GLIDER', 'TOW_TUG_PLANE', 'HELICOPTER_ROTORCRAFT', + 'PARACHUTE', 'DROP_PLANE', 'HANG_GLIDER', 'PARA_GLIDER', 'POWERED_AIRCRAFT', + 'JET_AIRCRAFT', 'FLYING_SAUCER', 'BALLOON', 'AIRSHIP', 'UNMANNED_AERIAL_VEHICLE', + 'STATIC_OBJECT', name='aircrafttype'), nullable=False, server_default='UNKNOWN')) + op.execute(""" + UPDATE {table} SET aircraft_type_enum = 'UNKNOWN' WHERE aircraft_type = 0; + UPDATE {table} SET aircraft_type_enum = 'GLIDER_OR_MOTOR_GLIDER' WHERE aircraft_type = 1; + UPDATE {table} SET aircraft_type_enum = 'TOW_TUG_PLANE' WHERE aircraft_type = 2; + UPDATE {table} SET aircraft_type_enum = 'HELICOPTER_ROTORCRAFT' WHERE aircraft_type = 3; + UPDATE {table} SET aircraft_type_enum = 'PARACHUTE' WHERE aircraft_type = 4; + UPDATE {table} SET aircraft_type_enum = 'DROP_PLANE' WHERE aircraft_type = 5; + UPDATE {table} SET aircraft_type_enum = 'HANG_GLIDER' WHERE aircraft_type = 6; + UPDATE {table} SET aircraft_type_enum = 'PARA_GLIDER' WHERE aircraft_type = 7; + UPDATE {table} SET aircraft_type_enum = 'POWERED_AIRCRAFT' WHERE aircraft_type = 8; + UPDATE {table} SET aircraft_type_enum = 'JET_AIRCRAFT' WHERE aircraft_type = 9; + UPDATE {table} SET aircraft_type_enum = 'FLYING_SAUCER' WHERE aircraft_type = 10; + UPDATE {table} SET aircraft_type_enum = 'BALLOON' WHERE aircraft_type = 11; + UPDATE {table} SET aircraft_type_enum = 'AIRSHIP' WHERE aircraft_type = 12; + UPDATE {table} SET aircraft_type_enum = 'UNMANNED_AERIAL_VEHICLE' WHERE aircraft_type = 13; + UPDATE {table} SET aircraft_type_enum = 'STATIC_OBJECT' WHERE aircraft_type = 15; + """.format(table=table)) + op.drop_column(table, 'aircraft_type') + op.alter_column(table, 'aircraft_type_enum', new_column_name='aircraft_type') + +def downgrade(): + for table in ['aircraft_beacons', 'devices']: + op.add_column(table, sa.Column('aircraft_type_int', sa.SmallInteger)) + op.execute(""" + UPDATE {table} SET aircraft_type_int = 0 WHERE aircraft_type = 'UNKNOWN'; + UPDATE {table} SET aircraft_type_int = 1 WHERE aircraft_type = 'GLIDER_OR_MOTOR_GLIDER'; + UPDATE {table} SET aircraft_type_int = 2 WHERE aircraft_type = 'TOW_TUG_PLANE'; + UPDATE {table} SET aircraft_type_int = 3 WHERE aircraft_type = 'HELICOPTER_ROTORCRAFT'; + UPDATE {table} SET aircraft_type_int = 4 WHERE aircraft_type = 'PARACHUTE'; + UPDATE {table} SET aircraft_type_int = 5 WHERE aircraft_type = 'DROP_PLANE'; + UPDATE {table} SET aircraft_type_int = 6 WHERE aircraft_type = 'HANG_GLIDER'; + UPDATE {table} SET aircraft_type_int = 7 WHERE aircraft_type = 'PARA_GLIDER'; + UPDATE {table} SET aircraft_type_int = 8 WHERE aircraft_type = 'POWERED_AIRCRAFT'; + UPDATE {table} SET aircraft_type_int = 9 WHERE aircraft_type = 'JET_AIRCRAFT'; + UPDATE {table} SET aircraft_type_int = 10 WHERE aircraft_type = 'FLYING_SAUCER'; + UPDATE {table} SET aircraft_type_int = 11 WHERE aircraft_type = 'BALLOON'; + UPDATE {table} SET aircraft_type_int = 12 WHERE aircraft_type = 'AIRSHIP'; + UPDATE {table} SET aircraft_type_int = 13 WHERE aircraft_type = 'UNMANNED_AERIAL_VEHICLE'; + UPDATE {table} SET aircraft_type_int = 15 WHERE aircraft_type = 'STATIC_OBJECT'; + """.format(table=table)) + op.drop_column(table, 'aircraft_type') + op.alter_column(table, 'aircraft_type_int', new_column_name='aircraft_type') + + aircrafttype.drop(op.get_bind()) \ No newline at end of file diff --git a/setup.py b/setup.py index c238b3d..946995c 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ setup( 'Flask-Caching==1.8.0', 'geopy==1.20.0', 'celery==4.3.0', - 'redis==3.3.11', + 'redis==3.3.11', 'aerofiles==1.0.0', 'geoalchemy2==0.6.3', 'shapely==1.6.4.post2', @@ -48,6 +48,7 @@ setup( 'psycopg2-binary==2.8.4', 'mgrs==1.3.5', 'xmlunittest==0.5.0', + 'flower==0.9.3', 'tqdm==4.39.0', 'requests==2.22.0', ], diff --git a/tests/backend/test_backends.py b/tests/backend/test_backends.py index 2ab2b4a..796c730 100644 --- a/tests/backend/test_backends.py +++ b/tests/backend/test_backends.py @@ -41,47 +41,43 @@ class TestDB(TestBaseDB, XmlTestMixin): name="FLRDD4711", receiver_name="Koenigsdf", location_wkt="0101000020E6100000211FF46C56ED26402650D7EDC6E94740", - aircraft_type=AircraftType.glider_or_motor_glider, + aircraft_type=AircraftType.GLIDER_OR_MOTOR_GLIDER, timestamp="2017-12-20 10:00:01", track=105, ground_speed=57, climb_rate=-0.5, - device_id=self.d01.id, ) self.ab12 = AircraftBeacon( name="FLRDD4711", receiver_name="Koenigsdf", location_wkt="0101000020E6100000806DEA295FED2640347D898BB6E94740", - aircraft_type=AircraftType.glider_or_motor_glider, + aircraft_type=AircraftType.GLIDER_OR_MOTOR_GLIDER, timestamp="2017-12-20 10:00:02", track=123, ground_speed=55, climb_rate=-0.4, altitude=209, - device_id=self.d01.id, ) self.ab21 = AircraftBeacon( name="FLRDD0815", receiver_name="Koenigsdf", location_wkt="0101000020E6100000F38B25BF58F22640448B6CE7FBE94740", - aircraft_type=AircraftType.powered_aircraft, + aircraft_type=AircraftType.POWERED_AIRCRAFT, timestamp="2017-12-20 09:54:30", track=280, ground_speed=80, climb_rate=-2.9, - device_id=self.d02.id, ) self.ab22 = AircraftBeacon( name="FLRDD0815", receiver_name="Bene", location_wkt="0101000020E6100000A5E8482EFFF12640DC1EAA16FEE94740", - aircraft_type=AircraftType.powered_aircraft, + aircraft_type=AircraftType.POWERED_AIRCRAFT, timestamp="2017-12-20 09:56:00", track=270, ground_speed=77, climb_rate=-1.5, altitude=543, - device_id=self.d02.id, ) db.session.add(self.ab11) db.session.add(self.ab12) diff --git a/tests/collect/test_ognrange.py b/tests/collect/test_ognrange.py index e01b001..3488fba 100644 --- a/tests/collect/test_ognrange.py +++ b/tests/collect/test_ognrange.py @@ -27,15 +27,16 @@ class TestOGNrange(TestBaseDB): # Create beacons and insert self.ab01 = AircraftBeacon( - name="FLRDD0815", receiver_name="Koenigsdf", device_id=self.dd0815.id, receiver_id=self.r01.id, timestamp="2017-12-10 10:00:00", location_mgrs_short="89ABC1267", altitude=800 + name="FLRDD0815", receiver_name="Koenigsdf", timestamp="2017-12-10 10:00:00", location_mgrs_short="89ABC1267", altitude=800 ) self.ab02 = AircraftBeacon( - name="FLRDD0815", receiver_name="Koenigsdf", device_id=self.dd0815.id, receiver_id=self.r01.id, timestamp="2017-12-10 10:00:01", location_mgrs_short="89ABC1267", altitude=850 + name="FLRDD0815", receiver_name="Koenigsdf", timestamp="2017-12-10 10:00:01", location_mgrs_short="89ABC1267", altitude=850 ) db.session.add(self.ab01) db.session.add(self.ab02) db.session.commit() + @unittest.skip('stats will replaced by timescaledb aggregates') def test_update_receiver_coverage(self): update_entries(db.session, date=date(2017, 12, 10)) diff --git a/tests/collect/test_stats.py b/tests/collect/test_stats.py index a2215df..60f0418 100644 --- a/tests/collect/test_stats.py +++ b/tests/collect/test_stats.py @@ -20,9 +20,9 @@ class TestStats(TestBaseDB): self.ab05 = AircraftBeacon(name="FLRDD4711", receiver_name="Koenigsdf", timestamp="2017-12-10 10:00:05") self.ab06 = AircraftBeacon(name="FLRDD4711", receiver_name="Koenigsdf", timestamp="2017-12-10 10:00:05") - self.rb01 = ReceiverBeacon(name="Koenigsdf", receiver_name="GLIDERN1", timestamp="2017-12-10 09:55:00", altitude=601, version="0.2.5", platform="ARM") - self.rb02 = ReceiverBeacon(name="Koenigsdf", receiver_name="GLIDERN1", timestamp="2017-12-10 10:00:00", altitude=601, version="0.2.7", platform="ARM") - self.rb03 = ReceiverBeacon(name="Koenigsdf", receiver_name="GLIDERN1", timestamp="2017-12-10 10:05:00", altitude=601, version="0.2.6", platform="ARM") + self.rb01 = ReceiverBeacon(name="Koenigsdf", receiver_name="GLIDERN1", timestamp="2017-12-10 09:55:00", altitude=601) + self.rb02 = ReceiverBeacon(name="Koenigsdf", receiver_name="GLIDERN1", timestamp="2017-12-10 10:00:00", altitude=601) + self.rb03 = ReceiverBeacon(name="Koenigsdf", receiver_name="GLIDERN1", timestamp="2017-12-10 10:05:00", altitude=601) self.r01 = Receiver(name="Koenigsdf") self.r02 = Receiver(name="Bene") @@ -33,6 +33,7 @@ class TestStats(TestBaseDB): db.session.add(self.d01) db.session.commit() + @unittest.skip('stats will replaced by timescaledb aggregates') def test_create_device_stats(self): # Compute 1st beacon self.ab01.device = self.d01 diff --git a/tests/collect/test_takeoff_landing.py b/tests/collect/test_takeoff_landing.py index d099d7e..4a423e1 100644 --- a/tests/collect/test_takeoff_landing.py +++ b/tests/collect/test_takeoff_landing.py @@ -18,151 +18,151 @@ class TestTakeoffLanding(TestBaseDB): db.session.execute("INSERT INTO airports(name, location, altitude, style) VALUES('Unterbuchen','0101000020E6100000462575029AF8264089F7098D4DE44740',635,3)") db.session.execute("UPDATE airports SET border = ST_Expand(location, 0.05)") - db.session.execute("INSERT INTO devices(address) VALUES('DDEFF7')") - db.session.execute("INSERT INTO devices(address) VALUES('DDAC7C')") + db.session.execute("INSERT INTO devices(address, aircraft_type) VALUES('DDEFF7', 'GLIDER_OR_MOTOR_GLIDER')") + db.session.execute("INSERT INTO devices(address, aircraft_type) VALUES('DDAC7C', 'GLIDER_OR_MOTOR_GLIDER')") def test_broken_rope(self): """Fill the db with a winch launch where the rope breaks. The algorithm should detect one takeoff and one landing.""" db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000009668B61829F12640330E0887F1E94740',604,'2016-07-02 10:47:12',0,0,0,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000009668B61829F12640330E0887F1E94740',604,'2016-07-02 10:47:12',0,0,0,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000009668B61829F12640330E0887F1E94740',605,'2016-07-02 10:47:32',0,0,-0.096520193,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000009668B61829F12640330E0887F1E94740',605,'2016-07-02 10:47:32',0,0,-0.096520193,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000009668B61829F12640330E0887F1E94740',606,'2016-07-02 10:47:52',0,0,-0.096520193,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000009668B61829F12640330E0887F1E94740',606,'2016-07-02 10:47:52',0,0,-0.096520193,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000009668B61829F12640330E0887F1E94740',606,'2016-07-02 10:48:12',0,0,-0.096520193,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000009668B61829F12640330E0887F1E94740',606,'2016-07-02 10:48:12',0,0,-0.096520193,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000001B2FDD2406F12640E53C762AF3E94740',606,'2016-07-02 10:48:24',284,51.85598112,0.299720599,0.1)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000001B2FDD2406F12640E53C762AF3E94740',606,'2016-07-02 10:48:24',284,51.85598112,0.299720599,0.1)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000F594AFDEBBF02640623583E5F5E94740',610,'2016-07-02 10:48:26',282,88.89596764,4.729489459,-0.2)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000F594AFDEBBF02640623583E5F5E94740',610,'2016-07-02 10:48:26',282,88.89596764,4.729489459,-0.2)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000001C0DE02D90F026401564F188F7E94740',619,'2016-07-02 10:48:27',281,94.45196562,10.66294133,-0.3)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000001C0DE02D90F026401564F188F7E94740',619,'2016-07-02 10:48:27',281,94.45196562,10.66294133,-0.3)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000ABF1D24D62F02640E12D90A0F8E94740',632,'2016-07-02 10:48:28',278,88.89596764,15.59055118,-0.7)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000ABF1D24D62F02640E12D90A0F8E94740',632,'2016-07-02 10:48:28',278,88.89596764,15.59055118,-0.7)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E610000069FD40CC38F02640C7925F2CF9E94740',650,'2016-07-02 10:48:29',273,83.33996966,18.90779782,-0.7)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E610000069FD40CC38F02640C7925F2CF9E94740',650,'2016-07-02 10:48:29',273,83.33996966,18.90779782,-0.7)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000002709AF4A0FF02640C7925F2CF9E94740',670,'2016-07-02 10:48:30',272,79.63597101,20.72136144,-0.3)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000002709AF4A0FF02640C7925F2CF9E94740',670,'2016-07-02 10:48:30',272,79.63597101,20.72136144,-0.3)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000007AA85AF8E7EF2640C7925F2CF9E94740',691,'2016-07-02 10:48:31',269,79.63597101,21.02108204,-0.4)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000007AA85AF8E7EF2640C7925F2CF9E94740',691,'2016-07-02 10:48:31',269,79.63597101,21.02108204,-0.4)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E610000068DB43D5C2EF2640E12D90A0F8E94740',712,'2016-07-02 10:48:32',267,74.07997303,21.62560325,-0.5)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E610000068DB43D5C2EF2640E12D90A0F8E94740',712,'2016-07-02 10:48:32',267,74.07997303,21.62560325,-0.5)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000EDA16AE19FEF2640FBC8C014F8E94740',728,'2016-07-02 10:48:33',266,68.52397506,12.36982474,-0.1)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000EDA16AE19FEF2640FBC8C014F8E94740',728,'2016-07-02 10:48:33',266,68.52397506,12.36982474,-0.1)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000000AFCCE1C7FEF26401564F188F7E94740',733,'2016-07-02 10:48:34',266,68.52397506,2.21488443,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000000AFCCE1C7FEF26401564F188F7E94740',733,'2016-07-02 10:48:34',266,68.52397506,2.21488443,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000275633585EEF26402FFF21FDF6E94740',731,'2016-07-02 10:48:35',267,68.52397506,-3.916687833,0.2)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000275633585EEF26402FFF21FDF6E94740',731,'2016-07-02 10:48:35',267,68.52397506,-3.916687833,0.2)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E610000015891C3539EF26402FFF21FDF6E94740',726,'2016-07-02 10:48:36',270,74.07997303,-6.329692659,1.1)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E610000015891C3539EF26402FFF21FDF6E94740',726,'2016-07-02 10:48:36',270,74.07997303,-6.329692659,1.1)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000E63FA4DFBEEE264078C1CDCFFAE94740',712,'2016-07-02 10:48:39',280,88.89596764,-2.611125222,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000E63FA4DFBEEE264078C1CDCFFAE94740',712,'2016-07-02 10:48:39',280,88.89596764,-2.611125222,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000004FF9EABD0BEE2640448B6CE7FBE94740',706,'2016-07-02 10:48:43',256,90.74796697,-0.198120396,-2.5)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000004FF9EABD0BEE2640448B6CE7FBE94740',706,'2016-07-02 10:48:43',256,90.74796697,-0.198120396,-2.5)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E610000046B921B3A0ED264003E78C28EDE94740',706,'2016-07-02 10:48:46',218,92.59996629,-0.198120396,-1.6)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E610000046B921B3A0ED264003E78C28EDE94740',706,'2016-07-02 10:48:46',218,92.59996629,-0.198120396,-1.6)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E610000005C58F3177ED2640900C4C81DFE94740',703,'2016-07-02 10:48:48',202,96.30396495,-1.402082804,-1)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E610000005C58F3177ED2640900C4C81DFE94740',703,'2016-07-02 10:48:48',202,96.30396495,-1.402082804,-1)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000211FF46C56ED26402650D7EDC6E94740',702,'2016-07-02 10:48:51',188,100.0079636,0.502921006,-1)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000211FF46C56ED26402650D7EDC6E94740',702,'2016-07-02 10:48:51',188,100.0079636,0.502921006,-1)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000806DEA295FED2640347D898BB6E94740',704,'2016-07-02 10:48:53',166,100.0079636,0.802641605,-2)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000806DEA295FED2640347D898BB6E94740',704,'2016-07-02 10:48:53',166,100.0079636,0.802641605,-2)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000337D898BB6ED26401383C0CAA1E94740',703,'2016-07-02 10:48:56',133,101.8599629,-1.803403607,-1.7)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000337D898BB6ED26401383C0CAA1E94740',703,'2016-07-02 10:48:56',133,101.8599629,-1.803403607,-1.7)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000000C05593CE2ED2640FDF675E09CE94740',700,'2016-07-02 10:48:57',123,103.7119622,-2.611125222,-1.4)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000000C05593CE2ED2640FDF675E09CE94740',700,'2016-07-02 10:48:57',123,103.7119622,-2.611125222,-1.4)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000F0CCF1F778EE26409FA87F2394E94740',693,'2016-07-02 10:49:00',105,111.1199596,-2.809245618,-0.6)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000F0CCF1F778EE26409FA87F2394E94740',693,'2016-07-02 10:49:00',105,111.1199596,-2.809245618,-0.6)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000C9073D9B55EF2640BD5296218EE94740',687,'2016-07-02 10:49:04',97,112.9719589,-1.605283211,-0.1)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000C9073D9B55EF2640BD5296218EE94740',687,'2016-07-02 10:49:04',97,112.9719589,-1.605283211,-0.1)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000006F8104C5EF26400C24287E8CE94740',682,'2016-07-02 10:49:06',97,114.8239582,-2.407924816,-0.2)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000006F8104C5EF26400C24287E8CE94740',682,'2016-07-02 10:49:06',97,114.8239582,-2.407924816,-0.2)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000A0648535A8F02640F597DD9387E94740',676,'2016-07-02 10:49:10',97,118.5279569,-1.402082804,0.1)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000A0648535A8F02640F597DD9387E94740',676,'2016-07-02 10:49:10',97,118.5279569,-1.402082804,0.1)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000D70FC48C03F22640621386EE7FE94740',672,'2016-07-02 10:49:16',97,116.6759575,-1.000762002,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000D70FC48C03F22640621386EE7FE94740',672,'2016-07-02 10:49:16',97,116.6759575,-1.000762002,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000A72C431CEBF22640CB7F48BF7DE94740',666,'2016-07-02 10:49:20',84,114.8239582,-1.605283211,-1.5)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000A72C431CEBF22640CB7F48BF7DE94740',666,'2016-07-02 10:49:20',84,114.8239582,-1.605283211,-1.5)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000BFCAA145B6F32640BD5296218EE94740',662,'2016-07-02 10:49:24',49,111.1199596,-1.203962408,-1.5)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000BFCAA145B6F32640BD5296218EE94740',662,'2016-07-02 10:49:24',49,111.1199596,-1.203962408,-1.5)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E610000074DA40A70DF4264077E09C11A5E94740',659,'2016-07-02 10:49:27',23,107.4159609,-1.402082804,-1.4)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E610000074DA40A70DF4264077E09C11A5E94740',659,'2016-07-02 10:49:27',23,107.4159609,-1.402082804,-1.4)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000009AE3EFF11CF42640347D898BB6E94740',656,'2016-07-02 10:49:29',4,101.8599629,-0.797561595,-1.8)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000009AE3EFF11CF42640347D898BB6E94740',656,'2016-07-02 10:49:29',4,101.8599629,-0.797561595,-1.8)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E610000074DA40A70DF426402650D7EDC6E94740',654,'2016-07-02 10:49:31',347,101.8599629,-1.706883414,-1)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E610000074DA40A70DF426402650D7EDC6E94740',654,'2016-07-02 10:49:31',347,101.8599629,-1.706883414,-1)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000156A4DF38EF3264086EE7F6DEAE94740',649,'2016-07-02 10:49:36',312,98.15596427,-1.503683007,-1.4)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000156A4DF38EF3264086EE7F6DEAE94740',649,'2016-07-02 10:49:36',312,98.15596427,-1.503683007,-1.4)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000FAEDEBC039F32640E53C762AF3E94740',644,'2016-07-02 10:49:38',295,96.30396495,-3.012446025,-1.2)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000FAEDEBC039F32640E53C762AF3E94740',644,'2016-07-02 10:49:38',295,96.30396495,-3.012446025,-1.2)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000B04A0F30E0F22640FBC8C014F8E94740',635,'2016-07-02 10:49:40',284,94.45196562,-5.125730251,-0.7)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B04A0F30E0F22640FBC8C014F8E94740',635,'2016-07-02 10:49:40',284,94.45196562,-5.125730251,-0.7)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000F38B25BF58F22640448B6CE7FBE94740',623,'2016-07-02 10:49:43',279,92.59996629,-2.809245618,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000F38B25BF58F22640448B6CE7FBE94740',623,'2016-07-02 10:49:43',279,92.59996629,-2.809245618,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000A5E8482EFFF12640DC1EAA16FEE94740',617,'2016-07-02 10:49:45',279,88.89596764,-3.312166624,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000A5E8482EFFF12640DC1EAA16FEE94740',617,'2016-07-02 10:49:45',279,88.89596764,-3.312166624,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000009F17012859F12640F0AAF40003EA4740',607,'2016-07-02 10:49:49',279,81.48797034,-1.300482601,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000009F17012859F12640F0AAF40003EA4740',607,'2016-07-02 10:49:49',279,81.48797034,-1.300482601,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000004B5658830AF12640873E323005EA4740',607,'2016-07-02 10:49:51',278,74.07997303,-0.294640589,-0.1)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000004B5658830AF12640873E323005EA4740',607,'2016-07-02 10:49:51',278,74.07997303,-0.294640589,-0.1)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000A0648535A8F0264006373FEB07EA4740',605,'2016-07-02 10:49:54',280,61.11597775,-0.096520193,0.5)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000A0648535A8F0264006373FEB07EA4740',605,'2016-07-02 10:49:54',280,61.11597775,-0.096520193,0.5)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E6100000C74B378941F02640E88C28ED0DEA4740',604,'2016-07-02 10:49:58',292,48.15198247,0.101600203,0.4)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E6100000C74B378941F02640E88C28ED0DEA4740',604,'2016-07-02 10:49:58',292,48.15198247,0.101600203,0.4)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E61000001B5A643BDFEF264045DB1EAA16EA4740',604,'2016-07-02 10:50:04',302,25.92799056,0.203200406,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E61000001B5A643BDFEF264045DB1EAA16EA4740',604,'2016-07-02 10:50:04',302,25.92799056,0.203200406,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E610000042D2948AB3EF264074029A081BEA4740',604,'2016-07-02 10:50:10',300,5.555997978,0.101600203,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E610000042D2948AB3EF264074029A081BEA4740',604,'2016-07-02 10:50:10',300,5.555997978,0.101600203,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7','0101000020E610000013AB192CAFEF264074029A081BEA4740',603,'2016-07-02 10:50:16',0,0,-0.096520193,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDEFF7', 'Koenigsdf', 'DDEFF7', 'GLIDER_OR_MOTOR_GLIDER','0101000020E610000013AB192CAFEF264074029A081BEA4740',603,'2016-07-02 10:50:16',0,0,-0.096520193,0)" ) - db.session.execute("UPDATE aircraft_beacons SET device_id = d.id, agl = altitude - 600 FROM devices d WHERE d.address='DDEFF7'") + db.session.execute("UPDATE aircraft_beacons SET agl = altitude - 602;") db.session.commit() # find the takeoff and the landing @@ -181,213 +181,213 @@ class TestTakeoffLanding(TestBaseDB): """Here we have a broken rope where the glider passes again the threshold for take off.""" db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',597,'2019-04-13 09:20:14',0,0,-0.096519999,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',597,'2019-04-13 09:20:14',0,0,-0.096519999,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',595,'2019-04-13 09:20:23',0,0,-0.096519999,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',595,'2019-04-13 09:20:23',0,0,-0.096519999,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',595,'2019-04-13 09:20:29',0,0,-0.096519999,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',595,'2019-04-13 09:20:29',0,0,-0.096519999,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',591,'2019-04-13 09:21:01',0,0,-0.096519999,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',591,'2019-04-13 09:21:01',0,0,-0.096519999,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',591,'2019-04-13 09:21:02',0,0,-0.096519999,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',591,'2019-04-13 09:21:02',0,0,-0.096519999,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',589,'2019-04-13 09:21:13',0,0,-0.096519999,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',589,'2019-04-13 09:21:13',0,0,-0.096519999,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',589,'2019-04-13 09:21:29',0,0,-0.096519999,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',589,'2019-04-13 09:21:29',0,0,-0.096519999,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',590,'2019-04-13 09:21:48',0,0,-0.096519999,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',590,'2019-04-13 09:21:48',0,0,-0.096519999,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',591,'2019-04-13 09:22:02',0,0,-0.096519999,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',591,'2019-04-13 09:22:02',0,0,-0.096519999,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',592,'2019-04-13 09:22:22',0,0,0.1016,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B5040FE689EA264091FC62C92FEA4740',592,'2019-04-13 09:22:22',0,0,0.1016,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000ED0DBE3099EA2640CA32C4B12EEA4740',593,'2019-04-13 09:22:40',102,25.925552,0.2032,0.60000002)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000ED0DBE3099EA2640CA32C4B12EEA4740',593,'2019-04-13 09:22:40',102,25.925552,0.2032,0.60000002)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E610000026E4839ECDEA26401904560E2DEA4740',594,'2019-04-13 09:22:42',100,68.517532,0.2032,-0.30000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E610000026E4839ECDEA26401904560E2DEA4740',594,'2019-04-13 09:22:42',100,68.517532,0.2032,-0.30000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000D044D8F0F4EA2640513AB7F62BEA4740',595,'2019-04-13 09:22:43',101,81.480309,1.91008,-0.30000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000D044D8F0F4EA2640513AB7F62BEA4740',595,'2019-04-13 09:22:43',101,81.480309,1.91008,-0.30000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E610000025396A721EEB2640A00B49532AEA4740',600,'2019-04-13 09:22:44',100,90.739433,5.6337199,-0.30000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E610000025396A721EEB2640A00B49532AEA4740',600,'2019-04-13 09:22:44',100,90.739433,5.6337199,-0.30000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E610000009E8B4814EEB2640CA41AA3B29EA4740',608,'2019-04-13 09:22:45',100,88.887611,9.2557602,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E610000009E8B4814EEB2640CA41AA3B29EA4740',608,'2019-04-13 09:22:45',100,88.887611,9.2557602,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000087084327AEB264019133C9827EA4740',620,'2019-04-13 09:22:46',99,87.035782,12.3698,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000087084327AEB264019133C9827EA4740',620,'2019-04-13 09:22:46',99,87.035782,12.3698,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000246416B4A3EB264052499D8026EA4740',634,'2019-04-13 09:22:47',97,83.33213,15.2908,-0.89999998)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000246416B4A3EB264052499D8026EA4740',634,'2019-04-13 09:22:47',97,83.33213,15.2908,-0.89999998)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000007958A835CDEB264067E4CDF425EA4740',650,'2019-04-13 09:22:48',94,79.628487,16.093439,-2.0999999)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000007958A835CDEB264067E4CDF425EA4740',650,'2019-04-13 09:22:48',94,79.628487,16.093439,-2.0999999)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000CE4C3AB7F6EB264067E4CDF425EA4740',667,'2019-04-13 09:22:49',91,75.924835,16.89608,-0.89999998)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000CE4C3AB7F6EB264067E4CDF425EA4740',667,'2019-04-13 09:22:49',91,75.924835,16.89608,-0.89999998)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000248613AB19EC264067E4CDF425EA4740',684,'2019-04-13 09:22:50',91,72.221184,17.20088,-0.30000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000248613AB19EC264067E4CDF425EA4740',684,'2019-04-13 09:22:50',91,72.221184,17.20088,-0.30000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000005C532ACE3EEC264067E4CDF425EA4740',701,'2019-04-13 09:22:51',90,68.517532,16.89608,-0.30000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000005C532ACE3EEC264067E4CDF425EA4740',701,'2019-04-13 09:22:51',90,68.517532,16.89608,-0.30000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000003FF9C5925FEC264067E4CDF425EA4740',718,'2019-04-13 09:22:52',91,68.517532,16.19504,-0.30000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000003FF9C5925FEC264067E4CDF425EA4740',718,'2019-04-13 09:22:52',91,68.517532,16.19504,-0.30000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000229F615780EC264052499D8026EA4740',733,'2019-04-13 09:22:53',89,59.258408,14.28496,-1.5)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000229F615780EC264052499D8026EA4740',733,'2019-04-13 09:22:53',89,59.258408,14.28496,-1.5)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B11D82BD9CEC264052499D8026EA4740',741,'2019-04-13 09:22:54',89,57.406582,3.62204,0.30000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B11D82BD9CEC264052499D8026EA4740',741,'2019-04-13 09:22:54',89,57.406582,3.62204,0.30000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000789CA223B9EC264067E4CDF425EA4740',736,'2019-04-13 09:22:55',88,53.70293,-8.3413601,0.89999998)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000789CA223B9EC264067E4CDF425EA4740',736,'2019-04-13 09:22:55',88,53.70293,-8.3413601,0.89999998)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B0AE00B9D7EC264052499D8026EA4740',724,'2019-04-13 09:22:56',89,62.962055,-14.5796,0.30000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B0AE00B9D7EC264052499D8026EA4740',724,'2019-04-13 09:22:56',89,62.962055,-14.5796,0.30000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000E97B17DCFCEC264052499D8026EA4740',710,'2019-04-13 09:22:57',92,85.18396,-12.1666,1.8)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000E97B17DCFCEC264052499D8026EA4740',710,'2019-04-13 09:22:57',92,85.18396,-12.1666,1.8)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000CC2A62EB2CED26408A7FFE6825EA4740',703,'2019-04-13 09:22:58',96,99.998558,-5.92836,2.0999999)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000CC2A62EB2CED26408A7FFE6825EA4740',703,'2019-04-13 09:22:58',96,99.998558,-5.92836,2.0999999)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000936DEA295FED2640B5B55F5124EA4740',701,'2019-04-13 09:22:59',102,99.998558,0.40132001,2.4000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000936DEA295FED2640B5B55F5124EA4740',701,'2019-04-13 09:22:59',102,99.998558,0.40132001,2.4000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000CB10C7BAB8ED2640D95F764F1EEA4740',704,'2019-04-13 09:23:01',116,92.591263,2.21488,5.6999998)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000CB10C7BAB8ED2640D95F764F1EEA4740',704,'2019-04-13 09:23:01',116,92.591263,2.21488,5.6999998)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000002005593CE2ED2640AE38FBF019EA4740',707,'2019-04-13 09:23:02',133,88.887611,2.8143201,7.5)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000002005593CE2ED2640AE38FBF019EA4740',707,'2019-04-13 09:23:02',133,88.887611,2.8143201,7.5)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000925CFE43FAED2640E77D426313EA4740',709,'2019-04-13 09:23:03',147,88.887611,1.50876,6.9000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000925CFE43FAED2640E77D426313EA4740',709,'2019-04-13 09:23:03',147,88.887611,1.50876,6.9000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000CA65AD8E09EE26404BF9EABD0BEA4740',710,'2019-04-13 09:23:04',159,88.887611,0.60452002,6.9000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000CA65AD8E09EE26404BF9EABD0BEA4740',710,'2019-04-13 09:23:04',159,88.887611,0.60452002,6.9000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000003DF9EABD0BEE2640448B6CE7FBE94740',709,'2019-04-13 09:23:06',183,92.591263,-0.79755998,5.4000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000003DF9EABD0BEE2640448B6CE7FBE94740',709,'2019-04-13 09:23:06',183,92.591263,-0.79755998,5.4000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000005917B7D100EE2640CBA145B6F3E94740',707,'2019-04-13 09:23:07',192,94.443085,-2.1082001,3.3)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000005917B7D100EE2640CBA145B6F3E94740',707,'2019-04-13 09:23:07',192,94.443085,-2.1082001,3.3)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E610000076711B0DE0ED2640A098966BE4E94740',701,'2019-04-13 09:23:09',196,99.998558,-2.61112,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E610000076711B0DE0ED2640A098966BE4E94740',701,'2019-04-13 09:23:09',196,99.998558,-2.61112,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000AF25E4839EED2640E08D2B1BC3E94740',695,'2019-04-13 09:23:13',202,105.55404,0.1016,1.5)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000AF25E4839EED2640E08D2B1BC3E94740',695,'2019-04-13 09:23:13',202,105.55404,0.1016,1.5)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000002152DD4931ED2640AF16FEF9A3E94740',696,'2019-04-13 09:23:17',214,103.70221,-0.39624,2.4000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000002152DD4931ED2640AF16FEF9A3E94740',696,'2019-04-13 09:23:17',214,103.70221,-0.39624,2.4000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000EA62C92F96EC264021BF58F28BE94740',696,'2019-04-13 09:23:21',236,105.55404,0.1016,2.4000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000EA62C92F96EC264021BF58F28BE94740',696,'2019-04-13 09:23:21',236,105.55404,0.1016,2.4000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000005CC2ABD203EC26404478557A80E94740',694,'2019-04-13 09:23:24',249,107.40586,-1.2039599,2.0999999)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000005CC2ABD203EC26404478557A80E94740',694,'2019-04-13 09:23:24',249,107.40586,-1.2039599,2.0999999)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000004182E2C798EB26402FEC0A907BE94740',690,'2019-04-13 09:23:26',256,111.10951,-2.2098,2.4000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000004182E2C798EB26402FEC0A907BE94740',690,'2019-04-13 09:23:26',256,111.10951,-2.2098,2.4000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000098A1F63EEEA26407DBD9CEC79E94740',685,'2019-04-13 09:23:29',268,114.81316,-1.00076,1.8)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000098A1F63EEEA26407DBD9CEC79E94740',685,'2019-04-13 09:23:29',268,114.81316,-1.00076,1.8)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000D1915CFE43EA2640E11A79337DE94740',684,'2019-04-13 09:23:32',277,112.96133,-0.79755998,0.89999998)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000D1915CFE43EA2640E11A79337DE94740',684,'2019-04-13 09:23:32',277,112.96133,-0.79755998,0.89999998)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E610000044BE55C4D6E926404478557A80E94740',682,'2019-04-13 09:23:34',280,114.81316,-2.0065999,0.60000002)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E610000044BE55C4D6E926404478557A80E94740',682,'2019-04-13 09:23:34',280,114.81316,-2.0065999,0.60000002)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E610000029ED0DBE30E92640932B1BC389E94740',675,'2019-04-13 09:23:37',292,118.51682,-1.2039599,2.4000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E610000029ED0DBE30E92640932B1BC389E94740',675,'2019-04-13 09:23:37',292,118.51682,-1.2039599,2.4000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000D467FD40CCE826409AA87F2394E94740',675,'2019-04-13 09:23:39',307,114.81316,0.80264002,4.1999998)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000D467FD40CCE826409AA87F2394E94740',675,'2019-04-13 09:23:39',307,114.81316,0.80264002,4.1999998)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000D49AE61DA7E826404BC8073D9BE94740',677,'2019-04-13 09:23:40',316,112.96133,2.0116799,5.4000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000D49AE61DA7E826404BC8073D9BE94740',677,'2019-04-13 09:23:40',316,112.96133,2.0116799,5.4000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000009CC420B072E826403D9B559FABE94740',680,'2019-04-13 09:23:42',339,103.70221,1.0058399,5.4000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000009CC420B072E826403D9B559FABE94740',680,'2019-04-13 09:23:42',339,103.70221,1.0058399,5.4000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000002A762AF369E8264019D3728DBCE94740',681,'2019-04-13 09:23:44',358,96.294907,0.2032,4.1999998)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000002A762AF369E8264019D3728DBCE94740',681,'2019-04-13 09:23:44',358,96.294907,0.2032,4.1999998)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000F1F44A5986E82640992A1895D4E94740',679,'2019-04-13 09:23:47',10,94.443085,-2.2098,0.89999998)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000F1F44A5986E82640992A1895D4E94740',679,'2019-04-13 09:23:47',10,94.443085,-2.2098,0.89999998)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000007F2E244DA9E826401982BD9CECE94740',671,'2019-04-13 09:23:50',14,96.294907,-2.2098,0.60000002)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000007F2E244DA9E826401982BD9CECE94740',671,'2019-04-13 09:23:50',14,96.294907,-2.2098,0.60000002)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000D3EFCCF1F7E8264099ACB00615EA4740',662,'2019-04-13 09:23:55',21,103.70221,-2.7127199,1.2)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000D3EFCCF1F7E8264099ACB00615EA4740',662,'2019-04-13 09:23:55',21,103.70221,-2.7127199,1.2)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E610000028B1759646E92640513AB7F62BEA4740',655,'2019-04-13 09:23:58',40,103.70221,-1.905,4.1999998)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E610000028B1759646E92640513AB7F62BEA4740',655,'2019-04-13 09:23:58',40,103.70221,-1.905,4.1999998)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000009A99999999E9264059B71B5736EA4740',652,'2019-04-13 09:24:00',60,99.998558,-1.2039599,5.0999999)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000009A99999999E9264059B71B5736EA4740',652,'2019-04-13 09:24:00',60,99.998558,-1.2039599,5.0999999)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000448B6CE7FBE9264091DE96B53AEA4740',649,'2019-04-13 09:24:02',78,98.146736,-2.5095201,4.1999998)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000448B6CE7FBE9264091DE96B53AEA4740',649,'2019-04-13 09:24:02',78,98.146736,-2.5095201,4.1999998)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000000AA4BA9362EA264091DE96B53AEA4740',643,'2019-04-13 09:24:04',93,98.146736,-2.8092401,3)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000000AA4BA9362EA264091DE96B53AEA4740',643,'2019-04-13 09:24:04',93,98.146736,-2.8092401,3)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B4958DE1C4EA26402E81BA6E37EA4740',636,'2019-04-13 09:24:06',100,98.146736,-3.71856,1.2)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B4958DE1C4EA26402E81BA6E37EA4740',636,'2019-04-13 09:24:06',100,98.146736,-3.71856,1.2)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000005D6DC5FEB2EB2640B597933D2FEA4740',619,'2019-04-13 09:24:11',100,94.443085,-3.71856,-0.30000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000005D6DC5FEB2EB2640B597933D2FEA4740',619,'2019-04-13 09:24:11',100,94.443085,-3.71856,-0.30000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000005BB1BFEC9EEC2640EEDCDAAF28EA4740',602,'2019-04-13 09:24:16',98,96.294907,-2.7127199,0.30000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000005BB1BFEC9EEC2640EEDCDAAF28EA4740',602,'2019-04-13 09:24:16',98,96.294907,-2.7127199,0.30000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000B003E78C28ED2640A01A2FDD24EA4740',598,'2019-04-13 09:24:19',98,88.887611,-0.70104003,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000B003E78C28ED2640A01A2FDD24EA4740',598,'2019-04-13 09:24:19',98,88.887611,-0.70104003,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000009298966BE4ED26408A8EE4F21FEA4740',597,'2019-04-13 09:24:24',100,59.258408,-0.096519999,0.30000001)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000009298966BE4ED26408A8EE4F21FEA4740',597,'2019-04-13 09:24:24',100,59.258408,-0.096519999,0.30000001)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E610000075C601E130EE2640EEFAA6C31DEA4740',596,'2019-04-13 09:24:28',86,25.925552,0,-4.1999998)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E610000075C601E130EE2640EEFAA6C31DEA4740',596,'2019-04-13 09:24:28',86,25.925552,0,-4.1999998)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E610000091B1E4174BEE26408A8EE4F21FEA4740',597,'2019-04-13 09:24:31',66,14.814602,-0.096519999,-3)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E610000091B1E4174BEE26408A8EE4F21FEA4740',597,'2019-04-13 09:24:31',66,14.814602,-0.096519999,-3)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000001F27563358EE26402722222222EA4740',597,'2019-04-13 09:24:38',0,0,0.1016,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000001F27563358EE26402722222222EA4740',597,'2019-04-13 09:24:38',0,0,0.1016,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000CAFFDAD453EE26402722222222EA4740',598,'2019-04-13 09:24:58',0,0,0.1016,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000CAFFDAD453EE26402722222222EA4740',598,'2019-04-13 09:24:58',0,0,0.1016,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E6100000586C9DA551EE26402722222222EA4740',597,'2019-04-13 09:25:18',0,0,0.1016,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E6100000586C9DA551EE26402722222222EA4740',597,'2019-04-13 09:25:18',0,0,0.1016,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E610000003098A1F63EE2640EEEBC03923EA4740',596,'2019-04-13 09:25:36',54,1.8518252,0.1016,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E610000003098A1F63EE2640EEEBC03923EA4740',596,'2019-04-13 09:25:36',54,1.8518252,0.1016,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E610000003CDF1F778EE2640A01A2FDD24EA4740',594,'2019-04-13 09:25:48',76,1.8518252,-0.096519999,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E610000003CDF1F778EE2640A01A2FDD24EA4740',594,'2019-04-13 09:25:48',76,1.8518252,-0.096519999,0)" ) db.session.execute( - "INSERT INTO aircraft_beacons(name, receiver_name, address, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','0101000020E61000001FF46C567DEE2640A01A2FDD24EA4740',593,'2019-04-13 09:25:59',0,0,-0.096519999,0)" + "INSERT INTO aircraft_beacons(name, receiver_name, address, aircraft_type, location, altitude, timestamp, track, ground_speed, climb_rate, turn_rate) VALUES('FLRDDAC7C','Koenigsd2','DDAC7C','GLIDER_OR_MOTOR_GLIDER','0101000020E61000001FF46C567DEE2640A01A2FDD24EA4740',593,'2019-04-13 09:25:59',0,0,-0.096519999,0)" ) - db.session.execute("UPDATE aircraft_beacons SET device_id = d.id, agl = altitude - 600 FROM devices d WHERE d.address='DDAC7C'") + db.session.execute("UPDATE aircraft_beacons SET agl = altitude - 602;") db.session.commit() # find the takeoff and the landing diff --git a/tests/model/all_classes.py b/tests/model/all_classes.py index 09af68a..15eabb7 100644 --- a/tests/model/all_classes.py +++ b/tests/model/all_classes.py @@ -1,4 +1,5 @@ import os +from enum import EnumMeta import unittest import inspect @@ -10,14 +11,17 @@ import app.model # noqa: E402 class TestStringMethods(unittest.TestCase): def test_string(self): - - try: - for name, obj in inspect.getmembers(app.model): - print("Testing: {}".format(name)) - if inspect.isclass(obj): + failures = 0 + for name, obj in inspect.getmembers(app.model): + try: + if inspect.isclass(obj) and not isinstance(obj, EnumMeta): print(obj()) - except AttributeError as e: - raise AssertionError(e) + except AttributeError as e: + print("Failed: {}".format(name)) + failures += 1 + + if failures > 0: + raise AssertionError("Not all classes are good") if __name__ == "__main__": diff --git a/tests/test_utils.py b/tests/test_utils.py index 30af1b6..a460d35 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -28,7 +28,7 @@ class TestStringMethods(unittest.TestCase): self.assertEqual(device.competition, "CU") self.assertTrue(device.tracked) self.assertTrue(device.identified) - self.assertEqual(device.aircraft_type, AircraftType.glider_or_motor_glider) + self.assertEqual(device.aircraft_type, AircraftType.GLIDER_OR_MOTOR_GLIDER) def test_get_trackable(self): devices = get_ddb(os.path.dirname(__file__) + "/custom_ddb.txt")