def __init__(self, data): # myutils.debug_hex(data) string_length, self.id_key = myutils.get_utf8_string(data) tmp = 4 + string_length # print(" id_key: {} (len:{})".format(self.id_key, string_length)) self.new_id = myutils.get_boolean(data[tmp:]) # print(" [*] new: {}".format(self.new_id)) tmp += myutils.DataSize._boolean # print(" [*] new_id:{}".format(self.new_id)) self.now_time = myutils.get_time(data[tmp:]) tmp += myutils.DataSize._time # print(" [*] date:{}".format(self.now_time)) self.snr = myutils.get_int32(data[tmp:]) tmp += myutils.DataSize._int32 # print(" [*] snr:{}".format(self.snr)) self.delta_time = myutils.get_double(data[tmp:]) tmp += myutils.DataSize._double # print(" [*] delta_time:{}".format(self.delta_time)) # Something in here? Seems zero in the debug # myutils.debug_hex(data[tmp:]) tmp += myutils.DataSize._uint32 self.delta_freq = myutils.get_uint32(data[tmp:]) tmp += myutils.DataSize._uint32 # print(" [*] delta_freq:{}".format(self.delta_freq)) self.drift = myutils.get_uint32(data[tmp:]) tmp += myutils.DataSize._uint32 # print(" [*] drift:{}".format(self.drift)) string_length, self.callsign = myutils.get_utf8_string(data[tmp:]) tmp += 4 + string_length # print(" [*] callsign:{}".format(self.callsign)) string_length, self.grid = myutils.get_utf8_string(data[tmp:]) tmp += 4 + string_length # print(" [*] grid:{}".format(self.grid)) self.power = myutils.get_uint32(data[tmp:]) # print(" [*] power:{}".format(self.power)) self.dist = 0 self.bearing = 0 if (myutils.validate_callsign(self.callsign)): if (myutils.validate_locator(self.grid)): self.dist = locator.calculate_distance("io64", self.grid) self.bearing = locator.calculate_heading("io64", self.grid)
def test_calculate_heading_edge_cases(self): assert abs(calculate_heading("JN48QM", "JN48QM") - 0 ) < 1
def test_calculate_heading_normal_cases(self): assert abs(calculate_heading("JN48QM", "FN44AB") - 298) < 1 assert abs(calculate_heading("FN44AB", "JN48QM") - 54) < 1 assert abs(calculate_heading("JN48QM", "QF67bf") - 74) < 1 assert abs(calculate_heading("QF67BF", "JN48QM") - 310) < 1
async def qrzLookup(origcall, config): '''Lookup call @QRZ''' my_lookuplib = LookupLib(lookuptype="qrz", username=config['qrz.com']['username'], pwd=config['qrz.com']['password']) cic = Callinfo(my_lookuplib) origcall = origcall.upper() try: call = cic.get_homecall(origcall) lookup = await qrzRedisLookup(call) except ValueError: callsign = None lookup = {} #dict() print("Not Found") return {'origcallsign': origcall, 'callsign': callsign} if lookup is False: try: lookup = cic.get_all(call) callsign = lookup['callsign'] redis.set('qrz' + call.upper(), json.dumps(lookup, default=str)) redis.expire('qrz' + call.upper(), 2629743000) redis.sadd('qrzCALLS', call.upper()) calls.append(call.upper()) except ValueError: callsign = None lookup = {} #dict() print("Not Found") return {'origcallsign': origcall, 'callsign': callsign} except KeyError: callsign = call lookup = {} #dict() print("Not Found") return {'origcallsign': origcall, 'callsign': callsign} else: callsign = lookup['callsign'] if callsign and 'aliases' in lookup: print( fg('blue') + '-=' + fg('turquoise_4') + attr('bold') + callsign + attr('reset') + fg('blue') + '=-' + attr('reset') + " (" + ','.join(lookup['aliases']) + ')') else: print( fg('blue') + '-=' + fg('turquoise_4') + attr('bold') + callsign + fg('blue') + '=-') print(fg('#884444') + attr('bold') + 'QTH: ', end="") await dictLookupAndPrint(lookup, '#a4a24f', 'fname', False) await dictLookupAndPrint(lookup, '#a4a24f', 'name', False, ", ") await dictLookupAndPrint(lookup, 'navajo_white_3', 'addr1', False, ", ") await dictLookupAndPrint(lookup, 'navajo_white_3', 'zipcode', False) await dictLookupAndPrint(lookup, 'navajo_white_3', 'addr2', False, ", ") await dictLookupAndPrint(lookup, 'navajo_white_3', 'country') print(fg('#884444') + attr('bold') + 'Grid square: ', end="") await dictLookupAndPrint(lookup, 'dark_sea_green_3b', 'locator', False) print(fg('#884444') + attr('bold') + 'Latitude: ', end="") latitude = await dictLookupAndPrint(lookup, 'dark_sea_green_3b', 'latitude', False) print(fg('#884444') + attr('bold') + 'Longitude: ', end="") longitude = await dictLookupAndPrint(lookup, 'dark_sea_green_3b', 'longitude') print(fg('#884444') + attr('bold') + 'CCode: ', end="") await dictLookupAndPrint(lookup, 'dark_sea_green_3b', 'ccode', False) print(fg('#884444') + attr('bold') + 'CQZone: ', end="") await dictLookupAndPrint(lookup, 'dark_sea_green_3b', 'cqz', False) print(fg('#884444') + attr('bold') + 'ITUZone: ', end="") await dictLookupAndPrint(lookup, 'dark_sea_green_3b', 'ituz') print(fg('#884444') + attr('bold') + 'QSL: ', end="") await dictLookupAndPrint(lookup, 'navajo_white_3', 'qslmgr', False) print(fg('#884444') + attr('bold') + 'eQSL: ', end="") await dictLookupAndPrint(lookup, 'navajo_white_3', 'eqsl', False) print(fg('#884444') + attr('bold') + 'lotw: ', end="") await dictLookupAndPrint(lookup, 'navajo_white_3', 'lotw') print(fg('#884444') + attr('bold') + 'E-Mail: ', end="") email = await dictLookupAndPrint(lookup, 'navajo_white_3', 'email', True) locator1 = latlong_to_locator(cfg['qth']['latitude'], cfg['qth']['longitude']) locator2 = latlong_to_locator(latitude, longitude) heading = calculate_heading(locator1, locator2) longpath = calculate_heading_longpath(locator1, locator2) print(fg('#884444') + attr('bold') + 'Heading: ', end="") print(fg('navajo_white_3') + "%.1f°" % heading, end="") print(fg('#884444') + attr('bold') + ' Longpath: ', end="") print(fg('navajo_white_3') + "%.1f°" % longpath, end="") print(attr('reset')) return { 'origcallsign': origcall, 'callsign': callsign, 'email': email, 'latitude': latitude, 'longitude': longitude, 'heading': heading, 'longpath': longpath }
def main(): global out_log sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # server_address = ('127.0.0.1', 2237) # sock.sendto('test message', config.server_address) sock.bind(config.server_address) # config.use_curses = True if config.use_curses: jt_curses = WsjtxCurses() # Exit py_wsjtx on WSJT-X exit # exit_on_wsjtxexit = False # Enable DXCC notify alerts # notify_alert = True if config.notify_alert: Notify.init("DX") if not popup_toast('Notifications enabled'): jt_curses.add_main_window('[!] Notification Error') # Publish mqtt messages, requires paho installed # config.use_mqtt = True # mqtt_server = "192.168.0.12" # Write all decodes to a log file config.log_decodes = False config.log_outfile = "/tmp/py_wsjtx.log" # Read existing log file log = WsjtxLog() log_info = "[*] Logfile found, {} entries read, {} stations.".format( log.entry_count, len(log.log_entries)) if config.use_curses: jt_curses.add_main_window(log_info) else: print(log_info) current_band = "" state = {} if config.log_decodes: out_log = open(config.log_outfile, 'a', 0) out_log.write("Started Log at {}\n".format(datetime.datetime.now())) if config.use_mqtt: import paho.mqtt.client as paho mqtt_client = paho.Client() mqtt_client.connect(config.mqtt_server, keepalive=60) mqtt_client.loop_start() mqtt_client.publish("py_wsjtx/status", "Started at {}".format(datetime.datetime.now())) # # Replay is PITA when testing # data, server = sock.recvfrom(1024) # p = header.create_header() # p += Replay.create_packet() # sock.sendto(p, server) try: while True: data, server = sock.recvfrom(1024) h = header(data[0:16]) # print "data:", data packet_type = struct.unpack(">L", data[8:12])[0] # print("[*] packet_type:{}".format(packet_type)) if packet_type == PacketType.Heartbeat: payload = Heartbeat(data[12:]) if config.use_curses: jt_curses.update_heartbeat( datetime.datetime.now().strftime("%H:%M:%S")) else: print("[*] Heartbeat [{}]".format(datetime.datetime.now())) if config.use_mqtt: mqtt_msg = json.dumps({ "heartbeat": datetime.datetime.now().strftime("%H:%M:%S") }) mqtt_client.publish( "py_wsjtx/{}/status".format(payload.id_key), mqtt_msg) elif packet_type == PacketType.Status: payload = StateChange(data[12:]) # Set a per radio state state[payload.id_key] = { 'freq': payload.dial_freq, 'mode': payload.tx_mode, 'tx': payload.tx_enabled, 'band': log.get_band(str(payload.dial_freq / 1000 / 1000)) } if config.use_mqtt: mqtt_msg = json.dumps({ 'status_frequency': payload.dial_freq, 'status_mode': payload.tx_mode, 'status_tx': payload.tx_enabled }) mqtt_client.publish( "py_wsjtx/{}/status".format(payload.id_key), mqtt_msg) if config.use_curses: jt_curses.set_banner(payload.dial_freq, payload.tx_mode, payload.tx_enabled) else: print(payload.do_print()) current_band = log.get_band( str(payload.dial_freq / 1000 / 1000)) # print("[!] Current band: {}".format(current_band)) elif packet_type == PacketType.Decode: # myutils.debug_packet(data) payload = Decode(data[12:]) # Get current radio state or return ??? # decode_mode = state.get(payload.id_key, {}).get('mode','???') decode_mode = "JT65" if payload.mode == '#' else "JT9" decode_band = state.get(payload.id_key, {}).get('band', '???') decode_dialfreq = state.get(payload.id_key, {}).get('freq', '???') if config.use_mqtt: mqtt_msg = json.dumps({ 'time': payload.now_time, 'db': str(payload.snr).rjust(2), 'dt': payload.delta_time, 'dialfreq': decode_dialfreq, 'freq': str(payload.delta_freq).rjust(4), 'mode': decode_mode, 'band': decode_band, 'msg': payload.message }) mqtt_client.publish( "py_wsjtx/{}/decodes".format(payload.id_key), mqtt_msg) # info = "[{}] db:{:0>2} DT:{:.1f} Freq:{} DFreq:{} Mode:{} Msg: {}".format( # payload.now_time, # str(payload.snr).rjust(2), # payload.delta_time, # decode_dialfreq, # str(payload.delta_freq).rjust(4), # decode_mode, # payload.message) info = "[{}] {:>3}db, {:>4}Hz, {:>3}, {:>4}, Msg: {}".format( payload.now_time, str(payload.snr).rjust(2), str(payload.delta_freq).rjust(4), decode_band, decode_mode, payload.message) if config.log_decodes: out_log.write("{}\n".format(info)) if config.use_curses: jt_curses.add_main_window(info) else: payload.do_print() # Check for CQ call if payload.message[:2] == "CQ": cq = payload.message.split(" ") if len(cq) > 1: # CQ call should be 'CQ CALL LOC', but can be: # 'CQ DX CALL LOC' or # 'CQ CALL DX LOC' cq_call = cq[1] if len(cq) == 2: cq_loc = "" else: cq_loc = cq[2] if cq_call == "DX": cq_call = cq[2] if len(cq) > 3: cq_loc = cq[3] else: cq_loc = "" if cq_loc == "DX": if len(cq) > 3: cq_loc = cq[3] else: cq_loc = "" # Check for valid callsign if (myutils.validate_callsign(cq_call)): # Have we worked call before? band = log.check_entry2(cq_call, current_band) if band["call"]: # worked call before if band["call_band"]: # ...and worked call on this band colour = bcolors.WKD_BEFORE status = log.WORKED_COUNTRY_AND_STATION elif band["country_band"]: # Worked call on a different band but # also worked country on this band colour = bcolors.WKD_COUNTRY_NOT_STATION status = log.WORKED_COUNTRY_NOT_STATION else: # TODO: check flags colour = bcolors.WKD_COUNTRY_DIFF_BAND status = log.WORKED_COUNTRY_DIFF_BAND else: # call not worked if band["country"]: if band["country_band"]: # ...but have worked country on this band colour = bcolors.WKD_COUNTRY_NOT_STATION status = log.WORKED_COUNTRY_NOT_STATION else: # ...but have worked country before, on different band colour = bcolors.WKD_COUNTRY_DIFF_BAND status = log.WORKED_COUNTRY_DIFF_BAND else: # Call or country not worked, raise DXCC alert colour = bcolors.NOT_WORKED status = log.NOT_WORKED if config.notify_alert: if not popup_toast( log.dxcc.find_country( cq_call)): jt_curses.add_main_window( '[!] Failed to notify CQ') if config.use_mqtt: mqtt_msg = json.dumps({ 'time': payload.now_time, 'db': str(payload.snr), 'dxcc_call': cq_call, 'dxcc_locator': cq_loc, 'dxcc_country': log.dxcc.find_country(cq_call), 'dxcc_mode': decode_mode, 'dxcc_band': decode_band, 'dialfreq': decode_dialfreq }) mqtt_client.publish( "py_wsjtx/{}/dxcc".format( payload.id_key), mqtt_msg) # Now display if config.use_curses: jt_curses.add_cq( cq_call, status + 1, cq_loc, log.dxcc.find_country(cq_call), band) else: print("[***] CQ CALLED BY {}{}{} ({}) [{}]". format(colour, cq_call, bcolors.ENDC, cq_loc, status)) if (myutils.validate_locator(cq_loc)): print( " [*] Distance: {:.0f}km, Bearing:{:.0f}" .format( locator.calculate_distance( config.locator, cq_loc), locator.calculate_heading( config.locator, cq_loc))) else: msg = "[*] CQ by non-valid callsign?" if config.use_curses: jt_curses.add_main_window(msg) else: print(msg) elif packet_type == PacketType.Clear: payload = Clear(data[12:]) if config.use_curses: jt_curses.add_main_window("[*] Clear Called") else: payload.do_print() elif packet_type == PacketType.Reply: # Not used, this is an out message pass elif packet_type == PacketType.QSO_Logged: # myutils.debug_packet(data) payload = Qso_Logged(data[12:]) if config.use_curses: jt_curses.add_main_window("[*] Logged QSO with {}".format( payload.dx_call)) else: payload.do_print() # re-read the log file log.read_log() elif packet_type == PacketType.Close: payload = Close(data[12:]) if config.use_curses: jt_curses.add_main_window("[!] Exit called") else: payload.do_print if config.exit_on_wsjtxexit: sys.exit(0) elif packet_type == PacketType.Replay: # Not used, this is an out message pass elif packet_type == PacketType.Halt_TX: # Not used, this is an out message pass elif packet_type == PacketType.Free_Text: # Not used, this is an out message pass elif packet_type == PacketType.WSPRDecode: payload = WSPRDecode(data[12:]) decode_band = state.get(payload.id_key, {}).get('band', '???') if config.use_mqtt: mqtt_msg = json.dumps({ 'WSPR_call': payload.callsign, 'band': decode_band, 'grid': payload.grid, 'dist': int(payload.dist), 'pwr': payload.power, 'db': payload.snr }) mqtt_client.publish( "py_wsjtx/{}/wspr".format(payload.id_key), mqtt_msg) info = "WSPR [{}]: {:10} ({:6}) db:{:4}, Freq:{:>10,}Hz, pwr:{:4}, Dist:{:>5.0f}km, Az: {:>3.0f}".format( payload.now_time, payload.callsign, payload.grid, payload.snr, payload.delta_freq, payload.power, payload.dist, payload.bearing) if config.log_decodes: out_log.write("{}\n".format(info)) if config.use_curses: jt_curses.add_main_window(info) else: payload.do_print() else: if config.use_curses: jt_curses.add_main_window( "[*] Packet type: {}".format(packet_type)) else: print("[*] Packet type: {}".format(packet_type)) except KeyboardInterrupt: if config.use_curses: jt_curses.exit_now() if config.log_decodes: out_log.write("Closed Log at {}\n".format(datetime.datetime.now())) out_log.close() print("ctrl-c caught, exiting") if config.notify_alert: Notify.uninit()
wspr_call = re.sub('[<>]', '', wspr_msg_split[0]) wspr_loc = wspr_msg_split[1] wspr_pwr = wspr_msg_split[2] if (len(wspr_msg_split) != 4): print 'No correct wspr message.' band_vec = ('LF', 'MW', '160m', '80m', '60m', '40m', '30m', '20m', '17m', '15m', '12m', '10m') freq_vec = (0.1, 0.4, 1.8, 3.5, 5.2, 7.0, 10.1, 14.0, 18.1, 21.0, 24.9, 28.1) wspr_band = band_vec[freq_vec.index( round(float(wspr_freq) - 0.05, 1))] wspr_dist = str( int(calculate_distance(wspr_loc_reporter, wspr_loc))) wspr_az = str(int(calculate_heading(wspr_loc_reporter, wspr_loc))) latitude, longitude = locator_to_latlong(wspr_loc) wspr_loc_geohash = geohash.encode(latitude, longitude, precision=5) print wspr_date + '' + wspr_time wspr_tuple_time = strptime(wspr_date + wspr_time, "%y%m%d%H%M") wspr_time = strftime("%Y-%m-%dT%H:%M:%SZ", wspr_tuple_time) print wspr_time json_body = [{ "measurement": "wspr_redpitaya_test", "tags": { "band": wspr_band, "reporter": wspr_reporter, "loc_reporter": wspr_loc_reporter,
def main(): global out_log sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # server_address = ('127.0.0.1', 2237) # sock.sendto('test message', config.server_address) sock.bind(config.server_address) # config.use_curses = True if config.use_curses: jt_curses = WsjtxCurses() # Exit py_wsjtx on WSJT-X exit # exit_on_wsjtxexit = False # Enable DXCC notify alerts # notify_alert = True if config.notify_alert: Notify.init("DX") if not popup_toast('Notifications enabled'): jt_curses.add_main_window('[!] Notification Error') # Publish mqtt messages, requires paho installed # config.use_mqtt = True # mqtt_server = "192.168.0.12" # Write all decodes to a log file config.log_decodes = False config.log_outfile = "/tmp/py_wsjtx.log" # Read existing log file log = WsjtxLog() log_info = "[*] Logfile found, {} entries read, {} stations.".format(log.entry_count, len(log.log_entries)) if config.use_curses: jt_curses.add_main_window(log_info) else: print(log_info) current_band = "" state = {} if config.log_decodes: out_log = open(config.log_outfile, 'a', 0) out_log.write("Started Log at {}\n".format(datetime.datetime.now())) if config.use_mqtt: import paho.mqtt.client as paho mqtt_client=paho.Client(protocol=paho.MQTTv31) mqtt_client.connect(config.mqtt_server, keepalive=60, ) mqtt_client.loop_start() mqtt_client.publish("py_wsjtx/status", "Started at {}".format(datetime.datetime.now())) # # Replay is PITA when testing # data, server = sock.recvfrom(1024) # p = header.create_header() # p += Replay.create_packet() # sock.sendto(p, server) try: while True: data, server = sock.recvfrom(1024) h = header(data[0:16]) # print "data:", data packet_type = struct.unpack(">L", data[8:12])[0] # print("[*] packet_type:{}".format(packet_type)) if packet_type == PacketType.Heartbeat: payload = Heartbeat(data[12:]) if config.use_curses: jt_curses.update_heartbeat(datetime.datetime.now().strftime("%H:%M:%S")) else: print("[*] Heartbeat [{}]".format(datetime.datetime.now())) if config.use_mqtt: mqtt_msg = json.dumps({"heartbeat": datetime.datetime.now().strftime("%H:%M:%S")}) mqtt_client.publish("py_wsjtx/{}/status".format(payload.id_key), mqtt_msg) elif packet_type == PacketType.Status: payload = StateChange(data[12:]) # Set a per radio state state[payload.id_key] = {'freq': payload.dial_freq, 'mode': payload.tx_mode, 'tx': str(payload.tx_enabled), 'band': log.get_band(str(payload.dial_freq/1000/1000)) } if config.use_mqtt: mqtt_msg = json.dumps({'status_frequency': str(payload.dial_freq), 'status_mode': str(payload.tx_mode), 'status_tx': str(payload.tx_enabled)}) mqtt_client.publish("py_wsjtx/{}/status".format(payload.id_key), mqtt_msg) if config.use_curses: jt_curses.set_banner(payload.dial_freq, payload.tx_mode, str(payload.tx_enabled)) else: print(payload.do_print()) current_band = log.get_band(str(payload.dial_freq/1000/1000)) # print("[!] Current band: {}".format(current_band)) elif packet_type == PacketType.Decode: # myutils.debug_packet(data) payload = Decode(data[12:]) # Get current radio state or return ??? decode_mode = state.get(payload.id_key, {}).get('mode','???') # If it's JT65/JT9 mode, check actual received signal mode if decode_mode == "JT9" or decode_mode == "JT65": if payload.mode == '#': decode_mode = "JT65" elif payload.mode == "@": decode_mode = "JT9" else: decode_mode = "ERR" decode_band = state.get(payload.id_key, {}).get('band','???') decode_dialfreq = state.get(payload.id_key, {}).get('freq','???') if config.use_mqtt: mqtt_msg = json.dumps({'time': payload.now_time, 'db': str(payload.snr).rjust(2), 'dt': payload.delta_time, 'dialfreq': decode_dialfreq, 'freq': str(payload.delta_freq).rjust(4), 'mode': decode_mode, 'band': decode_band, 'msg': payload.message}) # mqtt_client.publish("py_wsjtx/{}/decodes".format(payload.id_key), mqtt_msg) mqtt_client.publish("py_wsjtx/{}/decodes".format("WSJT-X"), mqtt_msg) # info = "[{}] db:{:0>2} DT:{:.1f} Freq:{} DFreq:{} Mode:{} Msg: {}".format( # payload.now_time, # str(payload.snr).rjust(2), # payload.delta_time, # decode_dialfreq, # str(payload.delta_freq).rjust(4), # decode_mode, # payload.message) info = "[{}] {:>3}db, {:>4}Hz, {:>3}, {:>4}, Msg: {}".format( payload.now_time, str(payload.snr).rjust(2), str(payload.delta_freq).rjust(4), decode_band, decode_mode, payload.message ) if config.log_decodes: out_log.write("{}\n".format(info)) if config.use_curses: jt_curses.add_main_window(info) else: payload.do_print() # Check for CQ call if payload.message[:2] == "CQ": cq = payload.message.split(" ") if len(cq) > 1: # CQ call should be 'CQ CALL LOC', but can be: # 'CQ DX CALL LOC' or # 'CQ CALL DX LOC' try: cq_call = cq[1] if len(cq) == 2: cq_loc = "" else: cq_loc = cq[2] if cq_call == "DX": cq_call = cq[2] if len(cq) > 3: cq_loc = cq[3] else: cq_loc = "" if cq_loc == "DX": if len(cq) > 3: cq_loc = cq[3] else: cq_loc = "" except: print("[!] Error parsing CQ call") continue # Check for valid callsign if (myutils.validate_callsign(cq_call)): # Have we worked call before? band = log.check_entry2(cq_call, current_band) if band["call"]: # worked call before if band["call_band"]: # ...and worked call on this band colour = bcolors.WKD_BEFORE status = log.WORKED_COUNTRY_AND_STATION elif band["country_band"]: # Worked call on a different band but # also worked country on this band colour = bcolors.WKD_COUNTRY_NOT_STATION status = log.WORKED_COUNTRY_NOT_STATION else: # TODO: check flags colour = bcolors.WKD_COUNTRY_DIFF_BAND status = log.WORKED_COUNTRY_DIFF_BAND else: # call not workedg if band["country"]: if band["country_band"]: # ...but have worked country on this band colour = bcolors.WKD_COUNTRY_NOT_STATION status = log.WORKED_COUNTRY_NOT_STATION else: # ...but have worked country before, on different band colour = bcolors.WKD_COUNTRY_DIFF_BAND status = log.WORKED_COUNTRY_DIFF_BAND else: # Call or country not worked, raise DXCC alert colour = bcolors.NOT_WORKED status = log.NOT_WORKED if config.notify_alert: if not popup_toast(log.dxcc.find_country(cq_call)): jt_curses.add_main_window('[!] Failed to notify CQ') if config.use_mqtt: mqtt_msg = json.dumps({'time': payload.now_time, 'db': str(payload.snr), 'dxcc_call': cq_call, 'dxcc_locator': cq_loc, 'dxcc_country': log.dxcc.find_country(cq_call), 'dxcc_mode': decode_mode, 'dxcc_band': decode_band, 'dialfreq': decode_dialfreq}) mqtt_client.publish("py_wsjtx/{}/dxcc".format(payload.id_key), mqtt_msg) # Now display if config.use_curses: jt_curses.add_cq(cq_call, status+1, cq_loc, log.dxcc.find_country(cq_call), band) else: print("[***] CQ CALLED BY {}{}{} ({}) [{}]".format(colour, cq_call, bcolors.ENDC, cq_loc, status)) if (myutils.validate_locator(cq_loc)): print(" [*] Distance: {:.0f}km, Bearing:{:.0f}".format( locator.calculate_distance(config.locator, cq_loc), locator.calculate_heading(config.locator, cq_loc) )) else: msg = "[*] CQ by non-valid callsign?" if config.use_curses: jt_curses.add_main_window(msg) else: print(msg) elif packet_type == PacketType.Clear: payload = Clear(data[12:]) if config.use_curses: jt_curses.add_main_window("[*] Clear Called") else: payload.do_print() elif packet_type == PacketType.Reply: # Not used, this is an out message pass elif packet_type == PacketType.QSO_Logged: # myutils.debug_packet(data) payload = Qso_Logged(data[12:]) if config.use_curses: jt_curses.add_main_window("[*] Logged QSO with {}".format(payload.dx_call)) else: payload.do_print() # re-read the log file log.read_log() elif packet_type == PacketType.Close: payload = Close(data[12:]) if config.use_curses: jt_curses.add_main_window("[!] Exit called") else: payload.do_print if config.exit_on_wsjtxexit: sys.exit(0) elif packet_type == PacketType.Replay: # Not used, this is an out message pass elif packet_type == PacketType.Halt_TX: # Not used, this is an out message pass elif packet_type == PacketType.Free_Text: # Not used, this is an out message pass elif packet_type == PacketType.WSPRDecode: payload = WSPRDecode(data[12:]) decode_band = state.get(payload.id_key, {}).get('band','???') if config.use_mqtt: mqtt_msg = json.dumps({'WSPR_call': payload.callsign, 'band': decode_band, 'grid': payload.grid, 'dist': int(payload.dist), 'pwr': payload.power, 'db': payload.snr}) mqtt_client.publish("py_wsjtx/{}/wspr".format(payload.id_key), mqtt_msg) info = "WSPR [{}]: {:10} ({:6}) db:{:4}, Freq:{:>10,}Hz, pwr:{:4}, Dist:{:>5.0f}km, Az: {:>3.0f}".format( payload.now_time, payload.callsign, payload.grid, payload.snr, payload.delta_freq, payload.power, payload.dist, payload.bearing) if config.log_decodes: out_log.write("{}\n".format(info)) if config.use_curses: jt_curses.add_main_window(info) else: payload.do_print() else: if config.use_curses: jt_curses.add_main_window("[*] Packet type: {}".format(packet_type)) else: print("[*] Packet type: {}".format(packet_type)) except KeyboardInterrupt: if config.use_curses: jt_curses.exit_now() if config.log_decodes: out_log.write("Closed Log at {}\n".format(datetime.datetime.now())) out_log.close() print("ctrl-c caught, exiting") if config.notify_alert: Notify.uninit()
configdir = os.path.expanduser('~/.config/ham-tools') with open(configdir + '/config.yaml') as f: cfg = yaml.load(f, Loader=yaml.FullLoader) address = ' '.join(sys.argv[1:]) geolocator = Nominatim(user_agent="ON3URE_hamtools") try: location = geolocator.geocode(address) locator1 = latlong_to_locator(cfg['qth']['latitude'], cfg['qth']['longitude']) locator2 = latlong_to_locator(location.latitude, location.longitude) heading = calculate_heading(locator1, locator2) longpath = calculate_heading_longpath(locator1, locator2) maidenhead = mh.to_maiden(location.latitude, location.longitude) print( fg('blue') + '-=' + fg('turquoise_4') + attr('bold') + "QTE: Bearing lookup" + attr('reset') + fg('blue') + '=-' + attr('reset')) print(fg('#884444') + attr('bold') + 'Address: ', end="") print(fg('dark_sea_green_3b') + location.address) print(fg('#884444') + attr('bold') + 'Latitude: ', end="") print(fg('dark_sea_green_3b') + "%.1f°" % location.latitude, end="") print(fg('#884444') + attr('bold') + ' Longitude: ', end="") print(fg('dark_sea_green_3b') + "%.1f°" % location.longitude, end="") print(fg('#884444') + attr('bold') + ' Grid square: ', end="") print(fg('dark_sea_green_3b') + maidenhead)