# Path: mlat/geodesy.py
# WGS84_A = 6378137.0
# WGS84_F = 1.0/298.257223563
# WGS84_B = WGS84_A * (1 - WGS84_F)
# WGS84_ECC_SQ = 1 - WGS84_B * WGS84_B / (WGS84_A * WGS84_A)
# WGS84_ECC = math.sqrt(WGS84_ECC_SQ)
# SPHERICAL_R = 6371e3
#     N = WGS84_A / math.sqrt(1 - WGS84_ECC_SQ * math.sin(lat)**2)
# def llh2ecef(llh):
# def ecef2llh(ecef):
# def greatcircle(p0, p1):
# def ecef_distance(p0, p1):
# 
# Path: mlat/profile.py
# def trackcpu(f, **kwargs):
# def dump_cpu_profiles(tofile=None):
# def trackcpu(f, name=None, **kwargs):
#     def cpu_measurement_wrapper(*args, **kwargs):
# def dump_cpu_profiles(tofile=sys.stderr):
# 
# Path: mlat/server/clocksync.py
# class Clock(object):
# class ClockPairing(object):
#     def __init__(self, epoch, freq, max_freq_error, jitter):
# def make_clock(clock_type):
#     def __init__(self, base, peer):
#     def is_new(self, base_ts):
#     def variance(self):
#     def error(self):
#     def valid(self):
#     def update(self, address, base_ts, peer_ts, base_interval, peer_interval):
#     def _prune_old_data(self, latest_base_ts):
#     def _update_drift(self, address, base_interval, peer_interval):
#     def _update_offset(self, address, base_ts, peer_ts, prediction_error):
#     def predict_peer(self, base_ts):
#     def predict_base(self, peer_ts):
#     def __str__(self):
#     KP = 0.05
#     KI = 0.01
# 
# Path: mlat/server/config.py
# MIN_NUC = 6
# MAX_RANGE = 500e3
# MAX_INTERMESSAGE_RANGE = 10e3
# MAX_ALT = 50000 * constants.FTOM
# MLAT_DELAY = 2.5
# SOLVER_MAXFEV = 50


import asyncio
import functools
import time
import logging
import modes.message
from mlat import geodesy, constants, profile
from mlat.server import clocksync, config
        interval: the nominal interval (in seconds)
          between the two messages; this is as measured by
          the first receiver to report the pair, and is used
          to distinguish cases where the same message is
          transmitted more than once.
        """

        self.address = address
        self.posA = posA
        self.posB = posB
        self.interval = interval
        self.receivers = []  # a list of (receiver, timestampA, timestampB) values


class ClockTracker(object):
    """Maintains clock pairings between receivers, and matches up incoming sync messages
    from receivers to update the parameters of the pairings."""

    def __init__(self):
        # map of (sync key) -> list of sync points
        #
        # sync key is a pair of bytearrays: (msgA, msgB)
        # where msgA and msgB are the contents of the
        # earlier and later message of the pair respectively.
        self.sync_points = {}

        # map of (pair key) -> pairing
        #
        # pair key is (receiver 0, receiver 1) where receiver 0
        # is always less than receiver 1.

# Path: mlat/geodesy.py
# WGS84_A = 6378137.0
# WGS84_F = 1.0/298.257223563
# WGS84_B = WGS84_A * (1 - WGS84_F)
# WGS84_ECC_SQ = 1 - WGS84_B * WGS84_B / (WGS84_A * WGS84_A)
# WGS84_ECC = math.sqrt(WGS84_ECC_SQ)
# SPHERICAL_R = 6371e3
#     N = WGS84_A / math.sqrt(1 - WGS84_ECC_SQ * math.sin(lat)**2)
# def llh2ecef(llh):
# def ecef2llh(ecef):
# def greatcircle(p0, p1):
# def ecef_distance(p0, p1):
# 
# Path: mlat/profile.py
# def trackcpu(f, **kwargs):
# def dump_cpu_profiles(tofile=None):
# def trackcpu(f, name=None, **kwargs):
#     def cpu_measurement_wrapper(*args, **kwargs):
# def dump_cpu_profiles(tofile=sys.stderr):
# 
# Path: mlat/server/clocksync.py
# class Clock(object):
# class ClockPairing(object):
#     def __init__(self, epoch, freq, max_freq_error, jitter):
# def make_clock(clock_type):
#     def __init__(self, base, peer):
#     def is_new(self, base_ts):
#     def variance(self):
#     def error(self):
#     def valid(self):
#     def update(self, address, base_ts, peer_ts, base_interval, peer_interval):
#     def _prune_old_data(self, latest_base_ts):
#     def _update_drift(self, address, base_interval, peer_interval):
#     def _update_offset(self, address, base_ts, peer_ts, prediction_error):
#     def predict_peer(self, base_ts):
#     def predict_base(self, peer_ts):
#     def __str__(self):
#     KP = 0.05
#     KI = 0.01
# 
# Path: mlat/server/config.py
# MIN_NUC = 6
# MAX_RANGE = 500e3
# MAX_INTERMESSAGE_RANGE = 10e3
# MAX_ALT = 50000 * constants.FTOM
# MLAT_DELAY = 2.5
# SOLVER_MAXFEV = 50


# Path: mlat/server/clocktrack.py
import asyncio
import functools
import time
import logging
import modes.message
from mlat import geodesy, constants, profile
from mlat.server import clocksync, config

        interval: the nominal interval (in seconds)
          between the two messages; this is as measured by
          the first receiver to report the pair, and is used
          to distinguish cases where the same message is
          transmitted more than once.
        """

        self.address = address
        self.posA = posA
        self.posB = posB
        self.interval = interval
        self.receivers = []  # a list of (receiver, timestampA, timestampB) values


class ClockTracker(object):
    """Maintains clock pairings between receivers, and matches up incoming sync messages
    from receivers to update the parameters of the pairings."""

    def __init__(self):
        # map of (sync key) -> list of sync points
        #
        # sync key is a pair of bytearrays: (msgA, msgB)
        # where msgA and msgB are the contents of the
        # earlier and later message of the pair respectively.
        self.sync_points = {}

        # map of (pair key) -> pairing
        #
        # pair key is (receiver 0, receiver 1) where receiver 0
        # is always less than receiver 1.

        self.clock_pairs = {}