diff --git a/alembic/versions/4ebfb325db6_added_deviceinfo.py b/alembic/versions/4ebfb325db6_added_deviceinfo.py new file mode 100644 index 0000000..23c7552 --- /dev/null +++ b/alembic/versions/4ebfb325db6_added_deviceinfo.py @@ -0,0 +1,62 @@ +"""Added DeviceInfo + +Revision ID: 4ebfb325db6 +Revises: 163f6213d3f +Create Date: 2016-06-04 11:11:00.546524 + +""" + +# revision identifiers, used by Alembic. +revision = '4ebfb325db6' +down_revision = '163f6213d3f' +branch_labels = None +depends_on = None + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.execute("CREATE TABLE device_info AS SELECT * FROM device;") + op.create_index('ix_device_info_address', 'device_info', ['address']) + op.drop_column('device_info', 'name') + op.drop_column('device_info', 'airport') + op.drop_column('device_info', 'frequency') + + op.drop_column('device', 'address_origin') + op.drop_column('device', 'name') + op.drop_column('device', 'airport') + op.drop_column('device', 'aircraft') + op.drop_column('device', 'registration') + op.drop_column('device', 'competition') + op.drop_column('device', 'frequency') + op.drop_column('device', 'tracked') + op.drop_column('device', 'identified') + + op.add_column('device', sa.Column('stealth', sa.Boolean)) + op.add_column('device', sa.Column('software_version', sa.Float)) + op.add_column('device', sa.Column('hardware_version', sa.SmallInteger)) + op.add_column('device', sa.Column('real_address', sa.String(6))) + + +def downgrade(): + op.add_column('device', sa.Column('address_origin', sa.SmallInteger)) + op.add_column('device', sa.Column('name', sa.Unicode)) + op.add_column('device', sa.Column('airport', sa.String)) + op.add_column('device', sa.Column('aircraft', sa.String)) + op.add_column('device', sa.Column('registration', sa.String(7))) + op.add_column('device', sa.Column('competition', sa.String(3))) + op.add_column('device', sa.Column('frequency', sa.String)) + op.add_column('device', sa.Column('tracked', sa.Boolean)) + op.add_column('device', sa.Column('identified', sa.Boolean)) + + op.create_index('ix_device_info_registration', 'device', ['registration']) + + op.drop_column('device', 'stealth') + op.drop_column('device', 'software_version') + op.drop_column('device', 'hardware_version') + op.drop_column('device', 'real_address') + + # transfer from device_info to device costs too much... + op.execute("DROP TABLE device_info;") + pass diff --git a/ogn/collect/database.py b/ogn/collect/database.py index a956bcc..40b7b47 100644 --- a/ogn/collect/database.py +++ b/ogn/collect/database.py @@ -1,8 +1,6 @@ -from sqlalchemy.sql import null - from celery.utils.log import get_task_logger -from ogn.model import Device, AddressOrigin +from ogn.model import DeviceInfo, AddressOrigin from ogn.utils import get_ddb from ogn.collect.celery import app @@ -10,45 +8,16 @@ from ogn.collect.celery import app logger = get_task_logger(__name__) -temp_address_origin = 7 - -def add_devices(session, origin): - before_sq = session.query(Device.address) \ - .filter(Device.address_origin == origin) \ - .subquery() - add_query = session.query(Device) \ - .filter(Device.address_origin == temp_address_origin) \ - .filter(~Device.address.in_(before_sq)) - - result = add_query.update({Device.address_origin: origin}, - synchronize_session='fetch') - - return result - - -def update_devices(session, origin, devices): - session.query(Device) \ - .filter(Device.address_origin == temp_address_origin) \ - .delete() - - session.bulk_save_objects(devices) - - # mark temporary added devices - session.query(Device) \ - .filter(Device.address_origin == null()) \ - .update({Device.address_origin: temp_address_origin}) - - logger.info('Added {} devices'.format(add_devices(session, origin))) - - # delete temporary added devices - session.query(Device) \ - .filter(Device.address_origin == temp_address_origin) \ +def update_device_infos(session, address_origin, device_infos): + session.query(DeviceInfo) \ + .filter(DeviceInfo.address_origin == address_origin) \ .delete() + session.bulk_save_objects(device_infos) session.commit() - return len(devices) + return len(device_infos) @app.task @@ -56,7 +25,8 @@ def import_ddb(): """Import registered devices from the DDB.""" logger.info("Import registered devices fom the DDB...") - counter = update_devices(app.session, AddressOrigin.ogn_ddb, get_ddb()) + counter = update_device_infos(app.session, AddressOrigin.ogn_ddb, + get_ddb()) logger.info("Imported {} devices.".format(counter)) @@ -65,6 +35,6 @@ def import_file(path='tests/custom_ddb.txt'): """Import registered devices from a local file.""" logger.info("Import registered devices from '{}'...".format(path)) - counter = update_devices(app.session, AddressOrigin.user_defined, - get_ddb(path)) + counter = update_device_infos(app.session, AddressOrigin.user_defined, + get_ddb(path)) logger.info("Imported {} devices.".format(counter)) diff --git a/ogn/collect/logbook.py b/ogn/collect/logbook.py index 2593e2e..cb0b9bf 100644 --- a/ogn/collect/logbook.py +++ b/ogn/collect/logbook.py @@ -26,25 +26,23 @@ def compute_takeoff_and_landing(): airport_radius = 0.025 # takeoff / landing must not exceed this radius (degree!) around the airport airport_delta = 100 # takeoff / landing must not exceed this altitude offset above/below the airport - # calculate the start (and stop) timestamp for the computatio - last_takeoff_landing_query = app.session.query(func.max(TakeoffLanding.timestamp)) - begin_computation = last_takeoff_landing_query.one()[0] - if begin_computation is None: - # if the table is empty - last_takeoff_landing_query = app.session.query(func.min(AircraftBeacon.timestamp)) - begin_computation = last_takeoff_landing_query.one()[0] - if begin_computation is None: - return 0 - else: - # we get the beacons async. to be safe we delete takeoffs/landings from last 24 hours and recalculate from then - begin_computation = begin_computation - timedelta(hours=24) - app.session.query(TakeoffLanding) \ - .filter(TakeoffLanding.timestamp >= begin_computation) \ - .delete() - end_computation = begin_computation + timedelta(days=5) + # max AircraftBeacon id offset computed per function call + max_id_offset = 500000 - logger.debug("Calculate takeoffs and landings between {} and {}" - .format(begin_computation, end_computation)) + # get the last AircraftBeacon used for TakeoffLanding and start from there + last_takeoff_landing_query = app.session.query(func.max(TakeoffLanding.id).label('max_id')) \ + .subquery() + + last_used_aircraft_beacon_query = app.session.query(AircraftBeacon.id) \ + .filter(TakeoffLanding.id == last_takeoff_landing_query.c.max_id) \ + .filter(and_(AircraftBeacon.timestamp == TakeoffLanding.timestamp, + AircraftBeacon.device_id == TakeoffLanding.device_id)) + + last_used_aircraft_beacon_id = last_used_aircraft_beacon_query.first() + if last_used_aircraft_beacon_id is None: + aircraft_beacon_id_start = 0 + else: + aircraft_beacon_id_start = last_used_aircraft_beacon_id[0] + 1 # make a query with current, previous and next position sq = app.session.query( @@ -66,8 +64,7 @@ def compute_takeoff_and_landing(): AircraftBeacon.device_id, func.lag(AircraftBeacon.device_id).over(order_by=and_(AircraftBeacon.device_id, AircraftBeacon.timestamp)).label('device_id_prev'), func.lead(AircraftBeacon.device_id).over(order_by=and_(AircraftBeacon.device_id, AircraftBeacon.timestamp)).label('device_id_next')) \ - .filter(AircraftBeacon.timestamp >= begin_computation) \ - .filter(AircraftBeacon.timestamp <= end_computation) \ + .filter(between(AircraftBeacon.id, aircraft_beacon_id_start, aircraft_beacon_id_start + max_id_offset)) \ .subquery() # find possible takeoffs and landings @@ -115,6 +112,6 @@ def compute_takeoff_and_landing(): result = app.session.execute(ins) counter = result.rowcount app.session.commit() - logger.debug("New/recalculated takeoffs and landings: {}".format(counter)) + logger.debug("New takeoffs and landings: {}".format(counter)) return counter diff --git a/ogn/commands/__init__.py b/ogn/commands/__init__.py index 17c89ac..b1860db 100644 --- a/ogn/commands/__init__.py +++ b/ogn/commands/__init__.py @@ -2,6 +2,7 @@ from .database import manager as database_manager from .showairport import manager as show_airport_manager from .showreceiver import manager as show_receiver_manager from .showdevices import manager as show_devices_manager +from .showdeviceinfos import manager as show_deviceinfos_manager from .logbook import manager as logbook_manager from manager import Manager @@ -12,4 +13,5 @@ manager.merge(database_manager, namespace='db') manager.merge(show_airport_manager, namespace='show.airport') manager.merge(show_receiver_manager, namespace='show.receiver') manager.merge(show_devices_manager, namespace='show.devices') +manager.merge(show_deviceinfos_manager, namespace='show.deviceinfos') manager.merge(logbook_manager, namespace='logbook') diff --git a/ogn/commands/database.py b/ogn/commands/database.py index fcb55b0..aa66cd6 100644 --- a/ogn/commands/database.py +++ b/ogn/commands/database.py @@ -1,7 +1,7 @@ from ogn.commands.dbutils import engine, session from ogn.model import Base, AddressOrigin from ogn.utils import get_ddb, get_airports -from ogn.collect.database import update_devices +from ogn.collect.database import update_device_infos from manager import Manager manager = Manager() @@ -50,7 +50,9 @@ def import_ddb(): """Import registered devices from the DDB.""" print("Import registered devices fom the DDB...") - counter = update_devices(session, AddressOrigin.ogn_ddb, get_ddb()) + address_origin = AddressOrigin.ogn_ddb + counter = update_device_infos(session, address_origin, + get_ddb(address_origin=address_origin)) print("Imported %i devices." % counter) @@ -60,8 +62,9 @@ def import_file(path='tests/custom_ddb.txt'): # (flushes previously manually imported entries) print("Import registered devices from '{}'...".format(path)) - counter = update_devices(session, AddressOrigin.user_defined, - get_ddb(path)) + address_origin = AddressOrigin.user_defined + counter = update_device_infos(session, address_origin, + get_ddb(csvfile=path, address_origin=address_origin)) print("Imported %i devices." % counter) diff --git a/ogn/commands/logbook.py b/ogn/commands/logbook.py index 36e2022..4daa597 100644 --- a/ogn/commands/logbook.py +++ b/ogn/commands/logbook.py @@ -7,7 +7,7 @@ from sqlalchemy import and_, or_ from sqlalchemy.sql.expression import true, false, label from sqlalchemy.orm import aliased -from ogn.model import Device, TakeoffLanding, Airport +from ogn.model import Device, DeviceInfo, TakeoffLanding, Airport from ogn.commands.dbutils import session from ogn.collect.logbook import compute_takeoff_and_landing @@ -25,7 +25,7 @@ def compute(): print("New/recalculated takeoffs/landings: {}".format(counter)) -@manager.arg('date', help='date (format: yyyy-mm-dd') +@manager.arg('date', help='date (format: yyyy-mm-dd)') @manager.arg('utc_delta_hours', help='delta hours to utc (for local time logs)') @manager.command def show(airport_name, utc_delta_hours=0, date=None): @@ -170,6 +170,14 @@ def show(airport_name, utc_delta_hours=0, date=None): .subquery() # get aircraft and airport informations and sort all entries by the reference time + sq2 = session.query(DeviceInfo.address, func.max(DeviceInfo.address_origin).label('address_origin')) \ + .group_by(DeviceInfo.address) \ + .subquery() + + sq3 = session.query(DeviceInfo.address, DeviceInfo.registration, DeviceInfo.aircraft) \ + .filter(and_(DeviceInfo.address == sq2.c.address, DeviceInfo.address_origin == sq2.c.address_origin)) \ + .subquery() + takeoff_airport = aliased(Airport, name='takeoff_airport') landing_airport = aliased(Airport, name='landing_airport') logbook_query = session.query(union_query.c.reftime, @@ -180,12 +188,16 @@ def show(airport_name, utc_delta_hours=0, date=None): union_query.c.landing_track, landing_airport, union_query.c.duration, - Device) \ - .outerjoin(Device, union_query.c.device_id == Device.id) \ + Device, + sq3.c.registration, + sq3.c.aircraft) \ .outerjoin(takeoff_airport, union_query.c.takeoff_airport_id == takeoff_airport.id) \ .outerjoin(landing_airport, union_query.c.landing_airport_id == landing_airport.id) \ + .outerjoin(Device, union_query.c.device_id == Device.id) \ + .outerjoin(sq3, sq3.c.address == Device.address) \ .order_by(union_query.c.reftime) + # ... and finally print out the logbook print('--- Logbook ({}) ---'.format(airport_name)) def none_datetime_replacer(datetime_object): @@ -197,11 +209,11 @@ def show(airport_name, utc_delta_hours=0, date=None): def none_timedelta_replacer(timedelta_object): return '--:--:--' if timedelta_object is None else timedelta_object - def none_registration_replacer(device_object): - return '[' + device_object.address + ']' if device_object.registration is None else device_object.registration + def none_registration_replacer(device_object, registration_object): + return '[' + device_object.address + ']' if registration_object is None else registration_object - def none_aircraft_replacer(device_object): - return '(unknown)' if device_object.aircraft is None else device_object.aircraft + def none_aircraft_replacer(device_object, aircraft_object): + return '(unknown)' if aircraft_object is None else aircraft_object def airport_marker(takeoff_airport_object, landing_airport_object): if takeoff_airport_object is not None and takeoff_airport_object.name is not airport.name: @@ -211,7 +223,7 @@ def show(airport_name, utc_delta_hours=0, date=None): else: return ('') - for [reftime, takeoff, takeoff_track, takeoff_airport, landing, landing_track, landing_airport, duration, device] in logbook_query.all(): + for [reftime, takeoff, takeoff_track, takeoff_airport, landing, landing_track, landing_airport, duration, device, registration, aircraft] in logbook_query.all(): print('%10s %8s (%2s) %8s (%2s) %8s %8s %17s %20s' % ( reftime.date(), none_datetime_replacer(takeoff), @@ -219,6 +231,6 @@ def show(airport_name, utc_delta_hours=0, date=None): none_datetime_replacer(landing), none_track_replacer(landing_track), none_timedelta_replacer(duration), - none_registration_replacer(device), - none_aircraft_replacer(device), + none_registration_replacer(device, registration), + none_aircraft_replacer(device, aircraft), airport_marker(takeoff_airport, landing_airport))) diff --git a/ogn/commands/showdeviceinfos.py b/ogn/commands/showdeviceinfos.py new file mode 100644 index 0000000..6d55ef7 --- /dev/null +++ b/ogn/commands/showdeviceinfos.py @@ -0,0 +1,62 @@ +from ogn.commands.dbutils import session +from ogn.model import AddressOrigin +from sqlalchemy import func, and_, true, false + +from manager import Manager +from ogn.model.device_info import DeviceInfo +manager = Manager() + + +def get_devices_stats(session): + sq_default = session.query(DeviceInfo.address) \ + .filter(and_(DeviceInfo.tracked == true(), DeviceInfo.identified == true())) \ + .subquery() + + sq_nt = session.query(DeviceInfo.address) \ + .filter(and_(DeviceInfo.tracked == false(), DeviceInfo.identified == true())) \ + .subquery() + + sq_ni = session.query(DeviceInfo.address) \ + .filter(and_(DeviceInfo.tracked == true(), DeviceInfo.identified == false())) \ + .subquery() + + sq_ntni = session.query(DeviceInfo.address) \ + .filter(and_(DeviceInfo.tracked == false(), DeviceInfo.identified == false())) \ + .subquery() + + query = session.query(DeviceInfo.address_origin, + func.count(DeviceInfo.id), + func.count(sq_default.c.address), + func.count(sq_nt.c.address), + func.count(sq_ni.c.address), + func.count(sq_ntni.c.address)) \ + .outerjoin(sq_default, sq_default.c.address == DeviceInfo.address) \ + .outerjoin(sq_nt, sq_nt.c.address == DeviceInfo.address) \ + .outerjoin(sq_ni, sq_ni.c.address == DeviceInfo.address) \ + .outerjoin(sq_ntni, sq_ntni.c.address == DeviceInfo.address) \ + .group_by(DeviceInfo.address_origin) + + stats = {} + for [address_origin, device_count, default_count, nt_count, ni_count, ntni_count] in query.all(): + origin = AddressOrigin(address_origin).name() + stats[origin] = {'device_count': device_count, + 'default_count': default_count, + 'nt_count': nt_count, + 'ni_count': ni_count, + 'ntni_count': ntni_count} + return stats + + +@manager.command +def stats(): + """Show some stats on registered devices.""" + print('--- Devices ---') + stats = get_devices_stats(session) + for origin in stats: + print('{:12s} Total:{:5d} - default:{:3d}, just not tracked:{:3d}, just not identified:{:3d}, not tracked & not identified: {:3d}' + .format(origin, + stats[origin]['device_count'], + stats[origin]['default_count'], + stats[origin]['nt_count'], + stats[origin]['ni_count'], + stats[origin]['ntni_count'])) diff --git a/ogn/commands/showdevices.py b/ogn/commands/showdevices.py index 50bf7a3..5bf02c1 100644 --- a/ogn/commands/showdevices.py +++ b/ogn/commands/showdevices.py @@ -1,53 +1,55 @@ from ogn.commands.dbutils import session -from ogn.model import AddressOrigin, Device -from sqlalchemy import func, and_, true, false +from ogn.model import Device, AircraftType +from sqlalchemy import func from manager import Manager manager = Manager() -def get_devices_stats(session): - sq_nt = session.query(Device.address) \ - .filter(and_(Device.tracked == false(), Device.identified == true())) \ - .subquery() - - sq_ni = session.query(Device.address) \ - .filter(and_(Device.tracked == true(), Device.identified == false())) \ - .subquery() - - sq_ntni = session.query(Device.address) \ - .filter(and_(Device.tracked == false(), Device.identified == false())) \ - .subquery() - - query = session.query(Device.address_origin, - func.count(Device.id), - func.count(sq_nt.c.address), - func.count(sq_ni.c.address), - func.count(sq_ntni.c.address)) \ - .outerjoin(sq_nt, sq_nt.c.address == Device.address) \ - .outerjoin(sq_ni, sq_ni.c.address == Device.address) \ - .outerjoin(sq_ntni, sq_ntni.c.address == Device.address) \ - .group_by(Device.address_origin) - - stats = {} - for [address_origin, device_count, nt_count, ni_count, ntni_count] in query.all(): - origin = AddressOrigin(address_origin).name() - stats[origin] = {'device_count': device_count, - 'nt_count': nt_count, - 'ni_count': ni_count, - 'ntni_count': ntni_count} - return stats +@manager.command +def aircraft_type_stats(): + """Show stats about aircraft types used by devices.""" + aircraft_type_query = session.query(Device.aircraft_type, + func.count(Device.id)) \ + .group_by(Device.aircraft_type) \ + .order_by(func.count(Device.id).desc()) + print("--- Aircraft types ---") + for [aircraft_type, count] in aircraft_type_query.all(): + at = AircraftType(aircraft_type) + print("{}: {}".format(at.name(), count)) @manager.command -def stats(): - """Show some stats on registered devices.""" - print('--- Devices ---') - stats = get_devices_stats(session) - for origin in stats: - print('{:12s} Total:{:5d} - not tracked:{:3d}, not identified:{:3d}, not tracked & not identified: {:3d}' - .format(origin, - stats[origin]['device_count'], - stats[origin]['nt_count'], - stats[origin]['ni_count'], - stats[origin]['ntni_count'])) +def stealth_stats(): + """Show stats about stealth flag set by devices.""" + stealth_query = session.query(Device.stealth, + func.count(Device.id)) \ + .group_by(Device.stealth) \ + .order_by(func.count(Device.id).desc()) + print("--- Stealth ---") + for [is_stealth, count] in stealth_query.all(): + print("{}: {}".format(is_stealth, count)) + + +@manager.command +def software_stats(): + """Show stats about software version used by devices.""" + software_query = session.query(Device.software_version, + func.count(Device.id)) \ + .group_by(Device.software_version) \ + .order_by(func.count(Device.id).desc()) + print("--- Software version ---") + for [software_version, count] in software_query.all(): + print("{}: {}".format(software_version, count)) + + +@manager.command +def hardware_stats(): + """Show stats about hardware version used by devices.""" + hardware_query = session.query(Device.hardware_version, + func.count(Device.id)) \ + .group_by(Device.hardware_version) \ + .order_by(func.count(Device.id).desc()) + print("\n--- Hardware version ---") + for [hardware_version, count] in hardware_query.all(): + print("{}: {}".format(hardware_version, count)) diff --git a/ogn/gateway/process.py b/ogn/gateway/process.py index 1dce36a..bfd0464 100644 --- a/ogn/gateway/process.py +++ b/ogn/gateway/process.py @@ -2,7 +2,6 @@ import logging from ogn.commands.dbutils import session from ogn.model import AircraftBeacon, ReceiverBeacon, Device, Receiver, Location from ogn.parser import parse_aprs, parse_ogn_receiver_beacon, parse_ogn_aircraft_beacon, ParseError -from ogn.model.address_origin import AddressOrigin logger = logging.getLogger(__name__) @@ -54,17 +53,25 @@ def process_beacon(raw_message): beacon = AircraftBeacon(**message) # connect beacon with device - device = session.query(Device.id) \ + device = session.query(Device) \ .filter(Device.address == beacon.address) \ - .order_by(Device.address_origin) \ .first() if device is None: device = Device() device.address = beacon.address - device.address_origin = AddressOrigin.seen session.add(device) beacon.device_id = device.id + # update device + device.aircraft_type = beacon.aircraft_type + device.stealth = beacon.stealth + if beacon.hardware_version is not None: + device.hardware_version = beacon.hardware_version + if beacon.software_version is not None: + device.software_version = beacon.software_version + if beacon.real_address is not None: + device.real_address = beacon.real_address + # connect beacon with receiver receiver = session.query(Receiver.id) \ .filter(Receiver.name == beacon.receiver_name) \ diff --git a/ogn/model/__init__.py b/ogn/model/__init__.py index 8ff0c22..add61fa 100644 --- a/ogn/model/__init__.py +++ b/ogn/model/__init__.py @@ -4,6 +4,7 @@ from .aircraft_type import AircraftType from .base import Base from .beacon import Beacon from .device import Device +from .device_info import DeviceInfo from .aircraft_beacon import AircraftBeacon from .receiver_beacon import ReceiverBeacon from .receiver import Receiver diff --git a/ogn/model/address_origin.py b/ogn/model/address_origin.py index e957357..a269973 100644 --- a/ogn/model/address_origin.py +++ b/ogn/model/address_origin.py @@ -1,22 +1,22 @@ class AddressOrigin: + unknown = 0 ogn_ddb = 1 flarmnet = 2 user_defined = 3 - seen = 4 def __init__(self, origin): - if origin in [1, 2, 3, 4]: + if origin in [0, 1, 2, 3]: self.origin = origin else: raise ValueError('no address origin with id {} known'.format(origin)) def name(self): - if self.origin == self.ogn_ddb: + if self.origin == self.unknown: + return 'unknown' + elif self.origin == self.ogn_ddb: return 'OGN-DDB' elif self.origin == self.flarmnet: return 'FlarmNet' elif self.origin == self.user_defined: return 'user-defined' - elif self.origin == self.seen: - return 'seen' return '' diff --git a/ogn/model/device.py b/ogn/model/device.py index 626bf3e..491817c 100644 --- a/ogn/model/device.py +++ b/ogn/model/device.py @@ -1,4 +1,4 @@ -from sqlalchemy import Column, Integer, String, Unicode, Boolean, SmallInteger +from sqlalchemy import Column, Integer, String, Float, Boolean, SmallInteger from sqlalchemy.orm import relationship from .base import Base @@ -8,32 +8,21 @@ class Device(Base): __tablename__ = 'device' id = Column(Integer, primary_key=True) - address_type = None address = Column(String(6), index=True) - name = Column(Unicode) - airport = Column(String) - aircraft = Column(String) - registration = Column(String(7), index=True) - competition = Column(String(3)) - frequency = Column(String) - tracked = Column(Boolean) - identified = Column(Boolean) aircraft_type = Column(SmallInteger, index=True) - - address_origin = Column(SmallInteger) + stealth = Column(Boolean) + software_version = Column(Float) + hardware_version = Column(SmallInteger) + real_address = Column(String(6)) # Relations aircraft_beacons = relationship('AircraftBeacon') def __repr__(self): - return "" % ( - self.address_type, + return "" % ( self.address, - self.name, - self.airport, - self.aircraft, - self.registration, - self.competition, - self.frequency, - self.tracked, - self.identified) + self.aircraft_type, + self.stealth, + self.software_version, + self.hardware_version, + self.real_address) diff --git a/ogn/model/device_info.py b/ogn/model/device_info.py new file mode 100644 index 0000000..fe543ba --- /dev/null +++ b/ogn/model/device_info.py @@ -0,0 +1,32 @@ +from sqlalchemy import Column, Integer, String, Boolean, SmallInteger + +from .base import Base + + +class DeviceInfo(Base): + __tablename__ = 'device_info' + + id = Column(Integer, primary_key=True) + address_type = None + address = Column(String(6), index=True) + aircraft = Column(String) + registration = Column(String(7)) + competition = Column(String(3)) + tracked = Column(Boolean) + identified = Column(Boolean) + aircraft_type = Column(SmallInteger) + + address_origin = Column(SmallInteger) + + def __repr__(self): + return "" % ( + self.address_type, + self.address, + self.name, + self.airport, + self.aircraft, + self.registration, + self.competition, + self.frequency, + self.tracked, + self.identified) diff --git a/ogn/utils.py b/ogn/utils.py index 8d29f5f..252d23d 100644 --- a/ogn/utils.py +++ b/ogn/utils.py @@ -2,7 +2,7 @@ import requests import csv from io import StringIO -from .model import Device, Airport, Location +from .model import AddressOrigin, DeviceInfo, Airport, Location from geopy.geocoders import Nominatim from geopy.exc import GeopyError @@ -21,7 +21,7 @@ nm2m = 1852 mi2m = 1609.34 -def get_ddb(csvfile=None): +def get_ddb(csvfile=None, address_origin=AddressOrigin.unknown): if csvfile is None: r = requests.get(DDB_URL) rows = '\n'.join(i for i in r.text.splitlines() if i[0] != '#') @@ -31,21 +31,22 @@ def get_ddb(csvfile=None): data = csv.reader(StringIO(rows), quotechar="'", quoting=csv.QUOTE_ALL) - devices = list() + device_infos = list() for row in data: - device = Device() - device.address_type = row[0] - device.address = row[1] - device.aircraft = row[2] - device.registration = row[3] - device.competition = row[4] - device.tracked = row[5] == 'Y' - device.identified = row[6] == 'Y' - device.aircraft_type = int(row[7]) + device_info = DeviceInfo() + device_info.address_type = row[0] + device_info.address = row[1] + device_info.aircraft = row[2] + device_info.registration = row[3] + 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.address_origin = address_origin - devices.append(device) + device_infos.append(device_info) - return devices + return device_infos def get_trackable(ddb):