diff --git a/README.md b/README.md index 193ce9c..62770c3 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,19 @@ For best performance you should use [TimescaleDB](https://www.timescale.com), wh ``` raster2pgsql -s 4326 -c -C -I -M -t 100x100 elevation_data.tif public.elevation | psql -d ogn ``` - + +11. Import Airports (needed for takeoff and landing calculation). A cup file is provided under tests: + + ``` + flask database import_airports tests/SeeYou.cup + ``` + +12. Import DDB (needed for registration signs in the logbook). + + ``` + flask database import_ddb + ``` + There is also a [Vagrant](https://www.vagrantup.com/) environment for the development of ogn-python. You can create and start this virtual machine with `vagrant up` and login with `vagrant ssh`. The code of ogn-python will be available in the shared folder `/vagrant`. diff --git a/ogn_python/collect/celery.py b/ogn_python/collect/celery.py index 103443c..99509da 100644 --- a/ogn_python/collect/celery.py +++ b/ogn_python/collect/celery.py @@ -25,7 +25,8 @@ def update_takeoff_landings(last_minutes): end = datetime.datetime.utcnow() start = end - datetime.timedelta(minutes=last_minutes) - takeoff_update_entries(session=db.session, start=start, end=end, logger=logger) + result = takeoff_update_entries(session=db.session, start=start, end=end, logger=logger) + return result @celery.task(name='update_logbook_entries') @@ -33,28 +34,32 @@ def update_logbook_entries(): """Add/update logbook entries.""" today = datetime.datetime.today() - logbook_update_entries(session=db.session, date=today, logger=logger) + result = logbook_update_entries(session=db.session, date=today, logger=logger) + return result @celery.task(name='update_logbook_max_altitude') def update_logbook_max_altitude(): """Add max altitudes in logbook when flight is complete (takeoff and landing).""" - logbook_update_max_altitudes(session=db.session, logger=logger) + result = logbook_update_max_altitudes(session=db.session, logger=logger) + return result @celery.task(name='import_ddb') def import_ddb(): """Import registered devices from the DDB.""" - device_infos_import_ddb(session=db.session, logger=logger) + result = device_infos_import_ddb(session=db.session, logger=logger) + return result @celery.task(name='update_receivers_country_code') def update_receivers_country_code(): """Update country code in receivers table if None.""" - receivers_update_country_code(session=db.session, logger=logger) + result = receivers_update_country_code(session=db.session, logger=logger) + return result @celery.task(name='purge_old_data') diff --git a/ogn_python/collect/database.py b/ogn_python/collect/database.py index d1d17db..79dcc2f 100644 --- a/ogn_python/collect/database.py +++ b/ogn_python/collect/database.py @@ -23,7 +23,7 @@ def upsert(session, model, rows, update_cols): # print(compile_query(on_conflict_stmt)) session.execute(on_conflict_stmt) - + def update_device_infos(session, address_origin, path=None): if address_origin == DeviceInfoOrigin.flarmnet: @@ -53,9 +53,10 @@ def import_ddb(session, logger=None): logger.info("Import registered devices fom the DDB...") counter = update_device_infos(session, DeviceInfoOrigin.ogn_ddb) - logger.info("Imported {} devices.".format(counter)) - return "Imported {} devices.".format(counter) + finish_message = "DeviceInfo: {} inserted.".format(counter) + logger.info(finish_message) + return finish_message def update_country_code(session, logger=None): @@ -70,6 +71,7 @@ def update_country_code(session, logger=None): synchronize_session='fetch') session.commit() - logger.info("Updated {} AircraftBeacons".format(update_receivers)) - return "Updated country for {} Receivers".format(update_receivers) + finish_message = "Receivers (country): {} updated".format(update_receivers) + logger.info(finish_message) + return finish_message diff --git a/ogn_python/collect/logbook.py b/ogn_python/collect/logbook.py index 65eb265..ed22bcd 100644 --- a/ogn_python/collect/logbook.py +++ b/ogn_python/collect/logbook.py @@ -137,9 +137,10 @@ def update_entries(session, date, logger=None): result = session.execute(ins) insert_counter = result.rowcount session.commit() - logger.debug("New logbook entries: {}".format(insert_counter)) - return "Logbook entries: {} inserted, {} updated".format(insert_counter, update_counter) + finish_message = "Logbook: {} inserted, {} updated".format(insert_counter, update_counter) + logger.debug(finish_message) + return finish_message def update_max_altitudes(session, logger=None): @@ -173,6 +174,7 @@ def update_max_altitudes(session, logger=None): synchronize_session='fetch') session.commit() - logger.info("Logbook: {} entries updated.".format(update_logbook)) - return "Logbook: {} entries updated.".format(update_logbook) + finish_message = "Logbook (altitude): {} entries updated.".format(update_logbook) + logger.info(finish_message) + return finish_message diff --git a/ogn_python/collect/ognrange.py b/ogn_python/collect/ognrange.py index 2cf9559..2002f26 100644 --- a/ogn_python/collect/ognrange.py +++ b/ogn_python/collect/ognrange.py @@ -80,6 +80,7 @@ def create_receiver_coverage(session, date, logger=None): result = session.execute(ins) insert_counter = result.rowcount session.commit() - logger.debug("New receiver coverage entries: {}".format(insert_counter)) - return "Receiver coverage entries: {} inserted, {} updated".format(insert_counter, update_counter) + finish_message = "ReceiverCoverage: {} inserted, {} updated".format(insert_counter, update_counter) + logger.debug(finish_message) + return finish_message diff --git a/ogn_python/collect/takeoff_landings.py b/ogn_python/collect/takeoff_landings.py index e5c0d38..95cd90d 100644 --- a/ogn_python/collect/takeoff_landings.py +++ b/ogn_python/collect/takeoff_landings.py @@ -134,6 +134,7 @@ def update_entries(session, start, end, logger=None): result = session.execute(ins) session.commit() insert_counter = result.rowcount - logger.info("Inserted {} TakeoffLandings".format(insert_counter)) - return "Inserted {} TakeoffLandings".format(insert_counter) + finish_message = "TakeoffLandings: Inserted {}".format(insert_counter) + logger.info(finish_message) + return finish_message diff --git a/ogn_python/model/device.py b/ogn_python/model/device.py index 4b04e37..e6e7f63 100644 --- a/ogn_python/model/device.py +++ b/ogn_python/model/device.py @@ -1,3 +1,5 @@ +import datetime + from sqlalchemy.ext.hybrid import hybrid_property from ogn_python import db @@ -36,3 +38,29 @@ class Device(db.Model): .order_by(DeviceInfo.address_origin) return query.first() + + EXPIRY_DATES = { + 6.67: datetime.date(2020, 10, 31), + 6.63: datetime.date(2020, 5, 31), + 6.62: datetime.date(2020, 5, 31), + 6.6: datetime.date(2020, 1, 31), + 6.42: datetime.date(2019, 10, 31), + 6.41: datetime.date(2019, 1, 31), + 6.4: datetime.date(2019, 1, 31), + 6.09: datetime.date(2018, 9, 30), + 6.08: datetime.date(2018, 9, 30), + 6.07: datetime.date(2018, 3, 31), + 6.06: datetime.date(2017, 9, 30), + 6.05: datetime.date(2017, 3, 31), + } + + def expiry_date(self): + if self.name.startswith('FLR'): + if self.software_version in self.EXPIRY_DATES: + return self.EXPIRY_DATES[self.software_version] + else: + return datetime.date(2000, 1, 1) + else: + return None + + diff --git a/ogn_python/routes.py b/ogn_python/routes.py index f4fd8a4..60b920d 100644 --- a/ogn_python/routes.py +++ b/ogn_python/routes.py @@ -1,3 +1,5 @@ +import datetime + from flask import request, render_template from sqlalchemy import func, and_, or_ @@ -87,7 +89,7 @@ def airports(): .order_by(Country.iso2) if sel_country: - airports = db.session.query(Airport) \ + airports = db.session.query(Airport, Receiver).outerjoin(Receiver) \ .filter(and_(or_(Logbook.takeoff_airport_id == Airport.id, Logbook.landing_airport_id == Airport.id), Airport.country_code == sel_country)) \ .group_by(Airport.id) \ .order_by(Airport.name) @@ -197,10 +199,16 @@ def logbook(): @app.route('/statistics.html') def statistics(): - receiverstats = db.session.query(ReceiverStats) \ - .limit(10) - return render_template('statistics.html', receiverstats=receiverstats) + 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) # Backend routes for other sites diff --git a/ogn_python/templates/airport_detail.html b/ogn_python/templates/airport_detail.html index 5ccf638..3f299bc 100644 --- a/ogn_python/templates/airport_detail.html +++ b/ogn_python/templates/airport_detail.html @@ -35,7 +35,7 @@ {{ device.address }} {% if device.info is none %}-{% else %}{{ device.info.registration }}{% endif %} {% if device.takeoff_landings %}{% set last_action = device.takeoff_landings|last %}{% if last_action.is_takeoff == True %}↗{% else %}↘{% endif %} @ {{ last_action.timestamp.strftime('%Y-%m-%d %H:%M:%S') }}{% endif %} - {{ device.software_version }} + {% if device.software_version is not none %}{{ device.software_version }}{% else %}-{% endif %} {% endfor %} diff --git a/ogn_python/templates/logbook.html b/ogn_python/templates/logbook.html index c844e49..9d69019 100644 --- a/ogn_python/templates/logbook.html +++ b/ogn_python/templates/logbook.html @@ -55,8 +55,8 @@ {% if entry.duration is not none %}{{ entry.duration }}{% endif %} {% if entry.max_altitude is not none %}{{ '%0.1f'|format(entry.max_altitude - entry.takeoff_airport.altitude) }} m{% endif %} - {% if entry.takeoff_airport is not none and entry.takeoff_airport.id|string() != sel_airport %}Take Off: {{ entry.takeoff_airport.name }} - {% elif entry.landing_airport is not none and entry.landing_airport.id|string() != sel_airport %}Landing: {{ entry.landing_airport.name }} + {% if entry.takeoff_airport is not none and entry.takeoff_airport.id|string() != sel_airport %}Take Off: {{ entry.takeoff_airport.country_code }} {{ entry.takeoff_airport.name }} + {% elif entry.landing_airport is not none and entry.landing_airport.id|string() != sel_airport %}Landing: {{ entry.landing_airport.country_code }} {{ entry.landing_airport.name }} {% endif %} diff --git a/ogn_python/templates/receiver_detail.html b/ogn_python/templates/receiver_detail.html index 69e4c5f..b2e73e6 100644 --- a/ogn_python/templates/receiver_detail.html +++ b/ogn_python/templates/receiver_detail.html @@ -13,7 +13,7 @@ Name:{{ receiver.country.iso2 }} {{ receiver.name }} Airport: {% if airport is not none %}{{ airport.country_code }} - {% if airport.takeoff_landings %}{{ airport.name }}{% else %}{{ airport.name }}{% endif %} + {% if airport.takeoff_landings %}{{ airport.name }}{% else %}{{ airport.name }}{% endif %} {% else %}-{% endif %} diff --git a/ogn_python/templates/statistics.html b/ogn_python/templates/statistics.html index 1e5b5dc..0936058 100644 --- a/ogn_python/templates/statistics.html +++ b/ogn_python/templates/statistics.html @@ -11,15 +11,13 @@ - {% for receiverstat in receiverstats %} - - + diff --git a/tests/model/test_device.py b/tests/model/test_device.py new file mode 100644 index 0000000..e6ec6f7 --- /dev/null +++ b/tests/model/test_device.py @@ -0,0 +1,29 @@ +import datetime + +import unittest + +from tests.base import TestBaseDB, db +from ogn_python.model import Device, DeviceInfo + + +class TestStringMethods(TestBaseDB): + def test_device_info(self): + device = Device(name='FLRDD0815', address='DD0815') + device_info1 = DeviceInfo(address='DD0815', address_origin=1, registration='D-0815') + device_info2 = DeviceInfo(address='DD0815', address_origin=2, registration='15') + + db.session.add(device) + db.session.add(device_info1) + db.session.add(device_info2) + db.session.commit() + + self.assertEqual(device.info, device_info1) + + def test_expiry_date(self): + device = Device(name='FLRDD0815', address='DD0815', software_version=6.42) + + self.assertEqual(device.expiry_date(), datetime.date(2019, 10, 31)) + + +if __name__ == '__main__': + unittest.main()
ReceiverCountry Aircrafts Beacons
{{ receiverstat.receiver.name }}{{ receiverstat.receiver.country.iso2 }}{{ receiverstat.receiver.country.iso2 }} {{ receiverstat.receiver.name }} {{ receiverstat.aircraft_count }} {{ receiverstat.beacon_count }}