#!/usr/bin/python """WSPR client using sdr-shell as the radio. Adam Sampson The wspr0 command-line tool that comes with wspr can deal with WAV files rather than doing audio IO itself, but they need to be 12000 Hz, mono, 16-bit signed, and 1440000 samples (two minutes) long. wspr0 Tx 14.0956 14.097061 0 2M0CGO IO86 37 55 out.wav (wait for start of an even-numbered minute) jackrec -f out.wav -d 120 sdr:ol sndfile-resample -to 12000 out.wav out12k.wav wspr0 Rx 10.1387 out12k.wav Use ecasound to do all the above? """ import sys, os, subprocess, optparse, datetime, time, threading from offog import die BANDS = { "2200m": (0.136000, 0.137500), "600m": (0.502400, 0.502400), "160m": (1.836600, 1.836600), "80m": (3.592600, 3.592600), "60m": (5.287200, 5.287200), "40m": (7.038600, 7.038600), "30m": (10.138700, 10.138700), "20m": (14.095600, 14.095600), "17m": (18.104600, 18.104600), "15m": (21.094600, 21.094600), "12m": (24.924600, 24.924600), "10m": (28.124600, 28.124600), "6m": (50.293000, 50.293000), "4m": (70.028600, 70.030100), "2m": (144.489000, 144.489000), } RIGCTL = [ "rigctl", "-m2", "-rlocalhost:19090" ] WSPR0 = ["/home/ats/src/wspr/wspr0"] PREROLL = 0.1 OUTPUT_DIR = "/home/ats/src/wspr/recordings" display_lock = threading.Lock() def status(*args): with display_lock: print ">>> " + "".join(map(str, args)) def cmd(args): if subprocess.call(args) != 0: die("Command failed: ", " ".join(args)) def rigctl(args): cmd(RIGCTL + args) def receive_thread(start_time, band, vfo_freq, tx_freq): status("Receiving at ", str(start_time)) client_name = "wspr%d_%d" % (os.getpid(), start_time.minute) output_base = OUTPUT_DIR + "/wspr-" + start_time.strftime("%Y-%m-%dT%H-%M") + "-" + band try: os.unlink(output_base + "-raw.wav") except OSError: pass cmd(["ecasound", "-q", "-t:120", "-G:jack," + client_name + ",notransport", "-i:jack,sdr", "-f:16,1,", "-o:" + output_base + "-raw.wav"]) cmd(["sndfile-resample", "-to", "12000", output_base + "-raw.wav", output_base + ".wav"]) os.unlink(output_base + "-raw.wav") status("Decoding at ", str(start_time)) with display_lock: cmd(WSPR0 + ["Rx", str(vfo_freq), output_base + ".wav"]) def main(): parser = optparse.OptionParser(usage="%prog [OPTIONS] BAND") (opts, args) = parser.parse_args() if len(args) != 1: parser.error("must specify band") band = args[0] if band not in BANDS: parser.error("unknown band") (vfo_freq, tx_freq) = BANDS[band] rigctl(["set_ptt", "0"]) rigctl(["set_freq", str(int(vfo_freq * 1000000))]) try: os.makedirs(OUTPUT_DIR) except OSError: pass preroll_delta = datetime.timedelta(seconds = PREROLL) while True: while True: now = datetime.datetime.utcnow() if (now.minute % 2) == 1 and now.second > 55: break time.sleep(1) start_time = now + datetime.timedelta(minutes = 1) start_time = start_time.replace(second = 0, microsecond = 0) while True: now = datetime.datetime.utcnow() + preroll_delta if now >= start_time: break time.sleep(0.05) func = receive_thread args = (start_time, band, vfo_freq, tx_freq) t = threading.Thread(target=func, args=args) t.start() time.sleep(2.0 * PREROLL) if __name__ == "__main__": main()