#!/usr/bin/env python
# coding: utf-8
import urllib2
import json
import calendar
import time
import locale
import subprocess
import shlex
import os
from random import randint
import argparse
import datetime
import tempfile
import ssl
import serial
import csv


RMBT_BIN = "rmbt"
HIST_FILE = "/tmp/netmetr-history.json"
# FALLBACK_CTRL_SRV = "netmetr-control.labs.nic.cz"
FALLBACK_CTRL_SRV = "control.netmetr.cz"
FALLBACK_MAX_HISTORY_LOGS = 10
FALLBACK_CLIENT_TYPE = "HW-PROBE"
DEBUG = None
COLORED_OUTPUT = None


class Netmetr:
    def __init__(self):
        self.language = locale.getdefaultlocale()[0]
        self.timezone = subprocess.check_output([
            "date",
            "+%Z"
        ])[:-1]

        self.control_server = uci_get("control_server")
        if not self.control_server:
            print_info("Control server not found, falling to: {}".format(FALLBACK_CTRL_SRV))
            self.control_server = FALLBACK_CTRL_SRV
            uci_set("control_server", FALLBACK_CTRL_SRV)
        self.client = uci_get("client")
        if not self.client:
            print_info("Client type not found, falling to: {}".format(FALLBACK_CLIENT_TYPE))
            self.client = FALLBACK_CLIENT_TYPE
            uci_set("client", FALLBACK_CLIENT_TYPE)

        if os.path.isfile("/etc/turris-version"):
            with open("/etc/turris-version", 'r') as turris_version:
                self.os_version = turris_version.read().split('\n')[0]
            self.hw_version = subprocess.check_output([
                "atsha204cmd",
                "hw-rev"
            ])[:-1]
            self.model = "Turris"
        else:
            self.os_version = "unknown"
            self.hw_version = "unknown"
            self.model = "default"

    def get_time(cls):
        return str(int(round(calendar.timegm(time.gmtime())*1000)))

    def send_request(self, req_json, uri):
        req = urllib2.Request(
            "https://{}/RMBTControlServer/{}".format(
                self.control_server,
                uri
            )
        )
        req.add_header('Accept', 'application/json')
        req.add_header('Content-Type', 'application/json')
        data = json.dumps(req_json)

        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
        ctx.verify_mode = ssl.CERT_REQUIRED
        ctx.set_default_verify_paths()
        # ctx.load_verify_locations("/etc/ssl/www_turris_cz_ca.pem")

        resp = urllib2.urlopen(req, data, context=ctx)

        return json.loads(resp.read())

    def load_uuid(self):
        """Checks the uci config for uuid and loads it to the
        script. If no uuid is found a https request is send to the control
        server to download it.
        """
        self.uuid = uci_get("uuid")
        if not self.uuid:
            print_info('Uuid not found, requesting new one.')
            self.uuid = 0

        # the download request must be sent all the time - either to raquest
        # new uuid or to check the existing one
        self.download_uuid()

    def download_uuid(self):
        """Creates a http request and ask the control server for correct uuid
        """
        print_progress("Checking uuid on the control server...")
        # Create json to request uuid
        req_json = {
            "uuid": self.uuid,
            "language": self.language,
            "timezone": self.timezone,
            "name": "RMBT",
            "terms_and_conditions_accepted": "true",
            "type": "DESKTOP",
            "version_code": "1",
            "version_name": "1.0",
        }

        if print_debug("Test settings request:"):
            print(json.dumps(req_json, indent=2))
        # Send the request
        resp_json = self.send_request(req_json, 'settings')
        uuid_new = resp_json["settings"][0].get("uuid", '')
        if uuid_new:  # New uuid was received
            self.uuid = uuid_new
            uci_set("uuid", self.uuid)
            uci_del("sync_code")
        else:
            self.uuid = req_json['uuid']
        if print_debug("Test settings response:"):
            print(json.dumps(resp_json, indent=2))

    def request_settings(self):
        """Creates a http request to get test token, number of threads, number
        of pings, server address and port and so on.
        """
        print_progress("Requesting test config from the control server...")
        req_json = {
            "client": "HW-PROBE",
            "language": self.language,
            "time": self.get_time(),
            "timezone": self.timezone,
            "type": "DESKTOP",
            "uuid": self.uuid,
            "version": "0.1",
            "version_code": "1"
        }
        if print_debug("Test testRequest request"):
            print(json.dumps(req_json, indent=2))

        # Send the request
        resp_json = self.send_request(req_json, 'testRequest')

        if print_debug("Test testRequest response:"):
            print(json.dumps(resp_json, indent=2))

        self.test_server_address = resp_json["test_server_address"]
        self.test_server_port = resp_json["test_server_port"]
        self.test_token = resp_json["test_token"]
        self.test_uuid = resp_json["test_uuid"]
        self.test_numthreads = resp_json["test_numthreads"]
        self.test_numpings = resp_json["test_numpings"]
        self.test_server_encryption = resp_json["test_server_encryption"]
        self.test_duration = resp_json["test_duration"]

    def measure_pings(self):
        """Run serie of pings to the test server and computes & saves
         the lowest one
        """

        print_progress("Starting ping test...")
        ping_values = list()
        for i in range(1, int(self.test_numpings)+1):
            process = subprocess.Popen([
                "ping", "-c1",
                self.test_server_address
            ], stdout=subprocess.PIPE)
            if (process.wait() == 0):
                try:
                    ping_result = process.stdout.read()
                    start = ping_result.index(b"time=") + len("time=")
                    end = ping_result.index(b" ms")
                    ping = float(ping_result[start:end])
                    print("ping_"+str(i)+"_msec = "+format(ping, '.2f'))
                    ping = int(ping * 1000000)
                    ping_values.append(ping)
                except:
                    print("Problem decoding pings.")
                    return ''
                time.sleep(0.5)
        try:
            return min(int(s) for s in ping_values)
        except:
            return ''

    def measure_speed(self):
        """Start RMBT client with saved arguments to measure the speed
        """
        # Create config file needed by rmbt-client
        _, self.config_file = tempfile.mkstemp()
        _, self.flows_file = tempfile.mkstemp()
        try:
            with open(self.config_file, "w") as config_file:
                config_file.write(
                        '{"cnf_file_flows": "'+self.flows_file+'.xz"}'
                )
        except Exception as e:
            print("Error creating config file")
            print(e)
            return ''

        encryption = {True: " -e "}
        print_progress("Starting speed test...")
        test_result = subprocess.check_output(shlex.split(
            RMBT_BIN +
            encryption.get(self.test_server_encryption, "") +
            " -h " + self.test_server_address +
            " -p " + str(self.test_server_port) +
            " -t " + self.test_token +
            " -f " + self.test_numthreads +
            " -d " + self.test_duration +
            " -u " + self.test_duration +
            " -c " + self.config_file
        ))
        if print_debug("Speed test result:"):
            print(test_result)
        test_result_json = json.loads(test_result.split("}")[1] + "}")
        self.dl_speed = test_result_json.get("res_dl_throughput_kbps")
        return test_result_json

    def import_speed_flows(self):
        """The speedtest flow is saved to a file during the test. This function
        imports it so it could be sent to the control server.
        """
        directions = {
            "dl": "download",
            "ul": "upload"
        }
        try:
            subprocess.call(shlex.split("unxz -f "+self.flows_file+".xz"))
            with open(self.flows_file, 'r') as json_data:
                flows_json = json.load(json_data)
        except Exception as e:
            print('Problem reading/decoding flows data.')
            print(e)
            return

        speed_array = list()
        for d_short, d_long in directions.items():
            thread = 0
            # Each direction has multiple threads
            for flow in flows_json["res_details"][d_short]:
                last_time = 0
                # Each thread has plenty of samples
                # We want to use a small amount of them
                for sample in flow["time_series"]:
                    if (sample.get("t") - last_time) > 30000000:
                        last_time = sample["t"]
                        speed_array.append({
                            "direction": d_long,
                            "thread": thread,
                            "time": sample["t"],
                            "bytes": sample["b"]
                         })
                thread += 1

        # Remove generated files
        try:
            os.remove(self.flows_file)
        except Exception as e:
            print(e)
        try:
            os.remove(self.config_file)
        except Exception as e:
            print(e)
        return speed_array

    def upload_result(self, pres, test_result_json, speed_array):
        """Uploads the tests result to the control server.
        """
        req_json = {
            "client_language": self.language,
            "client_name": "RMBT",
            "client_uuid": self.uuid,
            "client_version": "0.1",
            "client_software_version": "0.3",
            "geoLocations": [],
            "model": self.model,
            "network_type": 98,
            "platform": "RMBT",
            "product": "os: "+self.os_version+" hw: "+self.hw_version,
            "test_bytes_download": test_result_json.get("res_total_bytes_dl"),
            "test_bytes_upload": test_result_json.get("res_total_bytes_ul"),
            "test_nsec_download": test_result_json.get("res_dl_time_ns"),
            "test_nsec_upload": test_result_json.get("res_ul_time_ns"),
            "test_num_threads": test_result_json.get("res_dl_num_flows"),
            "test_ping_shortest": pres,
            "num_threads_ul": test_result_json.get("res_ul_num_flows"),
            "test_speed_download": self.dl_speed,
            "test_speed_upload": test_result_json.get(
                "res_ul_throughput_kbps"
            ),
            "test_token": self.test_token,
            "test_uuid": self.test_uuid,
            "timezone": self.timezone,
            "type": "DESKTOP",
            "version_code": "1",
            "developer_code": 0
        }
        if self.gps_console_path:
            req_json["geoLocations"] = [{
                "geo_lat": self.lat,
                "geo_long": self.lon,
                "accuracy": 5*float(self.hdop),
                "altitude": self.altitude,
                "bearing": self.bearing,
                "speed": self.speed,
                "tstamp": self.get_time(),
                "provider": "gps"
            }]
        if print_debug("Save result request (without speed array and pings)"):
            print(json.dumps(req_json, indent=2))

        req_json["speed_detail"] = speed_array
        req_json["pings"] = []

        resp_json = self.send_request(req_json, 'result')
        if print_debug("Save result response:"):
            print(json.dumps(resp_json, indent=2))

    def download_history(self):
        """Creates a http request and ask the control server for a measurement
        history.
        """
        max_history_logs = uci_get("max_history_logs")
        if not max_history_logs:
            print_info("Max history logs not found, falling to {}".format(FALLBACK_MAX_HISTORY_LOGS))
            max_history_logs = FALLBACK_MAX_HISTORY_LOGS
            uci_set("max_history_logs", max_history_logs)

        # Create json to request history
        req_json = {
            "language": self.language,
            "timezone": self.timezone,
            "result_limit": str(max_history_logs),
            "uuid": self.uuid,
        }

        if print_debug(
                "Downloading measurement history from the control server."):
            print(json.dumps(req_json, indent=2))
        # Send the request
        resp_json = self.send_request(req_json, 'history')

        if print_debug("Measurement history response:"):
            print(json.dumps(resp_json, indent=2))

        _, self.hist_file = tempfile.mkstemp()
        try:
            with open(self.hist_file, "w") as hist_file:
                    hist_file.write(json.dumps(resp_json, indent=2))
            os.rename(self.hist_file, HIST_FILE)
        except Exception as e:
            print("Error saving measurement history.")
            print(e)

    def download_sync_code(self):
        """Creates a http request and ask the control server for a
        synchronization code that can be used to view saved measurements from
        different devices. The new code is saved via uci.
        """
        # Create json to request synchronization code
        req_json = {
            "language": self.language,
            "timezone": self.timezone,
            "uuid": self.uuid,
        }

        if print_debug(
            "Downloading synchronization code from the control server."
        ):
            print(json.dumps(req_json, indent=2))
        # Send the request
        resp_json = self.send_request(req_json, 'sync')

        if print_debug("Synchronization token response:"):
            print(json.dumps(resp_json, indent=2))

        if not resp_json["error"]:
            self.sync_code = resp_json["sync"][0].get("sync_code", '')
            uci_set("sync_code", self.sync_code)
        else:
            self.sync_code = ''
            print("Error downloading synchronization code.")

    def load_sync_code(self):
        """Checks the uci config for sychronization code and loads it to the\
        script. If no synchronization code is found a https request is send to\
        download it.
        """
        self.sync_code = uci_get("sync_code")
        if not self.sync_code:
            print_info("Sync code not found, requesting new one.")
            self.download_sync_code()

    def measure_gps(self):
        if not self.gps_console_path:
            return
        if not os.path.exists(self.gps_console_path):
            print_error("GPS special file not found!")
            self.gps_console_path = None
            return

        print_progress("Starting GPS measurement.")
        try:
            with serial.Serial(self.gps_console_path, timeout=5) as ser:
                self.parse_gps_console(ser)
        except:
            print_error("GPS problem.")
            self.gps_console_path = None

    def parse_gps_console(self, console):
        GGA = False
        VTG = False
        for i in range(1, 100 + 1):
            line = console.readline()
            if len(line) > 0 and line[0] == "$":
                splitted = line.split(",")
                if splitted[0] == "$GPGGA" and not GGA:
                    GGA = self.parse_gps_GGA(splitted, i)
                elif splitted[0] == "$GPVTG" and not VTG:
                    VTG = self.parse_gps_VTG(splitted, i)
                if GGA and VTG:
                    print_debug("GPS measured (line {}). Closing console.".format(i))
                    break
        if not GGA or not VTG:
            self.gps_console_path = None
            print_error("GPS problem: no valid data. Console closed.")

    def parse_gps_GGA(self, text, i):
        lat = text[2]
        if lat == '':
            if print_debug("Empty latitude (line {})".format(i)):
                print(text)
            return False
        lon = text[4]
        if lon == '':
            if print_debug("Empty longitude (line {})".format(i)):
                print(text)
            return False
        if text[8] == '':
            if print_debug("Empty hdop (line {})".format(i)):
                print(text)
            return False
        else:
            self.hdop = text[8]
        if text[9] == '':
            if print_debug("Empty altitude (line {})".format(i)):
                print(text)
            return False
        else:
            self.altitude = text[9]
        self.lat = int(lat[0:2])+float(lat[2:])/60
        self.lon = int(lon[0:3])+float(lon[3:])/60
        if text[3] == "S":
            self.lat = -self.lat
        if text[5] == "W":
            self.lon = -self.lon
        return True

    def parse_gps_VTG(self, text, i):
        if text[7] == '':
            if print_debug("Empty speed (line {})".format(i)):
                print(text)
            return False
        else:
            self.speed = text[7]
        if text[1] == '':
            if print_debug("Empty bearing (line {})".format(i)):
                print(text)
            return False
        else:
            self.bearing = text[1]
        return True

    def load_lte_console(self):
        if os.path.isfile("/sbin/uci"):
            process = subprocess.Popen(
                    ["uci", "-q", "get", "netmetr.settings.lte_console_path"],
                    stdout=subprocess.PIPE
            )
            if process.wait() == 0:
                self.lte_console_path = process.stdout.read()[:-1]
            else:
                self.lte_console_path = None
        else:
            self.lte_console_path = None
            print_info(
                    "LTE console path can't be loaded (uci missing)."
                    " You can specify it via CLI."
            )

    def set_lte_console(self, path):
        self.lte_console_path = path
        if os.path.isfile("/sbin/uci"):
            subprocess.call([
                    "uci",
                    "set",
                    "netmetr.settings.lte_console_path="
                    + self.lte_console_path
                ])
            subprocess.call(["uci", "commit"])
        else:
            print_info(
                'LTE console path not saved (uci missing).'
            )

    def disable_lte(self):
        self.lte_console_path = None
        if os.path.isfile("/sbin/uci"):
            subprocess.call([
                    "uci",
                    "delete",
                    "netmetr.settings.lte_console_path"
                ])
            subprocess.call(["uci", "commit"])

    def measure_lte(self):
        if not self.lte_console_path:
            return
        if not os.path.exists(self.lte_console_path):
            print_error("LTE special file not found!")
            self.lte_console_path = None
            return
        print_progress("Starting LTE measurement.")
        try:
            with serial.Serial(
                self.lte_console_path,
                baudrate=115200,
                timeout=5
            ) as ser:
                self.parse_lte_console(ser)
        except:
            print_error("LTE problem.")
            self.lte_console_path = None

    def parse_lte_console(self, console):
        console.write("AT!GSTATUS?\r")
        self.lte = dict()
        value_map = {
            "LTE bw": "Bandwidth",
            "PCC RxM RSSI": "RSSI",
            "PCC RxM RSRP": "RSRP",
            "RSRQ (dB)": "RSRQ",
            "SINR (dB)": "SINR Rx[0]",
        }
        while True:
            line = console.readline()
            if len(line) == 4:  # this is "OK\r\n"
                break
            for value_pair in line.split("\t"):
                value_pair = value_pair.split(":")
                value_name = value_map.get(value_pair[0], None)
                if value_name:
                    self.lte[value_name] = value_pair[1].split()[0]

        console.write("AT!LTEINFO?\r")
        while True:
            line = console.readline()
            if len(line) < 3:
                continue
            split_line = line.split()
            if len(line) == 4:  # this is "OK\r\n"
                if print_debug("LTE results:"):
                    print(json.dumps(self.lte, indent=2))
                break
            if split_line[0] == "Serving:":
                line = console.readline()
                split_line = line.split()
                self.lte["MCC"] = split_line[1]
                self.lte["MNC"] = split_line[2]
                self.lte["LAC"] = split_line[3]
                self.lte["Cell Id"] = int(split_line[4], 16)
                self.lte["PCI"] = split_line[9]
            if split_line[0] == "InterFreq:" and split_line[1] == "EARFCN":
                line = console.readline()
                self.lte["DL EARFCN"] = line.split()[0]

    def export_csv(self, path):
        table = list()
        table.append(time.strftime('%d.%m.%Y %H:%M'))
        table.extend([''] * 19)
        table[7] = round(self.dl_speed)
        if self.lte_console_path:
            table[3] = self.lte['RSRP']
            table[4] = self.lte['SINR Rx[0]']
            table[5] = self.lte['RSRQ']
            table[6] = self.lte['RSSI']
            table[8] = self.lte['MCC']
            table[9] = self.lte['MNC']
            table[10] = self.lte['LAC']
            table[11] = self.lte['Cell Id']
            table[12] = self.lte['PCI']
            table[13] = self.lte['DL EARFCN']
            table[14] = self.lte['Bandwidth']
        if self.gps_console_path:
            table[1] = "{:.6f}".format(float(self.lat))
            table[2] = "{:.6f}".format(float(self.lon))
        if os.path.isfile(path):
            with open(path, 'a') as csvfile:
                    writer = csv.writer(csvfile, delimiter=',')
                    writer.writerow(table)
        else:
            with open(path, 'w') as csvfile:
                writer = csv.writer(csvfile, delimiter=',')
                writer.writerows([(
                    time.strftime('%d.%m.%Y %H:%M'), "Lat", "Long",
                    "RSRP", "SINR Rx[0]",
                    "RSRQ", "RSSI", "IP Thrpt DL", "MCC", "MNC", "LAC",
                    "Cell Id", "PCI", "DL EARFCN", "Bandwidth", "QPSK Rate",
                    "16-QAM Rate", "64-QAM Rate", "256-QAM Rate",
                    "Carrier Aggregation DL"
                )])
                writer.writerow(table)


def uci_get(var):
    if os.path.isfile("/sbin/uci"):
        # Loading control server
        process = subprocess.Popen(
            ["uci", "-q", "get", "netmetr.settings.{}".format(var)],
            stdout=subprocess.PIPE
        )
        if process.wait() == 0:
            return process.stdout.read()[:-1]
    return None


def uci_set(var, value):
    if os.path.isfile("/sbin/uci"):
        retcode = subprocess.call([
            "uci", "set",
            "netmetr.settings.{}={}".format(var, value)
        ])
        if retcode != 0:
            return False
        retcode = subprocess.call(["uci", "commit"])
        return retcode == 0
    return False


def uci_del(var):
    if os.path.isfile("/sbin/uci"):
        retcode = subprocess.call([
            "uci", "-q", "delete",
            "netmetr.settings.{}".format(var)
        ])
        if retcode != 0:
            return False
        retcode = subprocess.call(["uci", "commit"])
        return retcode == 0
    return False


def print_debug(msg):
    if DEBUG:
        if COLORED_OUTPUT:
            print('\033[93m' + msg + '\033[0m')
        else:
            print(msg)
    return DEBUG


def print_info(msg):
    if COLORED_OUTPUT:
        print('\033[91m' + msg + '\033[0m')
    else:
        print(msg)


def print_progress(msg):
    if COLORED_OUTPUT:
        print('\033[93m' + msg + '\033[0m')
    else:
        print(msg)


def print_error(msg):
    if COLORED_OUTPUT:
        print('\033[41mERROR: ' + msg + '\033[0m')
    else:
        print('ERROR: {}'.format(msg))


def prepare_parser():
    # Prepare argument parsing
    parser = argparse.ArgumentParser(
            description="NetMetr - client"
            " application for download and upload speed measurement."
    )
    parser.add_argument(
        '--rwait', nargs=1, type=int, default=[0],
        help='delay for a random amount of time up to RWAIT seconds before'
        ' the test starts'
    )
    parser.add_argument(
        '--autostart', action='store_true', help='use this'
        ' option only when running as an automated service - to check whether'
        ' it is right time to run the test'
    )
    parser.add_argument(
        '--dwlhist',
        action='store_true',
        help='download measurement history from the control server and save'
        ' it to {}'.format(HIST_FILE)
    )
    parser.add_argument(
        '--debug', action='store_true', help='enables debug'
        ' printouts'
    )
    parser.add_argument(
        '--no-color', action='store_true', help='disables'
        ' colored text output'
    )
    parser.add_argument(
        '--no-run', action='store_true', help='this option '
        'prevents from running the test. It could be used only to obtain sync'
        ' code or (with --dwlhist) to download measurement history'
    )
    parser.add_argument(
        '--set-gps-console', nargs=1,
        help='set path to GPS modul serial console. The GPS must be enabled to'
        ' measure location with every speed test.'
    )
    parser.add_argument(
        '--disable-gps', action='store_true', help='disable'
        ' gps location monitoring'
    )
    parser.add_argument(
        '--set-lte-console', nargs=1,
        help='set path to LTE modul serial console. The LTE must be enabled to'
        ' measure LTE parametres with every speed test.'
    )
    parser.add_argument(
        '--disable-lte', action='store_true', help='disable'
        ' lte parametres monitoring'
    )
    parser.add_argument(
        '--export-csv', nargs=1,
        help='set export of LTE, GPS and other measurement results to a CSV'
        ' file. If the file already exists the output will be appended.'
    )

    return parser


def main():
    # When autostarted - check whether autostart is enabled and
    # if it is right time to run the test.
    # In uci config, we expect hours of a day separated by commas (,)
    # these hours
    # are the time the test should be run. So whenever the script is started,
    # it looks to it's config and if it finds the current hour of day in it,
    # it will start the test

    args = prepare_parser().parse_args()

    global DEBUG
    global COLORED_OUTPUT

    DEBUG = args.debug
    COLORED_OUTPUT = not args.no_color

    if args.autostart:
        if uci_get("autostart_enabled") != '1':
            return
        hours = uci_get("hours_to_run")
        if not hours:
            return
        hours = hours.split()
        hours = map(int, hours)
        if datetime.datetime.now().hour not in hours:
            return

    # Wait appropriate amount of time
    time.sleep(randint(0, args.rwait[0]))

    netmetr = Netmetr()
    # Request uuid from the control server
    netmetr.load_uuid()

    # LTE
    if args.disable_lte:
        netmetr.lte_console_path = None
        uci_del("lte_console_path")
    else:
        if args.set_lte_console:
            netmetr.lte_console_path = args.set_lte_console[0]
            uci_set("lte_console_path", netmetr.lte_console_path)
        else:
            netmetr.lte_console_path = uci_get("lte_console_path")
    # GPS
    if args.disable_gps:
        netmetr.gps_console_path = None
        uci_del("gps_console_path")
    else:
        if args.set_gps_console:
            netmetr.gps_console_path = args.set_gps_console[0]
            uci_set("gps_console_path", netmetr.gps_console_path)
        else:
            netmetr.gps_console_path = uci_get("gps_console_path")

    if (not args.no_run):
        # Run gps first
        netmetr.measure_gps()

        # Run lte test
        netmetr.measure_lte()

        # Request test settings from the control server
        netmetr.request_settings()

        # Get the ping measurement result
        shortest_ping = netmetr.measure_pings()

        # Get the speed measurement result
        speed_result = netmetr.measure_speed()
        if speed_result == '':
            quit()

        # Get detailed test statistics
        speed_flows = netmetr.import_speed_flows()

        # Upload result to the control server
        netmetr.upload_result(shortest_ping, speed_result, speed_flows)

    # Optionally export csv
    if (args.export_csv):
        netmetr.export_csv(args.export_csv[0])

    # Optionally download measurement history from the control server
    if (args.dwlhist):
        netmetr.download_history()

    netmetr.load_sync_code()
    if (netmetr.sync_code):
        print_info("Your Sync code is: " + netmetr.sync_code)


if __name__ == "__main__":
    main()
