From c389f3ec24ceba0c9f6390b28523a6f576e79cc6 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Fri, 11 Mar 2016 14:37:47 -0800 Subject: [PATCH] Convert check_mhz into sourcestats, using --exec-send, doing multi-source statistics --- python/adsblib.py | 9 --- python/check_mhz.py | 44 ------------ {python => sinks/sourcestats}/.gitignore | 0 sinks/sourcestats/sourcestats.py | 91 ++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 53 deletions(-) delete mode 100644 python/adsblib.py delete mode 100755 python/check_mhz.py rename {python => sinks/sourcestats}/.gitignore (100%) create mode 100755 sinks/sourcestats/sourcestats.py diff --git a/python/adsblib.py b/python/adsblib.py deleted file mode 100644 index 81f72eb..0000000 --- a/python/adsblib.py +++ /dev/null @@ -1,9 +0,0 @@ -import json -import socket - - -def GetEvents(host, port): - with socket.create_connection((host, port)) as sock: - fh = sock.makefile() - for line in fh: - yield json.loads(line) diff --git a/python/check_mhz.py b/python/check_mhz.py deleted file mode 100755 index 4d270df..0000000 --- a/python/check_mhz.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/python3 - -import sys -import time - -import adsblib - - -if len(sys.argv) != 3: - print('Usage: %s ' % sys.argv[0]) - -print('Fetching samples...') - -advertised_mhz = None -start_time = None -start_timestamp = None -last_timestamp = None -for i, event in enumerate(adsblib.GetEvents(sys.argv[1], sys.argv[2])): - advertised_mhz = event.get('mlat_timestamp_mhz', advertised_mhz) - - if 'mlat_timestamp' not in event: - continue - - if not start_time: - start_time = time.time() - start_timestamp = event['mlat_timestamp'] - - if last_timestamp: - if event['mlat_timestamp'] < last_timestamp: - print('\rERROR: timestamp went backwards (%d -> %d)\x1b[K' % - (last_timestamp, event['mlat_timestamp'])) - - last_timestamp = event['mlat_timestamp'] - - if i % 1000 == 0 and start_time and advertised_mhz: - time_diff = time.time() - start_time - value_diff = event['mlat_timestamp'] - start_timestamp - measured_mhz = value_diff / time_diff / 1000000 - print( - '\r%d samples, %d seconds, advertised: %d MHz, measured: %d MHz\x1b[K' % - (i, time_diff, advertised_mhz, measured_mhz), - end='', flush=True) - -print() diff --git a/python/.gitignore b/sinks/sourcestats/.gitignore similarity index 100% rename from python/.gitignore rename to sinks/sourcestats/.gitignore diff --git a/sinks/sourcestats/sourcestats.py b/sinks/sourcestats/sourcestats.py new file mode 100755 index 0000000..a91ef71 --- /dev/null +++ b/sinks/sourcestats/sourcestats.py @@ -0,0 +1,91 @@ +#!/usr/bin/python3 -u + +import collections +import fileinput +import json +import sys +import threading +import time + + +def Log(s): + print('{sourcestats} %s' % s, file=sys.stderr, flush=True) + + +class Source(object): + _first_event = None + + def __init__(self): + self._count_by_type = collections.defaultdict(int) + + def HandleEvent(self, event): + now = time.clock_gettime(time.CLOCK_MONOTONIC) + if not self._first_event: + self._first_event = event + self._first_event_timestamp = now + self._last_event = event + self._last_event_timestamp = now + self._count_by_type[event['type']] += 1 + + def _GetDuration(self): + return self._last_event_timestamp - self._first_event_timestamp + + def GetTypeRate(self, t): + return self._count_by_type[t] / self._GetDuration() + + def GetHz(self): + ticks = self._last_event['mlat_timestamp'] - self._first_event['mlat_timestamp'] + return ticks / self._GetDuration() + + +class Reader(object): + def __init__(self): + self._sources = collections.defaultdict(Source) + self._input = fileinput.input() + self._LogStats() + + def _GetEvents(self): + for line in self._input: + yield json.loads(line) + + def _HandleHeader(self, event): + self._config = event + + def _LogStats(self): + data = [ + ('Source ID', 'Mode-AC', 'Mode-S short', 'Mode-S long', 'Clock rate'), + ] + + for source_id, source in self._sources.items(): + data.append(( + source_id, + '%.02f/s' % source.GetTypeRate('Mode-AC'), + '%.02f/s' % source.GetTypeRate('Mode-S short'), + '%.02f/s' % source.GetTypeRate('Mode-S long'), + '%.04f' % (source.GetHz() / (self._config['mlat_timestamp_mhz'] * 1000000)), + )) + + col_width = [max(len(row[i]) for row in data) + 2 for i in range(len(data[0]))] + for row in data: + Log(''.join(word.ljust(col_width[i]) for i, word in enumerate(row))) + Log('') + + self._timer = threading.Timer(60.0, self._LogStats) + self._timer.start() + + def Read(self): + for event in self._GetEvents(): + if event['type'] == 'header': + self._HandleHeader(event) + continue + source = self._sources[event['source_id']] + source.HandleEvent(event) + + +Log('Runtime data:') +Log('\tpython_version: %s' % sys.version.replace('\n', '')) +Log('') + + +reader = Reader() +reader.Read()