kopia lustrzana https://github.com/glidernet/ogn-python
commit
c87bb0f546
|
@ -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
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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']))
|
|
@ -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))
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ''
|
||||
|
|
|
@ -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 "<Device: %s,%s,%s,%s,%s,%s,%s,%s,%s,%s>" % (
|
||||
self.address_type,
|
||||
return "<Device: %s,%s,%s,%s,%s,%s>" % (
|
||||
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)
|
||||
|
|
|
@ -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 "<DeviceInfo: %s,%s,%s,%s,%s,%s,%s,%s,%s,%s>" % (
|
||||
self.address_type,
|
||||
self.address,
|
||||
self.name,
|
||||
self.airport,
|
||||
self.aircraft,
|
||||
self.registration,
|
||||
self.competition,
|
||||
self.frequency,
|
||||
self.tracked,
|
||||
self.identified)
|
29
ogn/utils.py
29
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):
|
||||
|
|
Ładowanie…
Reference in New Issue