Airport: |
{% if receiver.airport is not none %}{{ receiver.airport|to_html_flag|safe }}
{{ receiver.airport.name }}
diff --git a/app/templates/receiver_ranking.html b/app/templates/receiver_ranking.html
index 706b55e..1c38900 100644
--- a/app/templates/receiver_ranking.html
+++ b/app/templates/receiver_ranking.html
@@ -2,8 +2,6 @@
{% block content %}
-
-
Receiver Ranking
@@ -28,7 +26,6 @@
Name |
Airport |
Distance [km] |
- Normalized signal quality [dB] |
Senders |
Coverages |
Messages |
@@ -41,10 +38,9 @@
{{ today }} |
{% if yesterday is none %}(new){% elif yesterday - today > 0 %}{{ yesterday - today }}{% elif yesterday - today < 0 %}{{ today - yesterday }}{% endif %} |
{% if current is not none %}{{ current }}{% else %}-{% endif %} |
- {{ receiver.country|to_html_flag|safe }} {{ receiver|to_html_link|safe }} |
+ {{ receiver|to_html_flag|safe }}{{ receiver|to_html_link|safe }} |
{{ receiver.airport|to_html_link|safe }} |
{% if ranking is not none %}{{ '%0.1f' | format(ranking.max_distance/1000.0) }}{% else %}-{% endif %} |
- {% if ranking is not none %}{{ '%0.1f' | format(ranking.max_normalized_quality) }}{% else %}-{% endif %} |
{% if ranking is not none %}{{ ranking.senders_count }}{% else %}-{% endif %} |
{% if ranking is not none %}{{ ranking.coverages_count }}{% else %}-{% endif %} |
{% if ranking is not none %}{{ ranking.messages_count }}{% else %}-{% endif %} |
@@ -61,7 +57,12 @@
{{ super() }}
{% endblock %}
diff --git a/app/templates/receivers.html b/app/templates/receivers.html
index 119e66a..0e0cfc1 100644
--- a/app/templates/receivers.html
+++ b/app/templates/receivers.html
@@ -2,8 +2,6 @@
{% block content %}
-
-
Receivers
@@ -38,7 +36,7 @@
{% for receiver in receivers %}
{{ loop.index }} |
- {{ receiver.country|to_html_flag|safe }} |
+ {{ receiver|to_html_flag|safe }} |
{{ receiver|to_html_link|safe }} |
{{ receiver.airport|to_html_link|safe }} |
{{ receiver.altitude|int }} m |
diff --git a/app/templates/sender_detail.html b/app/templates/sender_detail.html
index b0c8352..da621f7 100644
--- a/app/templates/sender_detail.html
+++ b/app/templates/sender_detail.html
@@ -32,7 +32,7 @@
{% for info in sender.infos %}
{{ info.aircraft }} |
- {{ info.registration }} |
+ {{ info|to_html_flag|safe }}{{ info.registration }} |
{{ info.competition }} |
{{ info.aircraft_type.name }} |
{{ info.address_origin.name }} |
diff --git a/app/templates/sender_ranking.html b/app/templates/sender_ranking.html
index 093f35f..262ffad 100644
--- a/app/templates/sender_ranking.html
+++ b/app/templates/sender_ranking.html
@@ -1,6 +1,7 @@
{% extends "base.html" %}
{% block content %}
+
Sender Ranking
@@ -12,7 +13,6 @@
Name |
Aircraft |
Maximum distance [km] |
- Maximal normalized signal quality [dB] |
Receiver counter |
Coverage counter |
Message counter |
@@ -23,10 +23,9 @@
{% for entry in ranking %}
{{ loop.index }} |
- {{ entry.sender|to_html_link|safe }} |
+ {{ entry.sender|to_html_flag|safe }}{{ entry.sender|to_html_link|safe }} |
{% if entry.sender.infos|length > 0 %}{{ entry.sender.infos[0].aircraft }}{% else %}-{% endif %} |
{{ '%0.1f' | format(entry.max_distance/1000.0) }} |
- {{ '%0.1f' | format(entry.max_normalized_quality) }} |
{{ entry.receivers_count }} |
{{ entry.coverages_count }} |
{{ entry.messages_count }} |
@@ -44,7 +43,12 @@
{{ super() }}
{% endblock %}
diff --git a/app/utils.py b/app/utils.py
index 51f0054..968a054 100644
--- a/app/utils.py
+++ b/app/utils.py
@@ -1,21 +1,14 @@
-import csv
import gzip
-from io import StringIO
from datetime import datetime, timedelta
from flask import current_app
from aerofiles.seeyou import Reader
from ogn.parser.utils import FEETS_TO_METER
-import requests
from .model import AircraftType, SenderInfoOrigin, SenderInfo, Airport, Location
-DDB_URL = "http://ddb.glidernet.org/download/?t=1"
-FLARMNET_URL = "http://www.flarmnet.org/files/data.fln"
-
-
address_prefixes = {"F": "FLR", "O": "OGN", "I": "ICA"}
nm2m = 1852
@@ -33,60 +26,11 @@ def date_to_timestamps(date):
return (start, end)
-def get_ddb(csv_file=None, address_origin=SenderInfoOrigin.UNKNOWN):
- if csv_file is None:
- r = requests.get(DDB_URL)
- rows = "\n".join(i for i in r.text.splitlines() if i[0] != "#")
- else:
- r = open(csv_file, "r")
- rows = "".join(i for i in r.readlines() if i[0] != "#")
-
- data = csv.reader(StringIO(rows), quotechar="'", quoting=csv.QUOTE_ALL)
-
- sender_infos = list()
- for row in data:
- sender_info = SenderInfo()
- sender_info.address_type = row[0]
- sender_info.address = row[1]
- sender_info.aircraft = row[2]
- sender_info.registration = row[3]
- sender_info.competition = row[4]
- sender_info.tracked = row[5] == "Y"
- sender_info.identified = row[6] == "Y"
- sender_info.aircraft_type = AircraftType(int(row[7]))
- sender_info.address_origin = address_origin
-
- sender_infos.append(sender_info)
-
- return sender_infos
-
-
-def get_flarmnet(fln_file=None, address_origin=SenderInfoOrigin.FLARMNET):
- if fln_file is None:
- r = requests.get(FLARMNET_URL)
- rows = [bytes.fromhex(line).decode("latin1") for line in r.text.split("\n") if len(line) == 173]
- else:
- with open(fln_file, "r") as file:
- rows = [bytes.fromhex(line.strip()).decode("latin1") for line in file.readlines() if len(line) == 173]
-
- sender_infos = list()
- for row in rows:
- sender_info = SenderInfo()
- sender_info.address = row[0:6].strip()
- sender_info.aircraft = row[48:69].strip()
- sender_info.registration = row[69:76].strip()
- sender_info.competition = row[76:79].strip()
-
- sender_infos.append(sender_info)
-
- return sender_infos
-
-
-def get_trackable(ddb):
+def get_trackable(sender_info_dicts):
result = []
- for i in ddb:
- if i.tracked and i.address_type in address_prefixes:
- result.append("{}{}".format(address_prefixes[i.address_type], i.address))
+ for sender_info_dict in sender_info_dicts:
+ if sender_info_dict['tracked'] and sender_info_dict['address_type'] in address_prefixes:
+ result.append("{}{}".format(address_prefixes[sender_info_dict['address_type']], sender_info_dict['address']))
return result
diff --git a/migrations/versions/2ab0bbb8b49d_added_constraint_to_senderinfo.py b/migrations/versions/2ab0bbb8b49d_added_constraint_to_senderinfo.py
new file mode 100644
index 0000000..81af737
--- /dev/null
+++ b/migrations/versions/2ab0bbb8b49d_added_constraint_to_senderinfo.py
@@ -0,0 +1,30 @@
+"""Added Constraint to SenderInfo
+
+Revision ID: 2ab0bbb8b49d
+Revises: a72b2205b55c
+Create Date: 2020-12-11 23:27:16.497547
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '2ab0bbb8b49d'
+down_revision = 'a72b2205b55c'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.add_column('sender_infos', sa.Column('address_type', sa.VARCHAR(), nullable=True))
+ op.create_index('idx_sender_infos_address_address_origin_uc', 'sender_infos', ['address', 'address_origin'], unique=True)
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.drop_index('idx_sender_infos_address_address_origin_uc', table_name='sender_infos')
+ op.drop_column('sender_infos', 'address_type')
+ # ### end Alembic commands ###
diff --git a/migrations/versions/a72b2205b55c_added_country_relation_to_senderinfo.py b/migrations/versions/a72b2205b55c_added_country_relation_to_senderinfo.py
new file mode 100644
index 0000000..33fec3a
--- /dev/null
+++ b/migrations/versions/a72b2205b55c_added_country_relation_to_senderinfo.py
@@ -0,0 +1,32 @@
+"""Added country relation to SenderInfo
+
+Revision ID: a72b2205b55c
+Revises: f3afd6197391
+Create Date: 2020-12-08 18:03:10.131819
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = 'a72b2205b55c'
+down_revision = 'f3afd6197391'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.add_column('sender_infos', sa.Column('country_id', sa.Integer(), nullable=True))
+ op.create_index(op.f('ix_sender_infos_country_id'), 'sender_infos', ['country_id'], unique=False)
+ op.create_foreign_key(None, 'sender_infos', 'countries', ['country_id'], ['gid'])
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.drop_constraint(None, 'sender_infos', type_='foreignkey')
+ op.drop_index(op.f('ix_sender_infos_country_id'), table_name='sender_infos')
+ op.drop_column('sender_infos', 'country_id')
+ # ### end Alembic commands ###
diff --git a/setup.py b/setup.py
index 0ae6fb6..2513252 100644
--- a/setup.py
+++ b/setup.py
@@ -58,7 +58,8 @@ setup(
'requests==2.25.0',
'matplotlib==3.3.3',
'bokeh==2.2.3',
- 'pandas==1.1.5'
+ 'pandas==1.1.5',
+ 'flydenity==0.1.5'
],
test_require=[
'pytest==5.0.1',
diff --git a/tests/base.py b/tests/base.py
index 205273b..2ab7098 100644
--- a/tests/base.py
+++ b/tests/base.py
@@ -33,6 +33,11 @@ class TestBaseDB(unittest.TestCase):
db.session.execute("SELECT create_hypertable('receiver_statuses', 'reference_timestamp', chunk_time_interval => interval '1 day', if_not_exists => TRUE);")
db.session.commit()
+ # ... and insert some countries
+ db.session.execute("INSERT INTO countries(name, iso2) VALUES ('Germany', 'DE');")
+ db.session.execute("INSERT INTO countries(name, iso2) VALUES ('Austria', 'AT');")
+ db.session.execute("INSERT INTO countries(name, iso2) VALUES ('United Kingdom', 'GB');")
+
def tearDown(self):
db.session.remove()
diff --git a/tests/commands/test_database.py b/tests/commands/test_database.py
index 43e39a4..ed03dba 100644
--- a/tests/commands/test_database.py
+++ b/tests/commands/test_database.py
@@ -3,15 +3,16 @@ import os
from flask import current_app
from app.model import SenderInfo
-from app.commands.database import import_file
+from app.commands.database import import_ddb
from tests.base import TestBaseDB, db
class TestDatabase(TestBaseDB):
- def test_import_ddb_file(self):
+ def test_import_ddb(self):
runner = current_app.test_cli_runner()
- result = runner.invoke(import_file, [os.path.dirname(__file__) + "/../custom_ddb.txt"])
+ ddb_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../custom_ddb.txt"))
+ result = runner.invoke(import_ddb, ['--path', ddb_path])
self.assertEqual(result.exit_code, 0)
sender_infos = db.session.query(SenderInfo).all()
diff --git a/tests/test_utils.py b/tests/test_utils.py
index a460d35..975a05d 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -3,7 +3,8 @@ import unittest
from datetime import date
from app.model import AircraftType
-from app.utils import get_days, get_ddb, get_trackable, get_airports
+from app.utils import get_days, get_trackable, get_airports
+from app.commands.database import read_ddb
class TestStringMethods(unittest.TestCase):
@@ -14,25 +15,25 @@ class TestStringMethods(unittest.TestCase):
self.assertEqual(days, [date(2018, 2, 27), date(2018, 2, 28), date(2018, 3, 1), date(2018, 3, 2)])
def test_get_devices(self):
- devices = get_ddb()
- self.assertGreater(len(devices), 1000)
+ sender_infos = read_ddb()
+ self.assertGreater(len(sender_infos), 1000)
def test_get_ddb_from_file(self):
- devices = get_ddb(os.path.dirname(__file__) + "/custom_ddb.txt")
- self.assertEqual(len(devices), 6)
- device = devices[0]
+ sender_infos = read_ddb(os.path.dirname(__file__) + "/custom_ddb.txt")
+ self.assertEqual(len(sender_infos), 6)
+ sender_info = sender_infos[0]
- self.assertEqual(device.address, "DD4711")
- self.assertEqual(device.aircraft, "HK36 TTC")
- self.assertEqual(device.registration, "D-EULE")
- 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(sender_info['address'], "DD4711")
+ self.assertEqual(sender_info['aircraft'], "HK36 TTC")
+ self.assertEqual(sender_info['registration'], "D-EULE")
+ self.assertEqual(sender_info['competition'], "CU")
+ self.assertTrue(sender_info['tracked'])
+ self.assertTrue(sender_info['identified'])
+ self.assertEqual(sender_info['aircraft_type'], AircraftType.GLIDER_OR_MOTOR_GLIDER)
def test_get_trackable(self):
- devices = get_ddb(os.path.dirname(__file__) + "/custom_ddb.txt")
- trackable = get_trackable(devices)
+ sender_infos = read_ddb(os.path.dirname(__file__) + "/custom_ddb.txt")
+ trackable = get_trackable(sender_infos)
self.assertEqual(len(trackable), 4)
self.assertIn("FLRDD4711", trackable)
self.assertIn("FLRDD0815", trackable)
|