Merge branch 'master' of github.com:nzkarit/ADSB-out-private into python3-ConfigFile-repeats-logging

This commit is contained in:
nzkarit 2017-09-10 21:13:31 +12:00
commit 4f520ac84c
5 changed files with 100 additions and 30 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
*.iq8s
*.pyc
*.log

View File

@ -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,37 +31,60 @@ 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
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)
ppm = PPM()
df17_array = ppm.frame_1090es_ppm_modulate(df17_even, df17_odd)
hackrf = HackRF()
samples_array = hackrf.hackrf_raw_IQ_format(df17_array)
arguments = argParser()
global logger
logging.config.fileConfig('logging.cfg')
logger = logging.getLogger(__name__)
logger.info('Starting ADSB Encoder')
logger.debug('The arguments: %s' % (arguments))
logger.info('Repeating the message %s times' % (arguments.repeats))
SamplesFile = open('tmp.iq8s', 'wb')
SamplesFile.write(samples_array)
os.system("dd if=tmp.iq8s of=%s bs=4k seek=63" % (options.outputfilename))
for i in range(0, arguments.repeats):
modes = ModeS()
(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)
hackrf = HackRF()
samples_array = hackrf.hackrf_raw_IQ_format(df17_array)
SamplesFile.write(samples_array)
SamplesFile.close()
os.system('sync')
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')

View File

@ -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

15
config.cfg Normal file
View File

@ -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

28
logging.cfg Normal file
View File

@ -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=