From c8e625f608a15a69fa173a71c0f776e8a4c96fba Mon Sep 17 00:00:00 2001 From: nzkarit Date: Sun, 10 Sep 2017 20:29:20 +1200 Subject: [PATCH] Change to python3, moved to argparse, adding a config file for defaults, adding logging --- .gitignore | 1 + ADSB_Encoder.py | 62 ++++++++++++++++++++++++++++++++---------------- ModeSLocation.py | 2 +- config.cfg | 15 ++++++++++++ logging.cfg | 28 ++++++++++++++++++++++ 5 files changed, 87 insertions(+), 21 deletions(-) create mode 100644 config.cfg create mode 100644 logging.cfg diff --git a/.gitignore b/.gitignore index 81fbea6..34aef8c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.iq8s *.pyc +*.log diff --git a/ADSB_Encoder.py b/ADSB_Encoder.py index 2ed62ea..46da670 100755 --- a/ADSB_Encoder.py +++ b/ADSB_Encoder.py @@ -1,11 +1,14 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # from HackRF import HackRF from PPM import PPM from ModeS import ModeS from sys import argv, exit -from optparse import OptionParser +import argparse +import configparser +import logging +import logging.config import os ############################################################### @@ -28,29 +31,45 @@ import os ############################################################### # Further work on fork # Copyright (C) 2017 David Robinson -def optionParser(): - usage = 'usage: %prog [options]' - parser = OptionParser(usage=usage) - parser.add_option('-i', '--icao', action='store', type='int', dest='icao', default='0xABCDEF', help='The ICAO number for the plane in hex. Ensure the ICAO is prefixed with \'0x\' to ensure this is parsed as a hex number. Default: %default') - parser.add_option('--lat', '--latitude', action='store', type='float', dest='latitude', default='12.34', help='Latitude for the plane in decminal degrees. Default: %default') - parser.add_option('--lon', '--long', '--longitude', action='store', type='float', dest='longitude', default='56.78', help='Longitude for the place in decminal degrees. Default: %default') - parser.add_option('-a', '--alt', '--altitude', action='store', type='float', dest='altitude', default='9876.5', help='Altitude in decminal feet. Default: %default') - parser.add_option('--ca', '--capability', action='store', type='int', dest='capability', default=5, help='The capability. (Think this is always 5 from ADSB messages. More info would be appreciate). Default: %default') - parser.add_option('--tc', '--typecode', action='store', type='int', dest='typecode', default=11, help='The type for the ADSB messsage. See https://adsb-decode-guide.readthedocs.io/en/latest/content/introduction.html#ads-b-message-types for more information. Default: %default') - parser.add_option('--ss', '--surveillancestatus', action='store', type='int', dest='surveillancestatus', default=0, help='The surveillance status. (Think this is always 0 from ADSB messages. More info would be appreciate). Default: %default') - parser.add_option('--nicsb', '--nicsupplementb', action='store', type='int', dest='nicsupplementb', default=0, help='The NIC supplement-B.(Think this is always 0 from ADSB messages. More info would be appreciate). Default: %default') - parser.add_option('--time', action='store', type='int', dest='time', default=0, help='The time. (Think this is always 0 from ADSB messages. More info would be appreciate). Default: %default') - parser.add_option('-s', '--surface', action='store', default=False, dest='surface', help='If the plane is on the ground or not. Default: %default') - parser.add_option('-o', '--out', '--output', action='store', type='string', default='Samples_256K.iq8s', dest='outputfilename', help='The iq8s output filename. This is the file which you will feed into the hackRF. Default: %default') + +def auto_int(x): + """Parses HEX into for argParser""" + return int(x, 0) + +def argParser(): + #TODO add some contraint checking + description = 'This tool will generate ADS-B data in a form that a hackRF can broadcast. In addition to providing the information at the command the defaults can be changed in the config.cfg file and the the loggin config changed in logging.cfg.' + parser = argparse.ArgumentParser(description=description) + parser.add_argument('-i', '--icao', action='store', type=auto_int, dest='icao', default=cfg.get('plane', 'icao'), help='The ICAO number for the plane in hex. Ensure the ICAO is prefixed with \'0x\' to ensure this is parsed as a hex number. Default: %(default)s') + parser.add_argument('--lat', '--latitude', action='store', type=float, dest='latitude', default=cfg.getfloat('plane', 'latitude'), help='Latitude for the plane in decminal degrees. Default: %(default)s') + parser.add_argument('--lon', '--long', '--longitude', action='store', type=float, dest='longitude', default=cfg.getfloat('plane', 'longitude'), help='Longitude for the place in decminal degrees. Default: %(default)s') + parser.add_argument('-a', '--alt', '--altitude', action='store', type=float, dest='altitude', default=cfg.getfloat('plane', 'altitude'), help='Altitude in decminal feet. Default: %(default)s') + parser.add_argument('--ca', '--capability', action='store', type=int, dest='capability', default=cfg.getint('plane', 'capability'), help='The capability. (Think this is always 5 from ADSB messages. More info would be appreciate). Default: %(default)s') + parser.add_argument('--tc', '--typecode', action='store', type=int, dest='typecode', default=cfg.getint('plane', 'typecode'), help='The type for the ADSB messsage. See https://adsb-decode-guide.readthedocs.io/en/latest/content/introduction.html#ads-b-message-types for more information. Default: %(default)s') + parser.add_argument('--ss', '--surveillancestatus', action='store', type=int, dest='surveillancestatus', default=cfg.getint('plane', 'surveillancestatus'), help='The surveillance status. (Think this is always 0 from ADSB messages. More info would be appreciate). Default: %(default)s') + parser.add_argument('--nicsb', '--nicsupplementb', action='store', type=int, dest='nicsupplementb', default=cfg.getint('plane', 'nicsupplementb'), help='The NIC supplement-B.(Think this is always 0 from ADSB messages. More info would be appreciate). Default: %(default)s') + parser.add_argument('--time', action='store', type=int, dest='time', default=cfg.getint('plane', 'time'), help='The time. (Think this is always 0 from ADSB messages. More info would be appreciate). Default: %(default)s') + parser.add_argument('-s', '--surface', action='store', default=cfg.getboolean('plane', 'surface'), type=bool, dest='surface', help='If the plane is on the ground or not. Default: %(default)s') + parser.add_argument('-o', '--out', '--output', action='store', type=str, default=cfg.get('general', 'outputfilename'), dest='outputfilename', help='The iq8s output filename. This is the file which you will feed into the hackRF. Default: %(default)s') + parser.add_argument('-r', '--repeats', action='store', dest='repeats', type=int, default=cfg.getint('general', 'repeats'), help='How many repeats of the data to perform. Default: %(default)s') + return parser.parse_args() if __name__ == "__main__": + global cfg + cfg = configparser.ConfigParser() + cfg.read('config.cfg') - options, arguments = optionParser() - print options + arguments = argParser() + + global logger + logging.config.fileConfig('logging.cfg') + logger = logging.getLogger(__name__) + logger.info('Starting ADSB Encoder') + logger.debug('The arguments: %s' % (arguments)) modes = ModeS() - (df17_even, df17_odd) = modes.df17_pos_rep_encode(options.capability, options.icao, options.typecode, options.surveillancestatus, options.nicsupplementb, options.altitude, options.time, options.latitude, options.longitude, options.surface) + (df17_even, df17_odd) = modes.df17_pos_rep_encode(arguments.capability, arguments.icao, arguments.typecode, arguments.surveillancestatus, arguments.nicsupplementb, arguments.altitude, arguments.time, arguments.latitude, arguments.longitude, arguments.surface) ppm = PPM() df17_array = ppm.frame_1090es_ppm_modulate(df17_even, df17_odd) @@ -60,5 +79,8 @@ if __name__ == "__main__": SamplesFile = open('tmp.iq8s', 'wb') SamplesFile.write(samples_array) - os.system("dd if=tmp.iq8s of=%s bs=4k seek=63" % (options.outputfilename)) + SamplesFile.close() + os.system("dd if=tmp.iq8s of=%s bs=4k seek=63" % (arguments.outputfilename)) # TODO redirect output to /dev/null + os.system('sync') os.system('rm tmp.iq8s') + diff --git a/ModeSLocation.py b/ModeSLocation.py index 9261af5..93717fc 100644 --- a/ModeSLocation.py +++ b/ModeSLocation.py @@ -32,7 +32,7 @@ class ModeSLocation: def encode_alt_modes(self, alt, bit13): mbit = False qbit = True - encalt = (int(alt) + 1000) / 25 + encalt = int((int(alt) + 1000) / 25) if bit13 is True: tmp1 = (encalt & 0xfe0) << 2 diff --git a/config.cfg b/config.cfg new file mode 100644 index 0000000..3d0adc0 --- /dev/null +++ b/config.cfg @@ -0,0 +1,15 @@ +[general] +outputfilename = Samples_256K.iq8s +repeats = 1 + +[plane] +icao = 0xABCDEF +latitude = 12.34 +longitude = 56.78 +altitude = 9876.5 +capability = 5 +typecode = 11 +surveillancestatus = 0 +nicsupplementb = 0 +time = 0 +surface = false diff --git a/logging.cfg b/logging.cfg new file mode 100644 index 0000000..ac7b647 --- /dev/null +++ b/logging.cfg @@ -0,0 +1,28 @@ +[loggers] +keys=root + +[handlers] +keys=consoleHandler, timedRotatingFileHandler + +[formatters] +keys=simpleFormatter + +[logger_root] +level=DEBUG +handlers=consoleHandler, timedRotatingFileHandler + +[handler_timedRotatingFileHandler] +class=handlers.TimedRotatingFileHandler +level=DEBUG +formatter=simpleFormatter +args=('ADSB_Encoder.log', 'H', 1, 72) + +[handler_consoleHandler] +class=StreamHandler +level=WARNING +formatter=simpleFormatter +args=(sys.stdout,) + +[formatter_simpleFormatter] +format=%(asctime)s - %(name)s - %(levelname)s - %(message)s +datefmt=