Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions mlat-client
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ import mlat.client.version

from mlat.client.util import log
from mlat.client.receiver import ReceiverConnection
from mlat.client.receiver_mirror import ReceiverConnectionMirror
from mlat.client.mirror import MirrorReceiverConnection
from mlat.client.jsonclient import JsonServerConnection
from mlat.client.coordinator import Coordinator
from mlat.client.coordinator_mirror import CoordinatorMirror
from mlat.client import options


Expand Down Expand Up @@ -65,6 +68,9 @@ location pin from the coverage maps.""",
help="host:port of the multilateration server to connect to",
type=options.hostport,
default=('mlat.mutability.co.uk', 40147))
server.add_argument('--mirror_server',
help="host:port for mirrored traffic",
type=options.hostport)
server.add_argument('--no-udp',
dest='udp',
help="Don't offer to use UDP transport for sync/mlat messages",
Expand All @@ -77,8 +83,6 @@ location pin from the coverage maps.""",

outputs = options.build_outputs(args)

receiver = ReceiverConnection(host=args.input_connect[0], port=args.input_connect[1],
mode=options.connection_mode(args))
server = JsonServerConnection(host=args.server[0], port=args.server[1],
handshake_data={'lat': args.lat,
'lon': args.lon,
Expand All @@ -92,8 +96,20 @@ location pin from the coverage maps.""",
offer_udp=args.udp,
return_results=(len(outputs) > 0))

coordinator = Coordinator(receiver=receiver, server=server, outputs=outputs, freq=options.clock_frequency(args),
allow_anon=args.allow_anon_results, allow_modeac=args.allow_modeac_results)
if args.mirror_server is not None:

mirror_receiver = MirrorReceiverConnection(host=args.mirror_server[0], port=args.mirror_server[1])

receiver = ReceiverConnectionMirror(host=args.input_connect[0], port=args.input_connect[1],
mode=options.connection_mode(args))

coordinator = CoordinatorMirror(receiver=receiver, mirror_receiver=mirror_receiver, server=server, outputs=outputs, freq=options.clock_frequency(args),
allow_anon=args.allow_anon_results, allow_modeac=args.allow_modeac_results)
else:
receiver = ReceiverConnection(host=args.input_connect[0], port=args.input_connect[1],
mode=options.connection_mode(args))
coordinator = Coordinator(receiver=receiver, server=server, outputs=outputs, freq=options.clock_frequency(args),
allow_anon=args.allow_anon_results, allow_modeac=args.allow_modeac_results)

server.start()
coordinator.run_forever()
Expand Down
71 changes: 71 additions & 0 deletions mlat/client/coordinator_mirror.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# -*- mode: python; indent-tabs-mode: nil -*-

# Part of mlat-client - an ADS-B multilateration client.
# Copyright 2015, Oliver Jowett <oliver@mutability.co.uk>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""
Core of the client: track aircraft and send data to the server as needed - mirror server version.
"""

import asyncore
import time

import _modes
import mlat.profile
from mlat.client.util import monotonic_time, log
from mlat.client.stats import global_stats
from mlat.client.coordinator import Coordinator

class CoordinatorMirror(Coordinator):

def __init__(self, receiver, mirror_receiver, server, outputs, freq, allow_anon, allow_modeac):
super().__init__(receiver, server, outputs, freq, allow_anon, allow_modeac)

self.mirror_receiver = mirror_receiver
mirror_receiver.coordinator = self

# internals

def run_until(self, termination_condition):
try:
super().run_until(termination_condition)
finally:
self.mirror_receiver.disconnect('Client mirror shutting down')

def heartbeat(self, now):
self.mirror_receiver.heartbeat(now)
super().heartbeat(now)

def periodic_stats(self, now):
super().periodic_stats(now)
log('Mirror receiver status: {0}', self.mirror_receiver.state)

# callbacks from server connection

def server_connected(self):
super().server_connected()
if self.mirror_receiver.state != 'ready':
self.mirror_receiver.reconnect()

def server_disconnected(self):
super().server_disconnected()
self.mirror_receiver.disconnect('Lost connection to multilateration server, no need for input data')

@mlat.profile.trackcpu

def copy_received_messages(self, messages):
# self.mirror_receiver.send_to_mirror(messages)
self.mirror_receiver.send(messages)
49 changes: 49 additions & 0 deletions mlat/client/mirror.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# -*- mode: python; indent-tabs-mode: nil -*-

# Part of mlat-client - an ADS-B multilateration client.
# Copyright 2015, Oliver Jowett <oliver@mutability.co.uk>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""
Copy received Mode S messages to mirror server.
"""

import socket
import errno

import _modes
import mlat.profile
from mlat.client.stats import global_stats
from mlat.client.net import ReconnectingConnection
from mlat.client.util import log, monotonic_time

class MirrorReceiverConnection(ReconnectingConnection):
reconnect_interval = 15.0

def __init__(self, host, port):
ReconnectingConnection.__init__(self, host, port)
self.reset_connection()

@mlat.profile.trackcpu

def start_connection(self):
log('Mirror connected to {0}:{1}', self.host, self.port)
self.state = 'connected'


"""
def send_to_mirror(self,messages):
self.send(messages)
"""
94 changes: 94 additions & 0 deletions mlat/client/receiver_mirror.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# -*- mode: python; indent-tabs-mode: nil -*-

# Part of mlat-client - an ADS-B multilateration client.
# Copyright 2015, Oliver Jowett <oliver@mutability.co.uk>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""
Handles receiving Mode S messages from receivers using various formats - mirror server version.
"""

import socket
import errno

import _modes
import mlat.profile
from mlat.client.stats import global_stats
from mlat.client.net import ReconnectingConnection
from mlat.client.util import log, monotonic_time
from mlat.client.receiver import ReceiverConnection

class ReceiverConnectionMirror(ReceiverConnection):

def __init__(self, host, port, mode):
super().__init__(host, port, mode)
self.mirror_receiver = None

@mlat.profile.trackcpu
def handle_read(self):
try:
moredata = self.recv(16384)
except socket.error as e:
if e.errno == errno.EAGAIN:
return
raise

if not moredata:
self.close()
return

global_stats.receiver_rx_bytes += len(moredata)

self.coordinator.copy_received_messages(moredata)

if self.residual:
moredata = self.residual + moredata

self.last_data_received = monotonic_time()

try:
consumed, messages, pending_error = self.feed(moredata)
except ValueError as e:
log("Parsing receiver data failed: {e}", e=str(e))
self.reconnect_interval = 5.0
self.close()
return

if consumed < len(moredata):
self.residual = moredata[consumed:]
if len(self.residual) > 5120:
raise RuntimeError('parser broken - buffer not being consumed')
else:
self.residual = None

global_stats.receiver_rx_messages += self.reader.received_messages
global_stats.receiver_rx_filtered += self.reader.suppressed_messages
self.reader.received_messages = self.reader.suppressed_messages = 0

if messages:
self.coordinator.input_received_messages(messages)

if pending_error:
# call it again to get the exception
# now that we've handled all the messages
try:
if self.residual is None:
self.feed(b'')
else:
self.feed(self.residual)
except ValueError as e:
log("Parsing receiver data failed: {e}", e=str(e))
self.close()
return