mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-08-06 02:21:42 +00:00
113 lines
4.2 KiB
Python
113 lines
4.2 KiB
Python
import logging
|
|
|
|
import simplejson
|
|
from pyhamtools.frequency import freq_to_band
|
|
|
|
from core.constants import UNKNOWN_BAND, BANDS, CW_MODES, PHONE_MODES, DATA_MODES, MODE_ALIASES, ALL_MODES
|
|
from core.data_store import DATA_STORE
|
|
from data.callsign import Callsign
|
|
|
|
|
|
def safe_json_dumps(obj):
|
|
"""Safe version of json.dumps that also converts objects to dicts so they can be output, and ignores NaN floats
|
|
which are invalid in JSON."""
|
|
|
|
return simplejson.dumps(obj, ensure_ascii=False, ignore_nan=True, default=lambda o: o.__dict__)
|
|
|
|
|
|
def infer_mode_from_comment(comment):
|
|
"""Infer a mode from the comment"""
|
|
|
|
for mode in ALL_MODES:
|
|
if mode in comment.upper():
|
|
return mode
|
|
for mode in MODE_ALIASES.keys():
|
|
if mode in comment.upper():
|
|
return MODE_ALIASES[mode]
|
|
return None
|
|
|
|
|
|
def infer_mode_type_from_mode(mode):
|
|
"""Infer a "mode family" from a mode."""
|
|
|
|
if mode.upper() in CW_MODES:
|
|
return "CW"
|
|
elif mode.upper() in PHONE_MODES:
|
|
return "PHONE"
|
|
elif mode.upper() in DATA_MODES:
|
|
return "DATA"
|
|
else:
|
|
if mode.upper() != "OTHER":
|
|
logging.warning("Found an unrecognised mode: " + mode + ". Developer should categorise this.")
|
|
return None
|
|
|
|
|
|
def infer_band_from_freq(freq):
|
|
"""Infer a band from a frequency in Hz"""
|
|
|
|
for b in BANDS:
|
|
if b.start_freq <= freq <= b.end_freq:
|
|
return b
|
|
return UNKNOWN_BAND
|
|
|
|
|
|
def infer_mode_from_frequency(freq):
|
|
"""Infer a mode from the frequency (in Hz) according to the band plan. Just a guess really."""
|
|
|
|
try:
|
|
khz = freq / 1000.0
|
|
mode = freq_to_band(khz)["mode"]
|
|
# Some additional common digimode ranges in addition to what the 3rd-party freq_to_band function returns.
|
|
# This is mostly here just because freq_to_band is very specific about things like FT8 frequencies, and e.g.
|
|
# a spot at 7074.5 kHz will be indicated as LSB, even though it's clearly in the FT8 range. Future updates
|
|
# might include other common digimode centres of activity here, but this achieves the main goal of keeping
|
|
# large numbers of clearly-FT* spots off the list of people filtering out digimodes.
|
|
if (7074 <= khz < 7077) or (10136 <= khz < 10139) or (14074 <= khz < 14077) or (18100 <= khz < 18103) or (
|
|
21074 <= khz < 21077) or (24915 <= khz < 24918) or (28074 <= khz < 28077):
|
|
mode = "FT8"
|
|
if (7047.5 <= khz < 7050.5) or (10140 <= khz < 10143) or (14080 <= khz < 14083) or (
|
|
18104 <= khz < 18107) or (21140 <= khz < 21143) or (24919 <= khz < 24922) or (28180 <= khz < 28183):
|
|
mode = "FT4"
|
|
return mode
|
|
except KeyError:
|
|
return None
|
|
|
|
|
|
def get_flag_for_dxcc(dxcc):
|
|
"""Get an emoji flag for a given DXCC entity ID"""
|
|
|
|
dxcc_data = DATA_STORE.dxcc_data[dxcc] if dxcc in DATA_STORE.dxcc_data else None
|
|
return dxcc_data["flag"] if dxcc_data else None
|
|
|
|
|
|
def get_callsign_object_from_pyhamtools_callinfo(callsign, callinfo):
|
|
"""Utility function to take the data provided by a PyHamTools CallInfo object and populate our own Callsign data
|
|
object from it"""
|
|
|
|
try:
|
|
home_call = callinfo.get_homecall(callsign)
|
|
data = callinfo.get_all(callsign)
|
|
|
|
country = data["country"] if "country" in data else None
|
|
dxcc_id = data["adif"] if "adif" in data else None
|
|
continent = data["continent"] if "continent" in data else None
|
|
cq_zone = data["cqz"] if "cqz" in data else None
|
|
itu_zone = data["ituz"] if "ituz" in data else None
|
|
lat = float(data["latitude"]) if "latitude" in data else None
|
|
lon = float(data["longitude"]) if "longitude" in data else None
|
|
|
|
return Callsign(call=callsign,
|
|
home_call=home_call,
|
|
country=country,
|
|
dxcc_id=dxcc_id,
|
|
continent=continent,
|
|
cq_zone=cq_zone,
|
|
itu_zone=itu_zone,
|
|
latitude=lat,
|
|
longitude=lon,
|
|
location_source="DXCC")
|
|
|
|
except ValueError:
|
|
# Unknown callsign, can't look anything up, return a Callsign object with basic data so that gets cached
|
|
return Callsign(call=callsign)
|