No more stats table -> functionality of TimescaleDB

Changed PK in tables device/receiver from id to name
Altered FK in table takeoff_landings/logbook from device_id to address
Updated Flarm release dates
pull/78/head
Konstantin Gründger 2020-05-15 19:01:17 +02:00
rodzic 695478654b
commit a18e6aeab3
17 zmienionych plików z 16 dodań i 525 usunięć

Wyświetl plik

@ -22,7 +22,6 @@ CELERYBEAT_SCHEDULE = {
"update-takeoff-and-landing": {"task": "update_takeoff_landings", "schedule": timedelta(hours=1), "kwargs": {"last_minutes": 90}}, "update-takeoff-and-landing": {"task": "update_takeoff_landings", "schedule": timedelta(hours=1), "kwargs": {"last_minutes": 90}},
"update-logbook": {"task": "update_logbook_entries", "schedule": timedelta(hours=2), "kwargs": {"day_offset": 0}}, "update-logbook": {"task": "update_logbook_entries", "schedule": timedelta(hours=2), "kwargs": {"day_offset": 0}},
"update-max-altitudes": {"task": "update_logbook_max_altitude", "schedule": timedelta(hours=1), "kwargs": {"day_offset": 0}}, "update-max-altitudes": {"task": "update_logbook_max_altitude", "schedule": timedelta(hours=1), "kwargs": {"day_offset": 0}},
"update-stats-daily": {"task": "update_stats", "schedule": crontab(hour=0, minute=5), "kwargs": {"day_offset": -1}},
"update-logbook-daily": {"task": "update_logbook_entries", "schedule": crontab(hour=1, minute=0), "kwargs": {"day_offset": -1}}, "update-logbook-daily": {"task": "update_logbook_entries", "schedule": crontab(hour=1, minute=0), "kwargs": {"day_offset": -1}},
"purge_old_data": {"task": "purge_old_data", "schedule": timedelta(hours=1), "kwargs": {"max_hours": 48}}, "purge_old_data": {"task": "purge_old_data", "schedule": timedelta(hours=1), "kwargs": {"max_hours": 48}},
} }

Wyświetl plik

@ -4,7 +4,7 @@ from flask import request, render_template, send_file
from app import db from app import db
from app import cache from app import cache
from app.model import Airport, Country, Device, Logbook, Receiver, ReceiverStats from app.model import Airport, Country, Device, Logbook, Receiver
from app.main import bp from app.main import bp
@ -184,14 +184,3 @@ def download_flight():
buffer.seek(0) buffer.seek(0)
return send_file(buffer, as_attachment=True, attachment_filename="wtf.igc", mimetype="text/plain") return send_file(buffer, as_attachment=True, attachment_filename="wtf.igc", mimetype="text/plain")
@bp.route("/statistics.html")
def statistics():
today = datetime.date.today()
today = datetime.date(2018, 7, 31)
receiverstats = db.session.query(ReceiverStats).filter(ReceiverStats.date == today)
return render_template("statistics.html", title="Receiver Statistics", receiverstats=receiverstats)

Wyświetl plik

@ -2,20 +2,14 @@
from .aircraft_type import AircraftType from .aircraft_type import AircraftType
from .beacon import Beacon from .beacon import Beacon
from .country import Country from .country import Country
from .country_stats import CountryStats
from .device import Device from .device import Device
from .device_info import DeviceInfo from .device_info import DeviceInfo
from .device_info_origin import DeviceInfoOrigin from .device_info_origin import DeviceInfoOrigin
from .device_stats import DeviceStats
from .aircraft_beacon import AircraftBeacon from .aircraft_beacon import AircraftBeacon
from .receiver_beacon import ReceiverBeacon from .receiver_beacon import ReceiverBeacon
from .receiver import Receiver from .receiver import Receiver
from .receiver_stats import ReceiverStats
from .takeoff_landing import TakeoffLanding from .takeoff_landing import TakeoffLanding
from .airport import Airport from .airport import Airport
from .logbook import Logbook from .logbook import Logbook
from .receiver_coverage import ReceiverCoverage
from .relation_stats import RelationStats
from .flights2d import Flight2D
from .geo import Location from .geo import Location

Wyświetl plik

@ -56,75 +56,5 @@ class AircraftBeacon(Beacon):
self.quality, self.quality,
self.location_mgrs, self.location_mgrs,
self.location_mgrs_short, self.location_mgrs_short,
self.agl,
) )
@classmethod
def get_columns(self):
return [
"location",
"altitude",
"name",
"dstcall",
"relay",
"receiver_name",
"timestamp",
"track",
"ground_speed",
# 'raw_message',
# 'reference_timestamp',
"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",
"location_mgrs",
"location_mgrs_short",
]
def get_values(self):
return [
self.location_wkt,
int(self.altitude) if self.altitude else None,
self.name,
self.dstcall,
self.relay,
self.receiver_name,
self.timestamp,
self.track,
self.ground_speed,
# self.raw_message,
# self.reference_timestamp,
self.address_type,
self.aircraft_type,
self.stealth,
self.address,
self.climb_rate,
self.turn_rate,
self.signal_quality,
self.error_count,
self.frequency_offset,
self.gps_quality_horizontal,
self.gps_quality_vertical,
self.software_version,
self.hardware_version,
self.real_address,
self.signal_power,
self.distance,
self.radial,
self.quality,
self.location_mgrs,
self.location_mgrs_short,
]

Wyświetl plik

@ -10,14 +10,14 @@ from app import db
class Beacon(AbstractConcreteBase, db.Model): class Beacon(AbstractConcreteBase, db.Model):
# APRS data # APRS data
location_wkt = db.Column("location", Geometry("POINT", srid=4326)) location = db.Column("location", Geometry("POINT", srid=4326))
altitude = db.Column(db.Float(precision=2)) altitude = db.Column(db.Float(precision=2))
name = db.Column(db.String, primary_key=True, nullable=True) name = db.Column(db.String, primary_key=True)
dstcall = db.Column(db.String) dstcall = db.Column(db.String)
relay = db.Column(db.String) relay = db.Column(db.String)
receiver_name = db.Column(db.String(9), primary_key=True, nullable=True) receiver_name = db.Column(db.String(9), primary_key=True)
timestamp = db.Column(db.DateTime, primary_key=True, nullable=True) timestamp = db.Column(db.DateTime, primary_key=True)
symboltable = None symboltable = None
symbolcode = None symbolcode = None
track = db.Column(db.SmallInteger) track = db.Column(db.SmallInteger)
@ -31,15 +31,3 @@ class Beacon(AbstractConcreteBase, db.Model):
# Debug information # Debug information
raw_message = None raw_message = None
reference_timestamp = None reference_timestamp = None
@hybrid_property
def location(self):
if self.location_wkt is None:
return None
coords = to_shape(self.location_wkt)
return Location(lat=coords.y, lon=coords.x)
@location.expression
def location(cls):
return cls.location_wkt

Wyświetl plik

@ -1,17 +0,0 @@
from app import db
class CountryStats(db.Model):
__tablename__ = "country_stats"
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.Date)
# Static data
aircraft_beacon_count = db.Column(db.Integer)
device_count = db.Column(db.Integer)
# Relations
country_id = db.Column(db.Integer, db.ForeignKey("countries.gid", ondelete="SET NULL"), index=True)
country = db.relationship("Country", foreign_keys=[country_id], backref=db.backref("stats", order_by="CountryStats.date.asc()"))

Wyświetl plik

@ -10,9 +10,8 @@ from app.model.aircraft_type import AircraftType
class Device(db.Model): class Device(db.Model):
__tablename__ = "devices" __tablename__ = "devices"
id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String, primary_key=True)
name = db.Column(db.String, index=True)
# address = db.Column(db.String(6), index=True) # address = db.Column(db.String(6), index=True)
address = db.Column(db.String, index=True) address = db.Column(db.String, index=True)
firstseen = db.Column(db.DateTime, index=True) firstseen = db.Column(db.DateTime, index=True)
@ -38,6 +37,9 @@ class Device(db.Model):
return [info for info in query.all()] return [info for info in query.all()]
EXPIRY_DATES = { EXPIRY_DATES = {
7.0: datetime.date(2021, 10, 31),
6.83: datetime.date(2021, 10, 31),
6.82: datetime.date(2021, 5, 31),
6.81: datetime.date(2021, 1, 31), 6.81: datetime.date(2021, 1, 31),
6.80: datetime.date(2021, 1, 31), 6.80: datetime.date(2021, 1, 31),
6.67: datetime.date(2020, 10, 31), 6.67: datetime.date(2020, 10, 31),

Wyświetl plik

@ -1,52 +0,0 @@
from app import db
from .aircraft_type import AircraftType
class DeviceStats(db.Model):
__tablename__ = "device_stats"
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.Date)
# Static data
name = db.Column(db.String)
firstseen = db.Column(db.DateTime)
lastseen = db.Column(db.DateTime)
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)
real_address = db.Column(db.String(6))
# Statistic data
max_altitude = db.Column(db.Float(precision=2))
receiver_count = db.Column(db.SmallInteger)
aircraft_beacon_count = db.Column(db.Integer)
jumps = db.Column(db.SmallInteger)
ambiguous = db.Column(db.Boolean)
quality = db.Column(db.Float(precision=2))
# Relation statistic data
quality_offset = db.Column(db.Float(precision=2))
# Ranking data
max_altitude_ranking_worldwide = db.Column(db.Integer)
max_altitude_ranking_country = db.Column(db.Integer)
receiver_count_ranking_worldwide = db.Column(db.Integer)
receiver_count_ranking_country = db.Column(db.Integer)
aircraft_beacon_count_ranking_worldwide = db.Column(db.Integer)
aircraft_beacon_count_ranking_country = db.Column(db.Integer)
quality_ranking_worldwide = db.Column(db.Integer)
quality_ranking_country = db.Column(db.Integer)
# Relations
device_id = db.Column(db.Integer, db.ForeignKey("devices.id", ondelete="SET NULL"), index=True)
device = db.relationship("Device", foreign_keys=[device_id], backref=db.backref("stats", order_by="DeviceStats.date.asc()"))
def __repr__(self):
return "<DeviceStats: %s,%s,%s,%s>" % (self.date, self.receiver_count, self.aircraft_beacon_count, self.max_altitude)
db.Index("ix_device_stats_date_device_id", DeviceStats.date, DeviceStats.device_id)

Wyświetl plik

@ -1,24 +0,0 @@
from geoalchemy2.types import Geometry
from app import db
class Flight2D(db.Model):
__tablename__ = "flights2d"
date = db.Column(db.Date, primary_key=True)
flight_type = db.Column(db.SmallInteger, primary_key=True)
path_wkt = db.Column("path", Geometry("MULTILINESTRING", srid=4326))
path_simple_wkt = db.Column("path_simple", Geometry("MULTILINESTRING", srid=4326)) # this is the path simplified with ST_Simplify(path, 0.0001)
# Relations
device_id = db.Column(db.Integer, db.ForeignKey("devices.id", ondelete="SET NULL"), primary_key=True)
device = db.relationship("Device", foreign_keys=[device_id], backref="flights2d")
def __repr__(self):
return "<Flight %s: %s,%s>" % (self.date, self.path_wkt, self.path_simple_wkt)
db.Index("ix_flights2d_date_device_id", Flight2D.date, Flight2D.device_id)
# db.Index('ix_flights2d_date_path', Flight2D.date, Flight2D.path_wkt) --> CREATE INDEX ix_flights2d_date_path ON flights2d USING GIST("date", path)

Wyświetl plik

@ -9,6 +9,7 @@ class Logbook(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
reftime = db.Column(db.DateTime, index=True) reftime = db.Column(db.DateTime, index=True)
address = db.Column(db.String, index=True)
takeoff_timestamp = db.Column(db.DateTime) takeoff_timestamp = db.Column(db.DateTime)
takeoff_track = db.Column(db.SmallInteger) takeoff_track = db.Column(db.SmallInteger)
landing_timestamp = db.Column(db.DateTime) landing_timestamp = db.Column(db.DateTime)
@ -22,9 +23,6 @@ class Logbook(db.Model):
landing_airport_id = db.Column(db.Integer, db.ForeignKey("airports.id", ondelete="CASCADE"), index=True) landing_airport_id = db.Column(db.Integer, db.ForeignKey("airports.id", ondelete="CASCADE"), index=True)
landing_airport = db.relationship("Airport", foreign_keys=[landing_airport_id]) landing_airport = db.relationship("Airport", foreign_keys=[landing_airport_id])
device_id = db.Column(db.Integer, db.ForeignKey("devices.id", ondelete="CASCADE"), index=True)
device = db.relationship("Device", foreign_keys=[device_id], backref=db.backref("logbook", order_by="Logbook.reftime"))
@hybrid_property @hybrid_property
def duration(self): def duration(self):
return None if (self.landing_timestamp is None or self.takeoff_timestamp is None) else self.landing_timestamp - self.takeoff_timestamp return None if (self.landing_timestamp is None or self.takeoff_timestamp is None) else self.landing_timestamp - self.takeoff_timestamp

Wyświetl plik

@ -9,14 +9,13 @@ from app import db
class Receiver(db.Model): class Receiver(db.Model):
__tablename__ = "receivers" __tablename__ = "receivers"
id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(9), primary_key=True)
location_wkt = db.Column("location", Geometry("POINT", srid=4326)) location_wkt = db.Column("location", Geometry("POINT", srid=4326))
altitude = db.Column(db.Float(precision=2)) altitude = db.Column(db.Float(precision=2))
name = db.Column(db.String(9), index=True)
firstseen = db.Column(db.DateTime, index=True) firstseen = db.Column(db.DateTime, index=True)
lastseen = db.Column(db.DateTime, index=True) lastseen = db.Column(db.DateTime, index=True)
timestamp = db.Column(db.DateTime, index=True)
version = db.Column(db.String) version = db.Column(db.String)
platform = db.Column(db.String) platform = db.Column(db.String)

Wyświetl plik

@ -18,28 +18,3 @@ class ReceiverBeacon(Beacon):
self.receiver_name, self.receiver_name,
self.timestamp, self.timestamp,
) )
@classmethod
def get_columns(self):
return [
"location",
"altitude",
"name",
"dstcall",
"receiver_name",
"timestamp",
# 'raw_message',
# 'reference_timestamp',
]
def get_values(self):
return [
self.location_wkt,
int(self.altitude) if self.altitude else None,
self.name,
self.dstcall,
self.receiver_name,
self.timestamp,
# self.raw_message,
# self.reference_timestamp,
]

Wyświetl plik

@ -1,23 +0,0 @@
from app import db
class ReceiverCoverage(db.Model):
__tablename__ = "receiver_coverages"
location_mgrs_short = db.Column(db.String(9), primary_key=True)
date = db.Column(db.Date, primary_key=True)
max_signal_quality = db.Column(db.Float)
max_altitude = db.Column(db.Float(precision=2))
min_altitude = db.Column(db.Float(precision=2))
aircraft_beacon_count = db.Column(db.Integer)
device_count = db.Column(db.SmallInteger)
# Relations
receiver_id = db.Column(db.Integer, db.ForeignKey("receivers.id", ondelete="SET NULL"), primary_key=True)
receiver = db.relationship("Receiver", foreign_keys=[receiver_id], backref=db.backref("receiver_coverages", order_by="ReceiverCoverage.date.asc()"))
db.Index("ix_receiver_coverages_date_receiver_id", ReceiverCoverage.date, ReceiverCoverage.receiver_id)
db.Index("ix_receiver_coverages_receiver_id_date", ReceiverCoverage.receiver_id, ReceiverCoverage.date)

Wyświetl plik

@ -1,41 +0,0 @@
from geoalchemy2.types import Geometry
from app import db
class ReceiverStats(db.Model):
__tablename__ = "receiver_stats"
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.Date)
# Static data
firstseen = db.Column(db.DateTime, index=True)
lastseen = db.Column(db.DateTime, index=True)
location_wkt = db.Column("location", Geometry("POINT", srid=4326))
altitude = db.Column(db.Float(precision=2))
version = db.Column(db.String)
platform = db.Column(db.String)
# Statistic data
aircraft_beacon_count = db.Column(db.Integer)
aircraft_count = db.Column(db.SmallInteger)
max_distance = db.Column(db.Float)
quality = db.Column(db.Float(precision=2))
# Relation statistic data
quality_offset = db.Column(db.Float(precision=2))
# Ranking data
aircraft_beacon_count_ranking = db.Column(db.SmallInteger)
aircraft_count_ranking = db.Column(db.SmallInteger)
max_distance_ranking = db.Column(db.SmallInteger)
quality_ranking = db.Column(db.Integer)
# Relations
receiver_id = db.Column(db.Integer, db.ForeignKey("receivers.id", ondelete="SET NULL"), index=True)
receiver = db.relationship("Receiver", foreign_keys=[receiver_id], backref=db.backref("stats", order_by="ReceiverStats.date.asc()"))
db.Index("ix_receiver_stats_date_receiver_id", ReceiverStats.date, ReceiverStats.receiver_id)

Wyświetl plik

@ -1,26 +0,0 @@
from app import db
class RelationStats(db.Model):
__tablename__ = "relation_stats"
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.Date)
# Statistic data
quality = db.Column(db.Float(precision=2))
beacon_count = db.Column(db.Integer)
# Relations
device_id = db.Column(db.Integer, db.ForeignKey("devices.id", ondelete="SET NULL"), index=True)
device = db.relationship("Device", foreign_keys=[device_id], backref="relation_stats")
receiver_id = db.Column(db.Integer, db.ForeignKey("receivers.id", ondelete="SET NULL"), index=True)
receiver = db.relationship("Receiver", foreign_keys=[receiver_id], backref="relation_stats")
def __repr__(self):
return "<RelationStats: %s,%s,%s>" % (self.date, self.quality, self.beacon_count)
db.Index("ix_relation_stats_date_device_id", RelationStats.date, RelationStats.device_id, RelationStats.receiver_id)
db.Index("ix_relation_stats_date_receiver_id", RelationStats.date, RelationStats.receiver_id, RelationStats.device_id)

Wyświetl plik

@ -4,7 +4,7 @@ from app import db
class TakeoffLanding(db.Model): class TakeoffLanding(db.Model):
__tablename__ = "takeoff_landings" __tablename__ = "takeoff_landings"
device_id = db.Column(db.Integer, db.ForeignKey("devices.id", ondelete="SET NULL"), primary_key=True) address = db.Column(db.String, primary_key=True)
airport_id = db.Column(db.Integer, db.ForeignKey("airports.id", ondelete="SET NULL"), primary_key=True) airport_id = db.Column(db.Integer, db.ForeignKey("airports.id", ondelete="SET NULL"), primary_key=True)
timestamp = db.Column(db.DateTime, primary_key=True) timestamp = db.Column(db.DateTime, primary_key=True)
@ -13,4 +13,3 @@ class TakeoffLanding(db.Model):
# Relations # Relations
airport = db.relationship("Airport", foreign_keys=[airport_id], backref="takeoff_landings") airport = db.relationship("Airport", foreign_keys=[airport_id], backref="takeoff_landings")
device = db.relationship("Device", foreign_keys=[device_id], backref="takeoff_landings", order_by="TakeoffLanding.timestamp")

Wyświetl plik

@ -1,199 +0,0 @@
from datetime import datetime, date
import unittest
from tests.base import TestBaseDB, db
from app.model import AircraftBeacon, ReceiverBeacon, Receiver, Device, DeviceStats
from app.collect.stats import create_device_stats
class TestStats(TestBaseDB):
def setUp(self):
super().setUp()
# Prepare Beacons
self.ab01 = AircraftBeacon(name="FLRDD4711", receiver_name="Koenigsdf", timestamp="2017-12-10 10:00:01")
self.ab02 = AircraftBeacon(name="FLRDD4711", receiver_name="Koenigsdf", timestamp="2017-12-10 10:00:02")
self.ab03 = AircraftBeacon(name="FLRDD4711", receiver_name="Koenigsdf", timestamp="2017-12-10 10:00:03")
self.ab04 = AircraftBeacon(name="FLRDD4711", receiver_name="Koenigsdf", timestamp="2017-12-10 10:00:04")
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)
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")
self.d01 = Device(address="DD4711")
db.session.add(self.r01)
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
self.ab01.receiver = self.r01
db.session.add(self.ab01)
db.session.commit()
today = date(2017, 12, 10)
create_device_stats(db.session, date=today)
devicestats = db.session.query(DeviceStats).all()
self.assertEqual(len(devicestats), 1)
self.assertEqual(devicestats[0].device, self.d01)
self.assertEqual(devicestats[0].max_altitude, None)
self.assertEqual(devicestats[0].receiver_count, 1)
self.assertEqual(devicestats[0].aircraft_beacon_count, 1)
self.assertEqual(devicestats[0].date, datetime.strptime("2017-12-10", "%Y-%m-%d").date())
self.assertEqual(devicestats[0].firstseen, datetime(2017, 12, 10, 10, 0, 1))
self.assertEqual(devicestats[0].lastseen, datetime(2017, 12, 10, 10, 0, 1))
self.assertEqual(devicestats[0].aircraft_type, None)
self.assertEqual(devicestats[0].stealth, None)
self.assertEqual(devicestats[0].software_version, None)
self.assertEqual(devicestats[0].hardware_version, None)
self.assertEqual(devicestats[0].real_address, None)
# Compute 2nd beacon: set altitude, aircraft_type and stealth
self.ab02.device = self.d01
self.ab02.receiver = self.r01
self.ab02.altitude = 200
self.ab02.aircraft_type = 3
self.ab02.stealth = False
db.session.add(self.ab02)
db.session.commit()
create_device_stats(db.session, date=today)
devicestats = db.session.query(DeviceStats).all()
self.assertEqual(len(devicestats), 1)
self.assertEqual(devicestats[0].device, self.d01)
self.assertEqual(devicestats[0].max_altitude, 200)
self.assertEqual(devicestats[0].receiver_count, 1)
self.assertEqual(devicestats[0].aircraft_beacon_count, 2)
self.assertEqual(devicestats[0].date, datetime.strptime("2017-12-10", "%Y-%m-%d").date())
self.assertEqual(devicestats[0].firstseen, datetime(2017, 12, 10, 10, 0, 1))
self.assertEqual(devicestats[0].lastseen, datetime(2017, 12, 10, 10, 0, 2))
self.assertEqual(devicestats[0].aircraft_type, 3)
self.assertEqual(devicestats[0].stealth, False)
self.assertEqual(devicestats[0].software_version, None)
self.assertEqual(devicestats[0].hardware_version, None)
self.assertEqual(devicestats[0].real_address, None)
# Compute 3rd beacon: changed software version, but with error_count > 0
self.ab03.device = self.d01
self.ab03.receiver = self.r01
self.ab03.error_count = 1
self.ab03.software_version = 6.01
db.session.add(self.ab03)
db.session.commit()
create_device_stats(db.session, date=today)
devicestats = db.session.query(DeviceStats).all()
self.assertEqual(len(devicestats), 1)
self.assertEqual(devicestats[0].device, self.d01)
self.assertEqual(devicestats[0].max_altitude, 200)
self.assertEqual(devicestats[0].receiver_count, 1)
self.assertEqual(devicestats[0].aircraft_beacon_count, 2)
self.assertEqual(devicestats[0].date, datetime.strptime("2017-12-10", "%Y-%m-%d").date())
self.assertEqual(devicestats[0].firstseen, datetime(2017, 12, 10, 10, 0, 1))
self.assertEqual(devicestats[0].lastseen, datetime(2017, 12, 10, 10, 0, 2))
self.assertEqual(devicestats[0].aircraft_type, 3)
self.assertEqual(devicestats[0].stealth, False)
self.assertEqual(devicestats[0].software_version, None)
self.assertEqual(devicestats[0].hardware_version, None)
self.assertEqual(devicestats[0].real_address, None)
# Compute 4. beacon: another receiver, greater altitude, software_version, hardware_version, real_address
self.ab04.device = self.d01
self.ab04.receiver = self.r02
self.ab04.altitude = 250
self.ab04.software_version = 6.01
self.ab04.hardware_version = 15
self.ab04.real_address = "DDALFA"
db.session.add(self.ab04)
db.session.commit()
create_device_stats(db.session, date=today)
devicestats = db.session.query(DeviceStats).all()
self.assertEqual(len(devicestats), 1)
self.assertEqual(devicestats[0].device, self.d01)
self.assertEqual(devicestats[0].max_altitude, 250)
self.assertEqual(devicestats[0].receiver_count, 2)
self.assertEqual(devicestats[0].aircraft_beacon_count, 3)
self.assertEqual(devicestats[0].date, datetime.strptime("2017-12-10", "%Y-%m-%d").date())
self.assertEqual(devicestats[0].firstseen, datetime(2017, 12, 10, 10, 0, 1))
self.assertEqual(devicestats[0].lastseen, datetime(2017, 12, 10, 10, 0, 4))
self.assertEqual(devicestats[0].aircraft_type, 3)
self.assertEqual(devicestats[0].stealth, False)
self.assertEqual(devicestats[0].software_version, 6.01)
self.assertEqual(devicestats[0].hardware_version, 15)
self.assertEqual(devicestats[0].real_address, "DDALFA")
# Compute 5. beacon: lower altitude, stealth
self.ab05.device = self.d01
self.ab05.receiver = self.r02
self.ab05.altitude = 100
self.ab05.stealth = True
db.session.add(self.ab05)
db.session.commit()
create_device_stats(db.session, date=today)
devicestats = db.session.query(DeviceStats).all()
self.assertEqual(len(devicestats), 1)
self.assertEqual(devicestats[0].device, self.d01)
self.assertEqual(devicestats[0].max_altitude, 250)
self.assertEqual(devicestats[0].receiver_count, 2)
self.assertEqual(devicestats[0].aircraft_beacon_count, 4)
self.assertEqual(devicestats[0].date, datetime.strptime("2017-12-10", "%Y-%m-%d").date())
self.assertEqual(devicestats[0].firstseen, datetime(2017, 12, 10, 10, 0, 1))
self.assertEqual(devicestats[0].lastseen, datetime(2017, 12, 10, 10, 0, 5))
self.assertEqual(devicestats[0].aircraft_type, 3)
self.assertEqual(devicestats[0].stealth, True)
self.assertEqual(devicestats[0].software_version, 6.01)
self.assertEqual(devicestats[0].hardware_version, 15)
self.assertEqual(devicestats[0].real_address, "DDALFA")
# Compute 6. beacon: beacon from past, greater altitude, newer version
self.ab06.device = self.d01
self.ab06.receiver = self.r02
self.ab06.timestamp = datetime(2017, 12, 10, 9, 59, 50)
self.ab06.altitude = 300
self.ab06.software_version = 6.02
db.session.add(self.ab06)
db.session.commit()
create_device_stats(db.session, date=today)
devicestats = db.session.query(DeviceStats).all()
self.assertEqual(len(devicestats), 1)
self.assertEqual(devicestats[0].device, self.d01)
self.assertEqual(devicestats[0].max_altitude, 300)
self.assertEqual(devicestats[0].receiver_count, 2)
self.assertEqual(devicestats[0].aircraft_beacon_count, 5)
self.assertEqual(devicestats[0].date, datetime.strptime("2017-12-10", "%Y-%m-%d").date())
self.assertEqual(devicestats[0].firstseen, datetime(2017, 12, 10, 9, 59, 50))
self.assertEqual(devicestats[0].lastseen, datetime(2017, 12, 10, 10, 0, 5))
self.assertEqual(devicestats[0].aircraft_type, 3)
self.assertEqual(devicestats[0].stealth, True)
self.assertEqual(devicestats[0].software_version, 6.01)
self.assertEqual(devicestats[0].hardware_version, 15)
self.assertEqual(devicestats[0].real_address, "DDALFA")
if __name__ == "__main__":
unittest.main()