2017-06-23 06:13:51 +00:00
import os
2017-10-06 19:38:08 +00:00
import re
2018-09-03 17:58:35 +00:00
import logging
2017-06-23 06:13:51 +00:00
2017-06-19 18:59:00 +00:00
from manager import Manager
2017-10-03 11:31:24 +00:00
from ogn . commands . dbutils import session
from ogn . model import AircraftBeacon , ReceiverBeacon
from ogn . utils import open_file
2018-09-03 17:58:35 +00:00
from ogn . gateway . process_tools import FileSaver , Converter , Merger
2017-10-03 11:31:24 +00:00
2017-06-19 18:59:00 +00:00
manager = Manager ( )
2017-10-06 19:38:08 +00:00
PATTERN = ' ^.+ \ .txt \ _( \ d {4} \ - \ d {2} \ - \ d {2} )( \ .gz)?$ '
2017-06-19 18:59:00 +00:00
2017-06-23 06:13:51 +00:00
@manager.command
2018-09-03 17:58:35 +00:00
def convert_logfile ( path ) :
2017-06-23 06:13:51 +00:00
""" Convert ogn logfiles to csv logfiles (one for aircraft beacons and one for receiver beacons) <arg: path>. Logfile name: blablabla.txt_YYYY-MM-DD. """
2018-09-03 17:58:35 +00:00
logging . basicConfig ( filename = ' convert.log ' , level = logging . DEBUG )
2017-06-23 06:13:51 +00:00
if os . path . isfile ( path ) :
2017-10-06 19:38:08 +00:00
head , tail = os . path . split ( path )
convert ( tail , path = head )
2018-09-03 17:58:35 +00:00
logging . info ( " Finished converting single file {} " . format ( head ) )
2017-06-23 06:13:51 +00:00
elif os . path . isdir ( path ) :
for filename in os . listdir ( path ) :
convert ( filename , path = path )
2018-09-03 17:58:35 +00:00
logging . info ( " Finished converting file path {} " . format ( path ) )
2017-06-23 06:13:51 +00:00
else :
2018-09-03 17:58:35 +00:00
logging . warning ( " Not a file nor a path: {} " . format ( path ) )
2017-06-23 06:13:51 +00:00
def convert ( sourcefile , path = ' ' ) :
2018-09-03 17:58:35 +00:00
logging . info ( " convert: {} {} " . format ( sourcefile , path ) )
2017-06-23 06:13:51 +00:00
import datetime
2018-09-03 17:58:35 +00:00
from ogn . gateway . process import string_to_message
2017-12-18 21:54:00 +00:00
2017-10-06 19:38:08 +00:00
match = re . search ( PATTERN , sourcefile )
2017-06-23 06:13:51 +00:00
if match :
reference_date_string = match . group ( 1 )
2017-10-03 13:35:22 +00:00
reference_date = datetime . datetime . strptime ( reference_date_string , " % Y- % m- %d " )
2017-10-06 19:38:08 +00:00
2018-09-03 17:58:35 +00:00
# Build the processing pipeline
saver = FileSaver ( )
converter = Converter ( callback = saver )
merger = Merger ( callback = converter )
2017-10-06 19:38:08 +00:00
2018-09-03 17:58:35 +00:00
try :
saver . open ( path , reference_date_string )
except FileExistsError :
logging . warning ( " Output files already exists. Skipping " )
2017-10-06 19:38:08 +00:00
return
2017-06-23 06:13:51 +00:00
else :
2018-09-03 17:58:35 +00:00
logging . warning ( " filename ' {} ' does not match pattern. Skipping " . format ( sourcefile ) )
2017-06-23 06:13:51 +00:00
return
fin = open_file ( os . path . join ( path , sourcefile ) )
# get total lines of the input file
2018-09-03 17:58:35 +00:00
total_lines = 0
2017-06-23 06:13:51 +00:00
for line in fin :
2018-09-03 17:58:35 +00:00
total_lines + = 1
2017-06-23 06:13:51 +00:00
fin . seek ( 0 )
progress = - 1
2018-09-03 17:58:35 +00:00
current_line = 0
2017-06-23 06:13:51 +00:00
print ( ' Start importing ogn-logfile ' )
for line in fin :
2018-09-03 17:58:35 +00:00
current_line + = 1
if int ( 1000 * current_line / total_lines ) != progress :
progress = round ( 1000 * current_line / total_lines )
print ( " \r Reading line {} ( {} % ) " . format ( current_line , progress / 10 ) , end = ' ' )
message = string_to_message ( line . strip ( ) , reference_date = reference_date )
if message is None :
print ( " ===== " )
print ( line . strip ( ) )
continue
merger . add_message ( message )
merger . flush ( )
saver . close ( )
2017-06-23 06:13:51 +00:00
fin . close ( )
2017-06-19 18:59:00 +00:00
@manager.command
def drop_indices ( ) :
""" Drop indices of AircraftBeacon. """
session . execute ( """
2018-09-03 17:58:35 +00:00
DROP INDEX IF EXISTS idx_aircraft_beacons_location ;
DROP INDEX IF EXISTS ix_aircraft_beacons_date_device_id_address ;
DROP INDEX IF EXISTS ix_aircraft_beacons_date_receiver_id_distance ;
2018-01-11 07:35:07 +00:00
DROP INDEX IF EXISTS ix_aircraft_beacons_timestamp ;
2018-09-03 17:58:35 +00:00
DROP INDEX IF EXISTS idx_receiver_beacons_location ;
DROP INDEX IF EXISTS ix_receiver_beacons_date_receiver_id ;
DROP INDEX IF EXISTS ix_receiver_beacons_timestamp ;
2017-06-19 18:59:00 +00:00
""" )
2018-09-03 17:58:35 +00:00
print ( " Dropped indices of AircraftBeacon and ReceiverBeacon " )
2017-06-19 18:59:00 +00:00
2018-01-11 19:04:21 +00:00
# disable constraint trigger
session . execute ( """
2018-09-03 17:58:35 +00:00
ALTER TABLE aircraft_beacons DISABLE TRIGGER ALL ;
ALTER TABLE receiver_beacons DISABLE TRIGGER ALL ;
2018-01-11 19:04:21 +00:00
""" )
2018-09-03 17:58:35 +00:00
session . commit ( )
2018-01-11 19:04:21 +00:00
print ( " Disabled constraint triggers " )
2017-06-19 18:59:00 +00:00
@manager.command
def create_indices ( ) :
""" Create indices for AircraftBeacon. """
session . execute ( """
2018-09-03 17:58:35 +00:00
CREATE INDEX idx_aircraft_beacons_location ON aircraft_beacons USING GIST ( location ) ;
CREATE INDEX ix_aircraft_beacons_date_device_id_address ON aircraft_beacons USING BTREE ( ( timestamp : : date ) , device_id , address ) ;
CREATE INDEX ix_aircraft_beacons_date_receiver_id_distance ON aircraft_beacons USING BTREE ( ( timestamp : : date ) , receiver_id , distance ) ;
CREATE INDEX ix_aircraft_beacons_timestamp ON aircraft_beacons USING BTREE ( timestamp ) ;
CREATE INDEX idx_receiver_beacons_location ON receiver_beacons USING GIST ( location ) ;
CREATE INDEX ix_receiver_beacons_date_receiver_id ON receiver_beacons USING BTREE ( ( timestamp : : date ) , receiver_id ) ;
CREATE INDEX ix_receiver_beacons_timestamp ON receiver_beacons USING BTREE ( timestamp ) ;
2017-06-19 18:59:00 +00:00
""" )
2018-09-03 17:58:35 +00:00
print ( " Created indices for AircraftBeacon and ReceiverBeacon " )
2017-06-19 18:59:00 +00:00
2018-01-11 19:04:21 +00:00
session . execute ( """
2018-09-03 17:58:35 +00:00
ALTER TABLE aircraft_beacons ENABLE TRIGGER ALL ;
ALTER TABLE receiver_beacons ENABLE TRIGGER ALL ;
2018-01-11 19:04:21 +00:00
""" )
2018-09-03 17:58:35 +00:00
session . commit ( )
2018-01-11 19:04:21 +00:00
print ( " Enabled constraint triggers " )
2017-06-19 18:59:00 +00:00
@manager.command
def import_csv_logfile ( path , logfile = ' main.log ' , loglevel = ' INFO ' ) :
""" Import csv logfile <arg: csv logfile>. """
import datetime
import os
if os . path . isfile ( path ) :
print ( " {} : Importing file: {} " . format ( datetime . datetime . now ( ) , path ) )
import_logfile ( path )
elif os . path . isdir ( path ) :
print ( " {} : Scanning path: {} " . format ( datetime . datetime . now ( ) , path ) )
for filename in os . listdir ( path ) :
print ( " {} : Importing file: {} " . format ( datetime . datetime . now ( ) , filename ) )
import_logfile ( os . path . join ( path , filename ) )
else :
print ( " {} : Path {} not found. " . format ( datetime . datetime . now ( ) , path ) )
print ( " {} : Finished. " . format ( datetime . datetime . now ( ) ) )
def import_logfile ( path ) :
import os
import re
head , tail = os . path . split ( path )
match = re . search ( ' ^.+ \ .csv \ _( \ d {4} \ - \ d {2} \ - \ d {2} ).+?$ ' , tail )
if match :
reference_date_string = match . group ( 1 )
else :
print ( " filename ' {} ' does not match pattern. Skipping " . format ( path ) )
return
f = open_file ( path )
header = f . readline ( ) . strip ( )
f . close ( )
aircraft_beacon_header = ' , ' . join ( AircraftBeacon . get_csv_columns ( ) )
receiver_beacon_header = ' , ' . join ( ReceiverBeacon . get_csv_columns ( ) )
if header == aircraft_beacon_header :
2018-01-11 07:35:07 +00:00
if check_no_beacons ( ' aircraft_beacons ' , reference_date_string ) :
2017-06-19 18:59:00 +00:00
import_aircraft_beacon_logfile ( path )
else :
print ( " For {} beacons already exist. Skipping " . format ( reference_date_string ) )
elif header == receiver_beacon_header :
2018-01-11 07:35:07 +00:00
if check_no_beacons ( ' receiver_beacons ' , reference_date_string ) :
2017-06-19 18:59:00 +00:00
import_receiver_beacon_logfile ( path )
else :
print ( " For {} beacons already exist. Skipping " . format ( reference_date_string ) )
else :
2018-09-03 17:58:35 +00:00
s1 = header
s2 = ' , ' . join ( AircraftBeacon . get_csv_columns ( ) )
print ( s1 )
print ( s2 )
print ( [ i for i in range ( len ( s1 ) ) if s1 [ i ] != s2 [ i ] ] )
2017-12-02 12:08:44 +00:00
print ( " Unknown file type: {} " . format ( tail ) )
2017-06-19 18:59:00 +00:00
def check_no_beacons ( tablename , reference_date_string ) :
result = session . execute ( """ SELECT * FROM {0} WHERE timestamp BETWEEN ' {1} 00:00:00 ' AND ' {1} 23:59:59 ' LIMIT 1 """ . format ( tablename , reference_date_string ) )
if result . fetchall ( ) :
return False
else :
return True
def import_aircraft_beacon_logfile ( csv_logfile ) :
SQL_TEMPTABLE_STATEMENT = """
2018-01-11 07:35:07 +00:00
DROP TABLE IF EXISTS aircraft_beacons_temp ;
CREATE TABLE aircraft_beacons_temp (
2017-06-19 18:59:00 +00:00
location geometry ,
2018-09-03 17:58:35 +00:00
altitude real ,
2017-06-19 18:59:00 +00:00
name character varying ,
2018-01-19 18:14:57 +00:00
dstcall character varying ,
2018-04-28 09:43:45 +00:00
relay character varying ,
receiver_name character varying ( 9 ) ,
2017-06-19 18:59:00 +00:00
" timestamp " timestamp without time zone ,
2018-09-03 17:58:35 +00:00
track smallint ,
ground_speed real ,
2017-06-19 18:59:00 +00:00
address_type smallint ,
aircraft_type smallint ,
stealth boolean ,
2018-09-03 17:58:35 +00:00
address character varying ,
climb_rate real ,
turn_rate real ,
signal_quality real ,
error_count smallint ,
frequency_offset real ,
gps_quality_horizontal smallint ,
gps_quality_vertical smallint ,
software_version real ,
2017-06-19 18:59:00 +00:00
hardware_version smallint ,
real_address character varying ( 6 ) ,
2018-09-03 17:58:35 +00:00
signal_power real ,
2018-01-19 18:14:57 +00:00
2018-09-03 17:58:35 +00:00
distance real ,
radial smallint ,
normalized_signal_quality real ,
2018-01-19 18:14:57 +00:00
location_mgrs character varying ( 15 )
2017-06-19 18:59:00 +00:00
) ;
"""
session . execute ( SQL_TEMPTABLE_STATEMENT )
SQL_COPY_STATEMENT = """
2018-01-11 07:35:07 +00:00
COPY aircraft_beacons_temp ( % s ) FROM STDIN WITH
2017-06-19 18:59:00 +00:00
CSV
HEADER
DELIMITER AS ' , '
"""
file = open_file ( csv_logfile )
column_names = ' , ' . join ( AircraftBeacon . get_csv_columns ( ) )
sql = SQL_COPY_STATEMENT % column_names
print ( " Start importing logfile: {} " . format ( csv_logfile ) )
conn = session . connection ( ) . connection
cursor = conn . cursor ( )
cursor . copy_expert ( sql = sql , file = file )
conn . commit ( )
cursor . close ( )
file . close ( )
print ( " Read logfile into temporary table " )
# create device if not exist
session . execute ( """
2018-01-11 07:35:07 +00:00
INSERT INTO devices ( address )
2017-06-19 18:59:00 +00:00
SELECT DISTINCT ( t . address )
2018-01-11 07:35:07 +00:00
FROM aircraft_beacons_temp t
WHERE NOT EXISTS ( SELECT 1 FROM devices d WHERE d . address = t . address )
2017-06-19 18:59:00 +00:00
""" )
print ( " Inserted missing Devices " )
# create receiver if not exist
session . execute ( """
2018-01-11 07:35:07 +00:00
INSERT INTO receivers ( name )
2017-06-19 18:59:00 +00:00
SELECT DISTINCT ( t . receiver_name )
2018-01-11 07:35:07 +00:00
FROM aircraft_beacons_temp t
WHERE NOT EXISTS ( SELECT 1 FROM receivers r WHERE r . name = t . receiver_name )
2017-06-19 18:59:00 +00:00
""" )
print ( " Inserted missing Receivers " )
session . execute ( """
2018-04-28 09:43:45 +00:00
INSERT INTO aircraft_beacons ( location , altitude , name , dstcall , relay , receiver_name , timestamp , track , ground_speed ,
2018-09-03 17:58:35 +00:00
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 , normalized_signal_quality , location_mgrs ,
2018-01-19 18:14:57 +00:00
receiver_id , device_id )
2018-04-28 09:43:45 +00:00
SELECT t . location , t . altitude , t . name , t . dstcall , t . relay , t . receiver_name , t . timestamp , t . track , t . ground_speed ,
2018-09-03 17:58:35 +00:00
t . address_type , t . aircraft_type , t . stealth , t . address , t . climb_rate , t . turn_rate , t . signal_quality , t . error_count , t . frequency_offset , t . gps_quality_horizontal , t . gps_quality_vertical , t . software_version , t . hardware_version , t . real_address , t . signal_power ,
t . distance , t . radial , t . normalized_signal_quality , t . location_mgrs ,
2018-01-19 18:14:57 +00:00
r . id , d . id
2018-01-11 07:35:07 +00:00
FROM aircraft_beacons_temp t , receivers r , devices d
2017-06-19 18:59:00 +00:00
WHERE t . receiver_name = r . name AND t . address = d . address
""" )
print ( " Wrote AircraftBeacons from temporary table into final table " )
2018-01-11 07:35:07 +00:00
session . execute ( """ DROP TABLE aircraft_beacons_temp """ )
2017-06-19 18:59:00 +00:00
print ( " Dropped temporary table " )
session . commit ( )
print ( " Finished " )
def import_receiver_beacon_logfile ( csv_logfile ) :
""" Import csv logfile <arg: csv logfile>. """
SQL_TEMPTABLE_STATEMENT = """
2018-01-11 07:35:07 +00:00
DROP TABLE IF EXISTS receiver_beacons_temp ;
CREATE TABLE receiver_beacons_temp (
2017-06-19 18:59:00 +00:00
location geometry ,
2018-09-03 17:58:35 +00:00
altitude real ,
2017-06-19 18:59:00 +00:00
name character varying ,
receiver_name character varying ( 9 ) ,
2018-01-19 18:14:57 +00:00
dstcall character varying ,
2017-06-19 18:59:00 +00:00
" timestamp " timestamp without time zone ,
version character varying ,
platform character varying ,
2018-09-03 17:58:35 +00:00
cpu_load real ,
free_ram real ,
total_ram real ,
ntp_error real ,
rt_crystal_correction real ,
voltage real ,
amperage real ,
cpu_temp real ,
2017-06-19 18:59:00 +00:00
senders_visible integer ,
senders_total integer ,
2018-09-03 17:58:35 +00:00
rec_input_noise real ,
senders_signal real ,
2017-06-19 18:59:00 +00:00
senders_messages integer ,
2018-09-03 17:58:35 +00:00
good_senders_signal real ,
2017-06-19 18:59:00 +00:00
good_senders integer ,
good_and_bad_senders integer
) ;
"""
session . execute ( SQL_TEMPTABLE_STATEMENT )
SQL_COPY_STATEMENT = """
2018-01-11 07:35:07 +00:00
COPY receiver_beacons_temp ( % s ) FROM STDIN WITH
2017-06-19 18:59:00 +00:00
CSV
HEADER
DELIMITER AS ' , '
"""
file = open_file ( csv_logfile )
column_names = ' , ' . join ( ReceiverBeacon . get_csv_columns ( ) )
sql = SQL_COPY_STATEMENT % column_names
print ( " Start importing logfile: {} " . format ( csv_logfile ) )
conn = session . connection ( ) . connection
cursor = conn . cursor ( )
cursor . copy_expert ( sql = sql , file = file )
conn . commit ( )
cursor . close ( )
file . close ( )
print ( " Read logfile into temporary table " )
# create receiver if not exist
session . execute ( """
2018-01-11 07:35:07 +00:00
INSERT INTO receivers ( name )
2017-06-19 18:59:00 +00:00
SELECT DISTINCT ( t . name )
2018-01-11 07:35:07 +00:00
FROM receiver_beacons_temp t
WHERE NOT EXISTS ( SELECT 1 FROM receivers r WHERE r . name = t . name )
2017-06-19 18:59:00 +00:00
""" )
print ( " Inserted missing Receivers " )
session . execute ( """
2018-04-28 09:43:45 +00:00
INSERT INTO receiver_beacons ( location , altitude , name , dstcall , receiver_name , timestamp ,
2017-06-19 18:59:00 +00:00
version , platform , cpu_load , free_ram , total_ram , ntp_error , rt_crystal_correction , voltage , amperage , cpu_temp , senders_visible , senders_total , rec_input_noise , senders_signal , senders_messages , good_senders_signal , good_senders , good_and_bad_senders ,
2018-01-19 18:14:57 +00:00
receiver_id )
2018-04-28 09:43:45 +00:00
SELECT t . location , t . altitude , t . name , t . dstcall , t . receiver_name , t . timestamp ,
2017-06-19 18:59:00 +00:00
t . version , t . platform , t . cpu_load , t . free_ram , t . total_ram , t . ntp_error , t . rt_crystal_correction , t . voltage , amperage , t . cpu_temp , t . senders_visible , t . senders_total , t . rec_input_noise , t . senders_signal , t . senders_messages , t . good_senders_signal , t . good_senders , t . good_and_bad_senders ,
2018-01-19 18:14:57 +00:00
r . id
2018-01-11 07:35:07 +00:00
FROM receiver_beacons_temp t , receivers r
2017-06-19 18:59:00 +00:00
WHERE t . name = r . name
""" )
print ( " Wrote ReceiverBeacons from temporary table into final table " )
2018-01-11 07:35:07 +00:00
session . execute ( """ DROP TABLE receiver_beacons_temp """ )
2017-06-19 18:59:00 +00:00
print ( " Dropped temporary table " )
session . commit ( )
print ( " Finished " )