Merge branch 'master' of https://github.com/bistromath/gr-air-modes into simple_state_server

This commit is contained in:
Phelps Williams 2016-04-28 18:12:27 -07:00
commit b4695038e3
15 changed files with 169 additions and 132 deletions

View File

@ -22,7 +22,7 @@
# Project setup
########################################################################
cmake_minimum_required(VERSION 2.6)
project(gr-gr-air-modes CXX)
project(gr-gr-air-modes CXX C)
set(gr-gr-air-modes_VERSION_MAJOR 0)
set(gr-gr-air-modes_VERSION_MINOR 0)
enable_testing()
@ -49,6 +49,8 @@ endif()
########################################################################
include(GrBoost)
find_package(PythonLibs 2)
########################################################################
# Install directories
########################################################################
@ -69,12 +71,22 @@ set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks)
########################################################################
# Find gnuradio build dependencies
########################################################################
find_package(GnuradioRuntime)
set(GR_REQUIRED_COMPONENTS RUNTIME)
find_package(Gnuradio "3.7.2" REQUIRED)
if(NOT GNURADIO_RUNTIME_FOUND)
message(FATAL_ERROR "GnuRadio Runtime required to compile gr-air-modes")
endif()
########################################################################
# Find PyZMQ bindings
########################################################################
include(GrPython)
#GR_PYTHON_CHECK_MODULE("PyZMQ" "zmq" "int(zmq.__version__.split('.')[0]) >= 13" PYZMQ_FOUND)
#if(NOT PYZMQ_FOUND)
# message(FATAL_ERROR "Python ZMQ bindings not found.")
#endif()
########################################################################
# Setup the include and linker paths
########################################################################

View File

@ -233,7 +233,9 @@ class mainwindow(QtGui.QMainWindow):
try:
import osmosdr
self.src = osmosdr.source("")
self.rates = [rate.start() for rate in self.src.get_sample_rates() if (rate.start() % 2.e6) == 0]
self.rates = [rate.start() for rate in self.src.get_sample_rates()
if ((rate.start() % 2.e6) == 0)
or (rate.start() < 4.e6 and ((rate.start()%0.2e6) == 0))]
self.antennas = ["RX"]
self.src = None
self.ui.combo_ant.setEnabled(False)
@ -263,10 +265,15 @@ class mainwindow(QtGui.QMainWindow):
#set up recommended sample rate
if len(self.rates) > 1:
if max(self.rates) > 4.e6:
recommended_rate = min(x for x in self.rates if x >= 4e6 and
max(self.rates) % x == 0)
else:
recommended_rate = max(self.rates)
if recommended_rate >= 8.e6:
self.ui.check_pmf.setChecked(True)
else:
self.ui.check_pmf.setChecked(False)
self.ui.combo_rate.setCurrentIndex(self.rates.index(recommended_rate))
################ action handlers ####################
@ -400,10 +407,10 @@ class mainwindow(QtGui.QMainWindow):
def on_quit(self):
if self.running is True:
self._relay.close()
self._radio.close()
self._relay = None
self._radio = None
self._relay.close()
self._relay = None
self._rps_timer = None
try:
self.kmlgen.done = True

View File

@ -1,56 +0,0 @@
# - Find zeromq libraries
# This module finds zeromq if it is installed and determines where the
# include files and libraries are. It also determines what the name of
# the library is. This code sets the following variables:
#
# ZEROMQ_FOUND - have the zeromq libs been found
# ZEROMQ_LIBRARIES - path to the zeromq library
# ZEROMQ_INCLUDE_DIRS - path to where zmq.h is found
# ZEROMQ_DEBUG_LIBRARIES - path to the debug library
#INCLUDE(CMakeFindFrameworks)
# Search for the zeromq framework on Apple.
#CMAKE_FIND_FRAMEWORKS(ZeroMQ)
IF(WIN32)
FIND_LIBRARY(ZEROMQ_DEBUG_LIBRARY
NAMES libzmq_d zmq_d
PATHS
${ZEROMQ_LIBRARIES}
)
ENDIF(WIN32)
FIND_LIBRARY(ZEROMQ_LIBRARY
NAMES libzmq zmq
PATHS
${ZEROMQ_LIBRARIES}
${NSCP_LIBRARYDIR}
)
# IF(ZeroMQ_FRAMEWORKS AND NOT ZEROMQ_INCLUDE_DIR)
# FOREACH(dir ${ZeroMQ_FRAMEWORKS})
# SET(ZEROMQ_FRAMEWORK_INCLUDES ${ZEROMQ_FRAMEWORK_INCLUDES}
# ${dir}/Versions/${_CURRENT_VERSION}/include/zeromq${_CURRENT_VERSION})
# ENDFOREACH(dir)
# ENDIF(ZeroMQ_FRAMEWORKS AND NOT ZEROMQ_INCLUDE_DIR)
FIND_PATH(ZEROMQ_INCLUDE_DIR
NAMES zmq.hpp
PATHS
# ${ZEROMQ_FRAMEWORK_INCLUDES}
${ZEROMQ_INCLUDE_DIRS}
${NSCP_INCLUDEDIR}
${ZEROMQ_INCLUDE_DIR}
)
MARK_AS_ADVANCED(
ZEROMQ_DEBUG_LIBRARY
ZEROMQ_LIBRARY
ZEROMQ_INCLUDE_DIR
)
SET(ZEROMQ_INCLUDE_DIRS "${ZEROMQ_INCLUDE_DIR}")
SET(ZEROMQ_LIBRARIES "${ZEROMQ_LIBRARY}")
SET(ZEROMQ_DEBUG_LIBRARIES "${ZEROMQ_DEBUG_LIBRARY}")
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZeroMQ DEFAULT_MSG ZEROMQ_LIBRARIES ZEROMQ_INCLUDE_DIRS)

View File

@ -37,11 +37,11 @@ class AIR_MODES_API preamble : virtual public gr::block
{
public:
typedef boost::shared_ptr<preamble> sptr;
static sptr make(int channel_rate, float threshold_db);
static sptr make(float channel_rate, float threshold_db);
virtual void set_rate(int channel_rate) = 0;
virtual void set_rate(float channel_rate) = 0;
virtual void set_threshold(float threshold_db) = 0;
virtual int get_rate(void) = 0;
virtual float get_rate(void) = 0;
virtual float get_threshold(void) = 0;
};

View File

@ -34,11 +34,11 @@
namespace gr {
air_modes::preamble::sptr air_modes::preamble::make(int channel_rate, float threshold_db) {
air_modes::preamble::sptr air_modes::preamble::make(float channel_rate, float threshold_db) {
return gnuradio::get_initial_sptr(new air_modes::preamble_impl(channel_rate, threshold_db));
}
air_modes::preamble_impl::preamble_impl(int channel_rate, float threshold_db) :
air_modes::preamble_impl::preamble_impl(float channel_rate, float threshold_db) :
gr::block ("preamble",
gr::io_signature::make2 (2, 2, sizeof(float), sizeof(float)), //stream 0 is received data, stream 1 is moving average for reference
gr::io_signature::make (1, 1, sizeof(float))) //the output soft symbols
@ -53,11 +53,11 @@ air_modes::preamble_impl::preamble_impl(int channel_rate, float threshold_db) :
d_key = pmt::string_to_symbol("preamble_found");
}
void air_modes::preamble_impl::set_rate(int channel_rate) {
void air_modes::preamble_impl::set_rate(float channel_rate) {
d_samples_per_chip = channel_rate / d_chip_rate;
d_samples_per_symbol = d_samples_per_chip * 2;
d_check_width = 120 * d_samples_per_symbol;
d_secs_per_sample = 1.0/channel_rate;
d_sample_rate = channel_rate;
set_output_multiple(1+d_check_width*2);
set_history(d_samples_per_symbol);
}
@ -71,8 +71,8 @@ float air_modes::preamble_impl::get_threshold(void) {
return d_threshold_db;
}
int air_modes::preamble_impl::get_rate(void) {
return d_samples_per_chip * d_chip_rate;
float air_modes::preamble_impl::get_rate(void) {
return d_sample_rate;
}
static void integrate_and_dump(float *out, const float *in, int chips, int samps_per_chip) {
@ -97,19 +97,42 @@ static double correlate_preamble(const float *in, int samples_per_chip) {
return corr;
}
//todo: make it return a pair of some kind, otherwise you can lose precision
static double tag_to_timestamp(gr::tag_t tstamp, uint64_t abs_sample_cnt, double secs_per_sample) {
uint64_t ts_sample, last_whole_stamp;
static pmt::pmt_t tag_to_timestamp(gr::tag_t tstamp, uint64_t abs_sample_cnt, int rate) {
uint64_t last_whole_stamp;
double last_frac_stamp;
if(tstamp.key == NULL || pmt::symbol_to_string(tstamp.key) != "rx_time") return 0;
pmt::pmt_t tstime = pmt::make_tuple(pmt::from_uint64(0), pmt::from_double(0));
if(tstamp.key == NULL
|| !pmt::is_symbol(tstamp.key)
|| pmt::symbol_to_string(tstamp.key) != "rx_time") {
last_whole_stamp = 0;
last_frac_stamp = 0;
} else {
last_whole_stamp = pmt::to_uint64(pmt::tuple_ref(tstamp.value, 0));
last_frac_stamp = pmt::to_double(pmt::tuple_ref(tstamp.value, 1));
ts_sample = tstamp.offset;
}
//the timestamp tag has tstamp.offset, the sample index of the timestamp tag
//also tstamp.value, a pmt pair with (uint64, double) representing int and
//fractional timestamp, respectively.
//this function also gets an abs_sample_cnt which represents the sample count to
//find a timestamp for. sps is obviously samples per second.
//
//so (abs_sample_cnt - tstamp.offset) is the delay we apply to the tag
// int((abs_sample_cnt - tstamp.offset)/sps) is the integer offset
// (abs_sample_cnt - tstamp.offset)/sps is the fractional offset
uint64_t int_offset = int(abs_sample_cnt - tstamp.offset)/rate;
double frac_offset = ((abs_sample_cnt - tstamp.offset) % rate) / double(rate);
uint64_t abs_whole = last_whole_stamp + int_offset;
double abs_frac = last_frac_stamp + frac_offset;
if(abs_frac > 1.0f) {
abs_frac -= 1.0f;
abs_whole += 1;
}
tstime = pmt::make_tuple(pmt::from_uint64(abs_whole), pmt::from_double(abs_frac));
double tstime = double(abs_sample_cnt * secs_per_sample) + last_whole_stamp + last_frac_stamp;
if(0) std::cout << "HEY WE GOT A STAMP AT " << tstime << " TICKS AT SAMPLE " << ts_sample << " ABS SAMPLE CNT IS " << abs_sample_cnt << std::endl;
return tstime;
}
@ -124,7 +147,7 @@ int air_modes::preamble_impl::general_work(int noutput_items,
int mininputs = std::min(ninput_items[0], ninput_items[1]); //they should be matched but let's be safe
//round number of input samples down to nearest d_samples_per_chip
//we also subtract off d_samples_per_chip to allow the bit center finder some leeway
const int ninputs = std::max(mininputs - (mininputs % d_samples_per_chip) - d_samples_per_chip, 0);
const int ninputs = std::max(mininputs - (mininputs % int(d_samples_per_chip)) - int(d_samples_per_chip), 0);
if (ninputs <= 0) { consume_each(0); return 0; }
float *out = (float *) output_items[0];
@ -194,22 +217,20 @@ int air_modes::preamble_impl::general_work(int noutput_items,
//all right i'm prepared to call this a preamble
for(int j=0; j<240; j++) {
out[j] = in[i+j*d_samples_per_chip] - inavg[i];
out[j] = in[i+int(j*d_samples_per_chip)] - inavg[i];
}
//get the timestamp of the preamble
double tstamp = tag_to_timestamp(d_timestamp, abs_sample_cnt + i, d_secs_per_sample);
pmt::pmt_t tstamp = tag_to_timestamp(d_timestamp, abs_sample_cnt + i, d_sample_rate);
//now tag the preamble
add_item_tag(0, //stream ID
nitems_written(0), //sample
d_key, //frame_info
pmt::from_double(tstamp),
tstamp,
d_me //block src id
);
//std::cout << "PREAMBLE" << std::endl;
//produce only one output per work call -- TODO this should probably change
if(0) std::cout << "Preamble consumed " << i+240*d_samples_per_chip << "with i=" << i << ", returned 240" << std::endl;

View File

@ -15,26 +15,26 @@ private:
int d_check_width;
int d_chip_rate;
float d_preamble_length_us;
int d_samples_per_chip;
int d_samples_per_symbol;
float d_samples_per_chip;
float d_samples_per_symbol;
float d_threshold_db;
float d_threshold;
pmt::pmt_t d_me, d_key;
gr::tag_t d_timestamp;
double d_secs_per_sample;
pmt::pmt_t d_me, d_key;
int d_sample_rate;
public:
preamble_impl(int channel_rate, float threshold_db);
preamble_impl(float channel_rate, float threshold_db);
int general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
void set_rate(int channel_rate);
void set_rate(float channel_rate);
void set_threshold(float threshold_db);
float get_threshold(void);
int get_rate(void);
float get_rate(void);
};
} //namespace air_modes

View File

@ -158,8 +158,6 @@ int air_modes::slicer_impl::work(int noutput_items,
}
}
rx_packet.timestamp = pmt::to_double(tag_iter->value);
//here you might want to traverse the whole packet and if you find all 0's, just toss it. don't know why these packets turn up, but they pass ECC.
bool zeroes = 1;
for(int m = 0; m < 14; m++) {
@ -183,13 +181,15 @@ int air_modes::slicer_impl::work(int noutput_items,
//crc for the other short packets is usually nonzero, so they can't really be trusted that far
if(rx_packet.crc && (rx_packet.message_type == 11 || rx_packet.message_type == 17)) {continue;}
pmt::pmt_t tstamp = tag_iter->value;
d_payload.str("");
for(int m = 0; m < packet_length/8; m++) {
d_payload << std::hex << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]);
}
d_payload << " " << std::setw(6) << rx_packet.crc << " " << std::dec << rx_packet.reference_level
<< " " << std::setprecision(10) << std::setw(10) << rx_packet.timestamp;
<< " " << pmt::to_uint64(pmt::tuple_ref(tstamp, 0)) << " " << std::setprecision(10) << pmt::to_double(pmt::tuple_ref(tstamp, 1));
gr::message::sptr msg = gr::message::make_from_string(std::string(d_payload.str()));
d_queue->handle(msg);
}

View File

@ -38,6 +38,7 @@ private:
int d_chip_rate;
int d_samples_per_chip;
int d_samples_per_symbol;
gr::tag_t d_timestamp;
gr::msg_queue::sptr d_queue;
std::ostringstream d_payload;

View File

@ -51,6 +51,12 @@ from air_modes_swig import *
# import any pure python here
#
try:
import zmq
except ImportError:
raise RuntimeError("PyZMQ not found! Please install libzmq and PyZMQ to run gr-air-modes")
from rx_path import rx_path
from zmq_socket import zmq_pubsub_iface
from parse import *

View File

@ -18,7 +18,6 @@ class output_flightgear:
def __init__(self, cprdec, hostname, port, pub):
self.hostname = hostname
self.port = port
self.localpos = localpos
self.positions = {}
self.velocities = {}
self.callsigns = {}
@ -26,36 +25,35 @@ class output_flightgear:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.connect((self.hostname, self.port))
pub.subscribe("type17_dl", output)
pub.subscribe("type17_dl", self.output)
def output(self, msg):
try:
msgtype = msg.data["df"]
if msgtype == 17: #ADS-B report
icao24 = msg.data["aa"]
bdsreg = msg.data["me"].get_type()
if bdsreg == 0x08: #ident packet
(ident, actype) = air_modes.parseBDS08(data)
(ident, actype) = air_modes.parseBDS08(msg.data)
#select model based on actype
self.callsigns[icao24] = [ident, actype]
elif bdsreg == 0x06: #BDS0,6 pos
[ground_track, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS06(data, self._cpr)
[ground_track, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS06(msg.data, self._cpr)
self.positions[icao24] = [decoded_lat, decoded_lon, 0]
self.update(icao24)
elif bdsreg == 0x05: #BDS0,5 pos
[altitude, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS05(data, self._cpr)
[altitude, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS05(msg.data, self._cpr)
self.positions[icao24] = [decoded_lat, decoded_lon, altitude]
self.update(icao24)
elif bdsreg == 0x09: #velocity
subtype = data["bds09"].get_type()
subtype = msg.data["bds09"].get_type()
if subtype == 0:
[velocity, heading, vert_spd, turnrate] = air_modes.parseBDS09_0(data)
[velocity, heading, vert_spd, turnrate] = air_modes.parseBDS09_0(msg.data)
elif subtype == 1:
[velocity, heading, vert_spd] = air_modes.parseBDS09_1(data)
[velocity, heading, vert_spd] = air_modes.parseBDS09_1(msg.data)
turnrate = 0
else:
return

View File

@ -53,7 +53,6 @@ def html_template(my_position, json_file):
};
function jsonp_callback(results) { // from JSONP
clearMarkers();
airplanes = {};
for (var i = 0; i < results.length; i++) {
airplanes[results[i].icao] = {
@ -67,10 +66,20 @@ def html_template(my_position, json_file):
highlight: results[i].highlight
};
}
// clearMarkers();
refreshIcons();
}
function refreshIcons() {
//prune the list
for(var i = 0; i < planes.length; i++) {
icao = planes[i].get("icao")
if(!(icao in airplanes)) {
planes[i].setMap(null)
planes.splice(i, 1);
};
};
for (var airplane in airplanes) {
if (airplanes[airplane].highlight != 0) {
icon_file = "http://www.nerdnetworks.org/~bistromath/airplane_sprite_highlight.png";
@ -94,16 +103,33 @@ def html_template(my_position, json_file):
var planeOptions = {
map: map,
position: airplanes[airplane].center,
icao: airplane,
icon: plane_icon,
labelContent: identstr,
labelAnchor: new google.maps.Point(35, -32),
labelClass: "labels",
labelStyle: {opacity: 0.75}
};
var i = 0;
for(i; i<planes.length; i++) {
if(planes[i].get("icao") == airplane) {
planes[i].setPosition(airplanes[airplane].center);
if(planes[i].get("icon") != plane_icon) {
planes[i].setIcon(plane_icon); //handles highlight and heading
};
if(planes[i].get("labelContent") != identstr) {
planes[i].set("labelContent", identstr);
};
break;
};
};
if(i == planes.length) {
planeMarker = new MarkerWithLabel(planeOptions);
planes.push(planeMarker);
};
};
};
function initialize()
{

View File

@ -335,8 +335,8 @@ def parseBDS09_1(data):
ew = bool(data["dew"])
subtype = data["sub"]
if subtype == 0x02:
ns_vel <<= 2
ew_vel <<= 2
ns_vel *= 4
ew_vel *= 4
velocity = math.hypot(ns_vel, ew_vel)
if ew:
@ -423,12 +423,12 @@ def parse_TCAS_CRM(data):
def make_parser(pub):
publisher = pub
def publish(message):
[data, ecc, reference, timestamp] = message.split()
[data, ecc, reference, int_timestamp, frac_timestamp] = message.split()
try:
ret = air_modes.modes_report(modes_reply(int(data, 16)),
int(ecc, 16),
10.0*math.log10(max(1e-8,float(reference))),
air_modes.stamp(0, float(timestamp)))
air_modes.stamp(int(int_timestamp), float(frac_timestamp)))
pub["modes_dl"] = ret
pub["type%i_dl" % ret.data.get_type()] = ret
except ADSBError:

View File

@ -27,6 +27,7 @@ from gnuradio import gr, gru, eng_notation, filter, blocks
from gnuradio.filter import optfir
from gnuradio.eng_option import eng_option
from gnuradio.gr.pubsub import pubsub
from gnuradio.filter import pfb
from optparse import OptionParser, OptionGroup
import air_modes
import zmq
@ -45,9 +46,16 @@ class modes_radio (gr.top_block, pubsub):
self._resample = None
self._setup_source(options)
self._rx_path = air_modes.rx_path(self._rate, options.threshold,
if self._rate < 4e6:
self._resample = pfb.arb_resampler_ccf(4.e6/self._rate)
self._rx_rate = 4e6
else:
self._rx_rate = self._rate
self._rx_path = air_modes.rx_path(self._rx_rate, options.threshold,
self._queue, options.pmf, options.dcblock)
#now subscribe to set various options via pubsub
self.subscribe("freq", self.set_freq)
self.subscribe("gain", self.set_gain)
@ -125,8 +133,20 @@ class modes_radio (gr.top_block, pubsub):
return self.get_gain()
def set_rate(self, rate):
self._rx_path.set_rate(rate)
return self._u.set_rate(rate) if self.live_source() else 0
if(rate < 4e6 and self._rate > 4e6):
raise NotImplementedError("Lowering rate <4e6Msps not currently supported.")
if(rate < 4e6):
self._resample.set_rate(4e6/rate)
self._rx_rate = 4e6
else:
self._rx_rate = rate
self._rx_path.set_rate(self._rx_rate)
if self._options.source in ("osmocom"):
return self._u.set_sample_rate(rate)
if self._options.source in ("uhd"):
return self._u.set_rate(rate)
else:
return 0
def set_threshold(self, threshold):
self._rx_path.set_threshold(threshold)
@ -199,7 +219,7 @@ class modes_radio (gr.top_block, pubsub):
ip, port = re.search("(.*)\:(\d{1,5})", options.source).groups()
except:
raise Exception("Please input UDP source e.g. 192.168.10.1:12345")
self._u = gr.udp_source(gr.sizeof_gr_complex, ip, int(port))
self._u = blocks.udp_source(gr.sizeof_gr_complex, ip, int(port))
print "Using UDP source %s:%s" % (ip, port)
else:
self._u = blocks.file_source(gr.sizeof_gr_complex, options.source)
@ -208,5 +228,7 @@ class modes_radio (gr.top_block, pubsub):
print "Rate is %i" % (options.rate,)
def close(self):
self.stop()
self.wait()
self._sender.close()
self._u = None

View File

@ -37,7 +37,7 @@ class rx_path(gr.hier_block2):
# Convert incoming I/Q baseband to amplitude
self._demod = blocks.complex_to_mag_squared()
if use_dcblock:
self._dcblock = filter.dc_blocker_cc(100*self._spc,True)
self._dcblock = filter.dc_blocker_cc(100*self._spc,False)
self.connect(self, self._dcblock, self._demod)
else:
self.connect(self, self._demod)
@ -65,13 +65,13 @@ class rx_path(gr.hier_block2):
self.connect(self._sync, self._slicer)
def set_rate(self, rate):
self._sync.set_rate(rate)
self._sync.set_rate(int(rate))
self._spc = int(rate/2e6)
self._avg.set_length_and_scale(48*self._spc, 1.0/(48*self._spc))
if self._bb != self._demod:
self._pmf.set_length_and_scale(self._spc, 1.0/self._spc)
if self._dcblock is not None:
self._dcblock.set_length(100*self._spc)
# if self._dcblock is not None:
# self._dcblock.set_length(100*self._spc)
def set_threshold(self, threshold):
self._sync.set_threshold(threshold)

View File

@ -23,7 +23,7 @@
import time, os, sys, socket
from string import split, join
import air_modes
from datetime import *
import datetime
from air_modes.exceptions import *
import threading
@ -63,7 +63,7 @@ class output_sbs1:
#it could be cleaner if there were separate output_* fns
#but this works
for i in (0, 4, 5, 11, 17):
pub.subscribe("type%i_dl" % i, output)
pub.subscribe("type%i_dl" % i, self.output)
#spawn thread to add new connections as they come in
self._runner = dumb_task_runner(self.add_pending_conns, 0.1)
@ -83,7 +83,7 @@ class output_sbs1:
# dictionary is getting too large.
if len(self._aircraft_id_map) > 1e4:
minimum = min(self._aircraft_id_map.values()) + (len(self._aircraft_id_map) - 1e4)
for icao, _id in self._aircraft_id_map:
for icao, _id in dict(self._aircraft_id_map).iteritems():
if _id < minimum:
del self._aircraft_id_map[icao]
@ -111,7 +111,7 @@ class output_sbs1:
pass
def current_time(self):
timenow = datetime.now()
timenow = datetime.datetime.now()
return [timenow.strftime("%Y/%m/%d"), timenow.strftime("%H:%M:%S.%f")[0:-3]]
def decode_fs(self, fs):
@ -154,7 +154,7 @@ class output_sbs1:
[datestr, timestr] = self.current_time()
aircraft_id = self.get_aircraft_id(ecc)
retstr = "MSG,7,0,%i,%06X,%i,%s,%s,%s,%s,,%s,,,,,,,,,," % (aircraft_id, ecc, aircraft_id+100, datestr, timestr, datestr, timestr, air_modes.decode_alt(shortdata["ac"], True))
if vs:
if shortdata["vs"]:
retstr += "1\r\n"
else:
retstr += "0\r\n"
@ -174,7 +174,7 @@ class output_sbs1:
def pp11(self, shortdata, ecc):
[datestr, timestr] = self.current_time()
aircraft_id = self.get_aircraft_id(icao24)
aircraft_id = self.get_aircraft_id(shortdata["aa"])
return "MSG,8,0,%i,%06X,%i,%s,%s,%s,%s,,,,,,,,,,,,\r\n" % (aircraft_id, shortdata["aa"], aircraft_id+100, datestr, timestr, datestr, timestr)
def pp17(self, data):