Esempio n. 1
0
def decode_rs41(frequency, ppm=0, gain='automatic', bias=False, rx_queue=None, timeout=120):
    """ Decode a RS41 sonde """
    global latest_sonde_data, internet_push_queue, ozi_push_queue
    # Add a -T option if bias is enabled
    bias_option = "-T " if bias else ""

    decode_cmd = "rtl_fm %s-p %d -M fm -s 15k -f %d 2>/dev/null |" % (bias_option, int(ppm), frequency)
    decode_cmd += "sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 2>/dev/null |"

    # Note: I've got the check-CRC option hardcoded in here as always on. 
    # I figure this is prudent if we're going to proceed to push this telemetry data onto a map.

    decode_cmd += "./rs41ecc --crc --ecc " # if this doesn't work try -i at the end

    rx_last_line = time.time()

    # Receiver subprocess. Discard stderr, and feed stdout into an asynchronous read class.
    rx = subprocess.Popen(decode_cmd, shell=True, stdin=None, stdout=subprocess.PIPE, preexec_fn=os.setsid) 
    rx_stdout = AsynchronousFileReader(rx.stdout, autostart=True)

    while not rx_stdout.eof():
        for line in rx_stdout.readlines():
            if (line != None) and (line != ""):
                try:
                    data = process_rs_line(line)
                    # Reset timeout counter.
                    rx_last_line = time.time()

                    if data != None:
                        # Add in a few fields that don't come from the sonde telemetry.
                        data['freq'] = "%.3f MHz" % (frequency/1e6)
                        data['type'] = "RS41"

                        update_flight_stats(data)

                        latest_sonde_data = data

                        if rx_queue != None:
                            try:
                                internet_push_queue.put_nowait(data)
                                ozi_push_queue.put_nowait(data)
                            except:
                                pass
                except:
                    traceback.print_exc()
                    logging.error("Error parsing line: %s" % line)

        # Check timeout counter.
        if time.time() > (rx_last_line+timeout):
            logging.error("RX Timed out.")
            break
        # Sleep for a short time.
        time.sleep(0.1)

    logging.error("Closing RX Thread.")
    os.killpg(os.getpgid(rx.pid), signal.SIGTERM)
    rx_stdout.stop()
    rx_stdout.join()
    return
Esempio n. 2
0
def decode_rs92(frequency, ppm=0, gain=-1, bias=False, rx_queue=None, almanac=None, ephemeris=None, timeout=120):
    """ Decode a RS92 sonde """
    global latest_sonde_data, internet_push_queue, ozi_push_queue

    # Before we get started, do we need to download GPS data?
    if ephemeris == None:
        # If no ephemeris data defined, attempt to download it.
        # get_ephemeris will either return the saved file name, or None.
        ephemeris = get_ephemeris(destination="ephemeris.dat")

    # If ephemeris is still None, then we failed to download the ephemeris data.
    # Try and grab the almanac data instead
    if ephemeris == None:
        logging.error("Could not obtain ephemeris data, trying to download an almanac.")
        almanac = get_almanac(destination="almanac.txt")
        if almanac == None:
            # We probably don't have an internet connection. Bomb out, since we can't do much with the sonde telemetry without an almanac!
            logging.critical("Could not obtain GPS ephemeris or almanac data.")
            return False

    # Add a -T option if bias is enabled
    bias_option = "-T " if bias else ""

    # Add a gain parameter if we have been provided one.
    if gain != -1:
        gain_param = '-g %.1f ' % gain
    else:
        gain_param = ''

    decode_cmd = "rtl_fm %s-p %d %s-M fm -s 12k -f %d 2>/dev/null |" % (bias_option, int(ppm), gain_param, frequency)
    decode_cmd += "sox -t raw -r 12k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - lowpass 2500 highpass 20 2>/dev/null |"

    # Note: I've got the check-CRC option hardcoded in here as always on. 
    # I figure this is prudent if we're going to proceed to push this telemetry data onto a map.

    if ephemeris != None:
        decode_cmd += "./rs92ecc -v --crc --ecc --vel -e %s" % ephemeris
    elif almanac != None:
        decode_cmd += "./rs92ecc -v --crc --ecc --vel -a %s" % almanac

    logging.debug("Running command: %s" % decode_cmd)

    rx_last_line = time.time()

    # Receiver subprocess. Discard stderr, and feed stdout into an asynchronous read class.
    rx = subprocess.Popen(decode_cmd, shell=True, stdin=None, stdout=subprocess.PIPE, preexec_fn=os.setsid) 
    rx_stdout = AsynchronousFileReader(rx.stdout, autostart=True)

    while not rx_stdout.eof():
        for line in rx_stdout.readlines():
            if (line != None) and (line != ""):
                try:
                    data = process_rs_line(line)
                    # Reset timeout counter.
                    rx_last_line = time.time()

                    if data != None:
                        # Add in a few fields that don't come from the sonde telemetry.
                        data['freq'] = "%.3f MHz" % (frequency/1e6)
                        data['type'] = "RS92"

                        update_flight_stats(data)

                        if rx_queue != None:
                            try:
                                internet_push_queue.put_nowait(data)
                                ozi_push_queue.put_nowait(data)
                            except:
                                pass
                except:
                    traceback.print_exc()
                    logging.error("Error parsing line: %s" % line)

        # Check timeout counter.
        if time.time() > (rx_last_line+timeout):
            logging.error("RX Timed out.")
            break
        # Sleep for a short time.
        time.sleep(0.1)

    logging.error("Closing RX Thread.")
    os.killpg(os.getpgid(rx.pid), signal.SIGTERM)
    rx_stdout.stop()
    rx_stdout.join()
    return
Esempio n. 3
0
def decode_rs41(frequency,
                ppm=0,
                gain=-1,
                bias=False,
                rx_queue=None,
                timeout=120,
                save_log=False):
    """ Decode a RS41 sonde """
    global latest_sonde_data, internet_push_queue, ozi_push_queue
    # Add a -T option if bias is enabled
    bias_option = "-T " if bias else ""

    # Add a gain parameter if we have been provided one.
    if gain != -1:
        gain_param = '-g %.1f ' % gain
    else:
        gain_param = ''

    # Note: Have removed a 'highpass 20' filter from the sox line, will need to re-evaluate if adding that is useful in the future.
    decode_cmd = "rtl_fm %s-p %d %s-M fm -F9 -s 15k -f %d 2>/dev/null |" % (
        bias_option, int(ppm), gain_param, frequency)
    decode_cmd += "sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - lowpass 2600 2>/dev/null |"

    # Note: I've got the check-CRC option hardcoded in here as always on.
    # I figure this is prudent if we're going to proceed to push this telemetry data onto a map.

    decode_cmd += "./rs41ecc --crc --ecc "  # if this doesn't work try -i at the end

    logging.debug("Running command: %s" % decode_cmd)

    rx_last_line = time.time()

    # Receiver subprocess. Discard stderr, and feed stdout into an asynchronous read class.
    rx = subprocess.Popen(decode_cmd,
                          shell=True,
                          stdin=None,
                          stdout=subprocess.PIPE,
                          preexec_fn=os.setsid)
    rx_stdout = AsynchronousFileReader(rx.stdout, autostart=True)

    _log_file = None

    while not rx_stdout.eof():
        for line in rx_stdout.readlines():
            if (line != None) and (line != ""):
                try:
                    data = process_rs_line(line)
                    # Reset timeout counter.
                    rx_last_line = time.time()

                    if data != None:
                        # Add in a few fields that don't come from the sonde telemetry.
                        data['freq'] = "%.3f MHz" % (frequency / 1e6)
                        data['type'] = "RS41"

                        # Per-Sonde Logging
                        if save_log:
                            if _log_file is None:
                                _log_file_name = "./log/%s_%s_%s_%d.log" % (
                                    datetime.datetime.utcnow().strftime(
                                        "%Y%m%d-%H%M%S"), data['id'],
                                    data['type'], int(frequency / 1e3))

                                _log_file = open(_log_file_name, 'wb')

                            # Write a log line
                            # datetime,id,frame_no,lat,lon,alt,type,frequency
                            _log_line = "%s,%s,%d,%.5f,%.5f,%.1f,%s,%.3f\n" % (
                                data['datetime_str'], data['id'],
                                data['frame'], data['lat'], data['lon'],
                                data['alt'], data['type'], frequency / 1e6)

                            _log_file.write(_log_line)
                            _log_file.flush()

                        update_flight_stats(data)

                        latest_sonde_data = data

                        if rx_queue != None:
                            try:
                                internet_push_queue.put_nowait(data)
                                ozi_push_queue.put_nowait(data)
                            except:
                                pass
                except:
                    traceback.print_exc()
                    logging.error("Error parsing line: %s" % line)

        # Check timeout counter.
        if time.time() > (rx_last_line + timeout):
            logging.error("RX Timed out.")
            break
        # Sleep for a short time.
        time.sleep(0.1)

    # If we were writing a log, close the file.
    if _log_file != None:
        _log_file.flush()
        _log_file.close()

    logging.error("Closing RX Thread.")
    os.killpg(os.getpgid(rx.pid), signal.SIGTERM)
    rx_stdout.stop()
    rx_stdout.join()
    return
Esempio n. 4
0
def decode_rs92(frequency,
                ppm=0,
                gain=-1,
                bias=False,
                rx_queue=None,
                almanac=None,
                ephemeris=None,
                timeout=120,
                save_log=False):
    """ Decode a RS92 sonde """
    global latest_sonde_data, internet_push_queue, ozi_push_queue

    # Before we get started, do we need to download GPS data?
    if ephemeris == None:
        # If no ephemeris data defined, attempt to download it.
        # get_ephemeris will either return the saved file name, or None.
        ephemeris = get_ephemeris(destination="ephemeris.dat")

    # If ephemeris is still None, then we failed to download the ephemeris data.
    # Try and grab the almanac data instead
    if ephemeris == None:
        logging.error(
            "Could not obtain ephemeris data, trying to download an almanac.")
        almanac = get_almanac(destination="almanac.txt")
        if almanac == None:
            # We probably don't have an internet connection. Bomb out, since we can't do much with the sonde telemetry without an almanac!
            logging.critical("Could not obtain GPS ephemeris or almanac data.")
            return False

    # Add a -T option if bias is enabled
    bias_option = "-T " if bias else ""

    # Add a gain parameter if we have been provided one.
    if gain != -1:
        gain_param = '-g %.1f ' % gain
    else:
        gain_param = ''

    # Example command:
    # rtl_fm -p 0 -g 26.0 -M fm -F9 -s 12k -f 400500000 | sox -t raw -r 12k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 lowpass 2500 2>/dev/null | ./rs92ecc
    decode_cmd = "rtl_fm %s-p %d %s-M fm -F9 -s 12k -f %d 2>/dev/null |" % (
        bias_option, int(ppm), gain_param, frequency)
    decode_cmd += "sox -t raw -r 12k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - lowpass 2500 highpass 20 2>/dev/null |"

    # Note: I've got the check-CRC option hardcoded in here as always on.
    # I figure this is prudent if we're going to proceed to push this telemetry data onto a map.

    if ephemeris != None:
        decode_cmd += "./rs92ecc -vx -v --crc --ecc --vel -e %s" % ephemeris
    elif almanac != None:
        decode_cmd += "./rs92ecc -vx -v --crc --ecc --vel -a %s" % almanac

    logging.debug("Running command: %s" % decode_cmd)

    rx_last_line = time.time()

    # Receiver subprocess. Discard stderr, and feed stdout into an asynchronous read class.
    rx = subprocess.Popen(decode_cmd,
                          shell=True,
                          stdin=None,
                          stdout=subprocess.PIPE,
                          preexec_fn=os.setsid)
    rx_stdout = AsynchronousFileReader(rx.stdout, autostart=True)

    _log_file = None

    while not rx_stdout.eof():
        for line in rx_stdout.readlines():
            if (line != None) and (line != ""):
                try:
                    data = process_rs_line(line)
                    # Reset timeout counter.
                    rx_last_line = time.time()

                    if data != None:
                        # Add in a few fields that don't come from the sonde telemetry.
                        data['freq'] = "%.3f MHz" % (frequency / 1e6)
                        data['type'] = "RS92"

                        # If we are seeing any aux data (i.e. there is something strapped to this RS92), append '-Ozone' to the type.
                        if 'aux' in data.keys():
                            _ozone = "-Ozone"
                        else:
                            _ozone = ""

                        # Per-Sonde Logging
                        if save_log:
                            if _log_file is None:
                                _log_file_name = "./log/%s_%s_%s_%d.log" % (
                                    datetime.datetime.utcnow().strftime(
                                        "%Y%m%d-%H%M%S"), data['id'],
                                    (data['type'] + _ozone),
                                    int(frequency / 1e3))

                                _log_file = open(_log_file_name, 'wb')

                            # Write a log line
                            # datetime,id,frame_no,lat,lon,alt,type,frequency
                            _log_line = "%s,%s,%d,%.5f,%.5f,%.1f,%s,%.3f\n" % (
                                data['datetime_str'], data['id'],
                                data['frame'], data['lat'], data['lon'],
                                data['alt'],
                                (data['type'] + _ozone), frequency / 1e6)

                            _log_file.write(_log_line)
                            _log_file.flush()

                        update_flight_stats(data)

                        if rx_queue != None:
                            try:
                                internet_push_queue.put_nowait(data)
                                ozi_push_queue.put_nowait(data)
                            except:
                                pass
                except:
                    traceback.print_exc()
                    logging.error("Error parsing line: %s" % line)

        # Check timeout counter.
        if time.time() > (rx_last_line + timeout):
            logging.error("RX Timed out.")
            break
        # Sleep for a short time.
        time.sleep(0.1)

    # If we were writing a log, close the file.
    if _log_file != None:
        _log_file.flush()
        _log_file.close()

    logging.error("Closing RX Thread.")
    os.killpg(os.getpgid(rx.pid), signal.SIGTERM)
    rx_stdout.stop()
    rx_stdout.join()
    return