Improve error reporting

This commit is contained in:
Ian Renton
2026-07-25 08:53:55 +01:00
parent 66010dc682
commit c397009ada
16 changed files with 227 additions and 157 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ class HTTPAlertProvider(AlertProvider):
logging.debug("Polling " + self.name + " alert API...") logging.debug("Polling " + self.name + " alert API...")
http_response = requests.get(self._url, headers=HTTP_HEADERS, timeout=(5, 30)) http_response = requests.get(self._url, headers=HTTP_HEADERS, timeout=(5, 30))
# Check response code was good # Check response code was good
if http_response.status_code == 200: if http_response.ok:
# Pass off to the subclass for processing # Pass off to the subclass for processing
new_alerts = self._http_response_to_alerts(http_response) new_alerts = self._http_response_to_alerts(http_response)
# Submit the new alerts for processing. There might not be any alerts for the less popular programs. # Submit the new alerts for processing. There might not be any alerts for the less popular programs.
+41 -23
View File
@@ -5,7 +5,6 @@ import re
import urllib.parse import urllib.parse
from datetime import timedelta from datetime import timedelta
import requests
import xmltodict import xmltodict
from diskcache import Cache from diskcache import Cache
from pyhamtools import LookupLib, Callinfo, callinfo from pyhamtools import LookupLib, Callinfo, callinfo
@@ -143,12 +142,16 @@ class LookupHelper:
try: try:
logging.info("Downloading Country-files.com cty.plist...") logging.info("Downloading Country-files.com cty.plist...")
response = SEMI_STATIC_URL_DATA_CACHE.get("https://www.country-files.com/cty/cty.plist", response = SEMI_STATIC_URL_DATA_CACHE.get("https://www.country-files.com/cty/cty.plist",
headers=HTTP_HEADERS).text headers=HTTP_HEADERS)
with open(self._country_files_cty_plist_download_location, "w") as f: if response.ok:
f.write(response) with open(self._country_files_cty_plist_download_location, "w") as f:
f.flush() f.write(response.text)
return True f.flush()
return True
else:
logging.warning(f"HTTP {response.status_code} when downloading Country-files.com cty.plist.")
return False
except Exception as e: except Exception as e:
logging.error("Exception when downloading Clublog cty.xml", e) logging.error("Exception when downloading Clublog cty.xml", e)
@@ -161,12 +164,16 @@ class LookupHelper:
logging.info("Downloading dxcc.json...") logging.info("Downloading dxcc.json...")
response = SEMI_STATIC_URL_DATA_CACHE.get( response = SEMI_STATIC_URL_DATA_CACHE.get(
"https://raw.githubusercontent.com/k0swe/dxcc-json/refs/heads/main/dxcc.json", "https://raw.githubusercontent.com/k0swe/dxcc-json/refs/heads/main/dxcc.json",
headers=HTTP_HEADERS).text headers=HTTP_HEADERS)
with open(self._dxcc_json_download_location, "w") as f: if response.ok:
f.write(response) with open(self._dxcc_json_download_location, "w") as f:
f.flush() f.write(response.text)
return True f.flush()
return True
else:
logging.warning(f"HTTP {response.status_code} when downloading dxcc.json.")
return False
except Exception as e: except Exception as e:
logging.error("Exception when downloading dxcc.json", e) logging.error("Exception when downloading dxcc.json", e)
@@ -496,14 +503,20 @@ class LookupHelper:
for lookup_call in calls_to_try: for lookup_call in calls_to_try:
try: try:
lookup_response = requests.get( response = SEMI_STATIC_URL_DATA_CACHE.get(
self._qrz_base_url + "?s=" + session_key + "&callsign=" + urllib.parse.quote_plus(lookup_call), self._qrz_base_url + "?s=" + session_key + "&callsign=" + urllib.parse.quote_plus(lookup_call),
headers=HTTP_HEADERS, timeout=10).content headers=HTTP_HEADERS, timeout=10)
raw = xmltodict.parse(lookup_response).get("QRZDatabase", {}).get("Callsign") if response.ok:
if raw: raw = xmltodict.parse(response.content).get("QRZDatabase", {}).get("Callsign")
data = _normalize_qrz_data(raw) if raw:
self._qrz_callsign_data_cache.add(call, data, expire=604800) # 1 week in seconds data = _normalize_qrz_data(raw)
return data self._qrz_callsign_data_cache.add(call, data, expire=604800) # 1 week in seconds
return data
elif not response.from_cache:
logging.warning("Malformed response looking up callsign %s using QRZ", lookup_call)
elif not response.from_cache:
logging.warning("HTTP %d looking up callsign %s using QRZ", lookup_call)
except (KeyError, ValueError): except (KeyError, ValueError):
continue continue
except Exception: except Exception:
@@ -552,12 +565,17 @@ class LookupHelper:
for lookup_call in calls_to_try: for lookup_call in calls_to_try:
try: try:
lookup_data = SEMI_STATIC_URL_DATA_CACHE.get( response = SEMI_STATIC_URL_DATA_CACHE.get(
self._hamqth_base_url + "?id=" + session_id + "&callsign=" + urllib.parse.quote_plus( self._hamqth_base_url + "?id=" + session_id + "&callsign=" + urllib.parse.quote_plus(
lookup_call) + "&prg=" + HAMQTH_PRG, headers=HTTP_HEADERS).content lookup_call) + "&prg=" + HAMQTH_PRG, headers=HTTP_HEADERS)
data = xmltodict.parse(lookup_data)["HamQTH"]["search"] if response.ok:
self._hamqth_callsign_data_cache.add(call, data, expire=604800) # 1 week in seconds data = xmltodict.parse(response.content)["HamQTH"]["search"]
return data self._hamqth_callsign_data_cache.add(call, data, expire=604800) # 1 week in seconds
return data
elif not response.from_cache:
logging.warning("HTTP %d looking up callsign %s using HamQTH", response.status_code, lookup_call)
return None
except (KeyError, ValueError): except (KeyError, ValueError):
continue continue
except Exception: except Exception:
+153 -109
View File
@@ -45,144 +45,181 @@ def populate_sig_ref_info(sig_ref):
try: try:
if sig.upper() == "POTA": if sig.upper() == "POTA":
response = SEMI_STATIC_URL_DATA_CACHE.get("https://api.pota.app/park/" + ref_id, headers=HTTP_HEADERS) response = SEMI_STATIC_URL_DATA_CACHE.get("https://api.pota.app/park/" + ref_id, headers=HTTP_HEADERS)
if not response.ok: if response.ok:
data = response.json()
if data:
fullname = str(data["name"]) if "name" in data else None
if fullname and "parktypeDesc" in data and data["parktypeDesc"] != "":
fullname = fullname + " " + data["parktypeDesc"]
sig_ref.name = fullname
sig_ref.url = "https://pota.app/#/park/" + ref_id
sig_ref.grid = data["grid6"] if "grid6" in data else None
sig_ref.latitude = data["latitude"] if "latitude" in data else None
sig_ref.longitude = data["longitude"] if "longitude" in data else None
elif not response.from_cache:
logging.warning("Malformed response looking up %s ref %s", sig, ref_id)
elif not response.from_cache:
logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id) logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id)
data = response.json() if response.ok else None
if data:
fullname = str(data["name"]) if "name" in data else None
if fullname and "parktypeDesc" in data and data["parktypeDesc"] != "":
fullname = fullname + " " + data["parktypeDesc"]
sig_ref.name = fullname
sig_ref.url = "https://pota.app/#/park/" + ref_id
sig_ref.grid = data["grid6"] if "grid6" in data else None
sig_ref.latitude = data["latitude"] if "latitude" in data else None
sig_ref.longitude = data["longitude"] if "longitude" in data else None
elif sig.upper() == "SOTA": elif sig.upper() == "SOTA":
response = SEMI_STATIC_URL_DATA_CACHE.get("https://api-db2.sota.org.uk/api/summits/" + ref_id, response = SEMI_STATIC_URL_DATA_CACHE.get("https://api-db2.sota.org.uk/api/summits/" + ref_id,
headers=HTTP_HEADERS) headers=HTTP_HEADERS)
if not response.ok: if response.ok:
data = response.json()
if data:
sig_ref.name = data["name"] if "name" in data else None
sig_ref.url = "https://www.sotadata.org.uk/en/summit/" + ref_id
sig_ref.grid = data["locator"] if "locator" in data else None
sig_ref.latitude = data["latitude"] if "latitude" in data else None
sig_ref.longitude = data["longitude"] if "longitude" in data else None
sig_ref.activation_score = data["points"] if "points" in data else None
elif not response.from_cache:
logging.warning("Malformed response looking up %s ref %s", sig, ref_id)
elif not response.from_cache:
logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id) logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id)
data = response.json() if response.ok else None
if data:
sig_ref.name = data["name"] if "name" in data else None
sig_ref.url = "https://www.sotadata.org.uk/en/summit/" + ref_id
sig_ref.grid = data["locator"] if "locator" in data else None
sig_ref.latitude = data["latitude"] if "latitude" in data else None
sig_ref.longitude = data["longitude"] if "longitude" in data else None
sig_ref.activation_score = data["points"] if "points" in data else None
elif sig.upper() == "WWBOTA": elif sig.upper() == "WWBOTA":
response = SEMI_STATIC_URL_DATA_CACHE.get("https://api.wwbota.org/bunkers/" + ref_id, response = SEMI_STATIC_URL_DATA_CACHE.get("https://api.wwbota.org/bunkers/" + ref_id,
headers=HTTP_HEADERS) headers=HTTP_HEADERS)
if not response.ok: if response.ok:
data = response.json()
if data:
sig_ref.name = data["name"] if "name" in data else None
sig_ref.url = "https://bunkerwiki.org/?s=" + ref_id if ref_id.startswith("B/G") else None
sig_ref.grid = data["locator"] if "locator" in data else None
sig_ref.latitude = data["lat"] if "lat" in data else None
sig_ref.longitude = data["long"] if "long" in data else None
elif not response.from_cache:
logging.warning("Malformed response looking up %s ref %s", sig, ref_id)
elif not response.from_cache:
logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id) logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id)
data = response.json() if response.ok else None
if data:
sig_ref.name = data["name"] if "name" in data else None
sig_ref.url = "https://bunkerwiki.org/?s=" + ref_id if ref_id.startswith("B/G") else None
sig_ref.grid = data["locator"] if "locator" in data else None
sig_ref.latitude = data["lat"] if "lat" in data else None
sig_ref.longitude = data["long"] if "long" in data else None
elif sig.upper() == "GMA" or sig.upper() == "ARLHS" or sig.upper() == "ILLW" or sig.upper() == "WCA" or sig.upper() == "MOTA" or sig.upper() == "IOTA": elif sig.upper() == "GMA" or sig.upper() == "ARLHS" or sig.upper() == "ILLW" or sig.upper() == "WCA" or sig.upper() == "MOTA" or sig.upper() == "IOTA":
response = SEMI_STATIC_URL_DATA_CACHE.get("https://www.cqgma.org/api/ref/?" + ref_id, response = SEMI_STATIC_URL_DATA_CACHE.get("https://www.cqgma.org/api/ref/?" + ref_id,
headers=HTTP_HEADERS) headers=HTTP_HEADERS)
if not response.ok: if response.ok:
data = response.json()
if data:
sig_ref.name = data["name"] if "name" in data else None
sig_ref.url = "https://www.cqgma.org/zinfo.php?ref=" + ref_id
sig_ref.grid = data["locator"] if "locator" in data else None
sig_ref.latitude = data["latitude"] if "latitude" in data else None
sig_ref.longitude = data["longitude"] if "longitude" in data else None
elif not response.from_cache:
logging.warning("Malformed response looking up %s ref %s via GMA", sig, ref_id)
elif not response.from_cache:
logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id) logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id)
data = response.json() if response.ok else None
if data:
sig_ref.name = data["name"] if "name" in data else None
sig_ref.url = "https://www.cqgma.org/zinfo.php?ref=" + ref_id
sig_ref.grid = data["locator"] if "locator" in data else None
sig_ref.latitude = data["latitude"] if "latitude" in data else None
sig_ref.longitude = data["longitude"] if "longitude" in data else None
elif sig.upper() == "WWFF": elif sig.upper() == "WWFF":
wwff_response = SEMI_STATIC_URL_DATA_CACHE.get("https://wwff.co/wwff-data/wwff_directory.csv", response = SEMI_STATIC_URL_DATA_CACHE.get("https://wwff.co/wwff-data/wwff_directory.csv",
headers=HTTP_HEADERS) headers=HTTP_HEADERS)
if not wwff_response.ok: if response.ok:
logging.warning("HTTP %d looking up %s ref %s", wwff_response.status_code, sig, ref_id) wwff_index = {row["reference"]: row for row in csv.DictReader(response.content.decode().splitlines())}
return sig_ref row = wwff_index.get(ref_id)
wwff_index = {row["reference"]: row for row in csv.DictReader(wwff_response.content.decode().splitlines())} if row:
row = wwff_index.get(ref_id) sig_ref.name = row["name"] if "name" in row else None
if row: sig_ref.url = "https://wwff.co/directory/?showRef=" + ref_id
sig_ref.name = row["name"] if "name" in row else None sig_ref.grid = row["iaruLocator"] if "iaruLocator" in row and row["iaruLocator"] != "-" else None
sig_ref.url = "https://wwff.co/directory/?showRef=" + ref_id sig_ref.latitude = float(row["latitude"]) if "latitude" in row and row["latitude"] != "-" else None
sig_ref.grid = row["iaruLocator"] if "iaruLocator" in row and row["iaruLocator"] != "-" else None sig_ref.longitude = float(row["longitude"]) if "longitude" in row and row[
sig_ref.latitude = float(row["latitude"]) if "latitude" in row and row["latitude"] != "-" else None "longitude"] != "-" else None
sig_ref.longitude = float(row["longitude"]) if "longitude" in row and row["longitude"] != "-" else None elif not response.from_cache:
logging.warning("WWFF database did not contain data for ref %s", ref_id)
elif not response.from_cache:
logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id)
elif sig.upper() == "SIOTA": elif sig.upper() == "SIOTA":
siota_response = SEMI_STATIC_URL_DATA_CACHE.get("https://www.silosontheair.com/data/silos.csv", response = SEMI_STATIC_URL_DATA_CACHE.get("https://www.silosontheair.com/data/silos.csv",
headers=HTTP_HEADERS) headers=HTTP_HEADERS)
if not siota_response.ok: if response.ok:
logging.warning("HTTP %d looking up %s ref %s", siota_response.status_code, sig, ref_id) siota_index = {row["SILO_CODE"]: row for row in
return sig_ref csv.DictReader(response.content.decode().splitlines())}
siota_index = {row["SILO_CODE"]: row for row in row = siota_index.get(ref_id)
csv.DictReader(siota_response.content.decode().splitlines())} if row:
row = siota_index.get(ref_id) sig_ref.name = row["NAME"] if "NAME" in row else None
if row: sig_ref.grid = row["LOCATOR"] if "LOCATOR" in row else None
sig_ref.name = row["NAME"] if "NAME" in row else None sig_ref.latitude = float(row["LAT"]) if "LAT" in row else None
sig_ref.grid = row["LOCATOR"] if "LOCATOR" in row else None sig_ref.longitude = float(row["LNG"]) if "LNG" in row else None
sig_ref.latitude = float(row["LAT"]) if "LAT" in row else None elif not response.from_cache:
sig_ref.longitude = float(row["LNG"]) if "LNG" in row else None logging.warning("SIOTA database did not contain data for ref %s", ref_id)
elif not response.from_cache:
logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id)
elif sig.upper() == "WOTA": elif sig.upper() == "WOTA":
response = SEMI_STATIC_URL_DATA_CACHE.get("https://www.wota.org.uk/mapping/data/summits.json", response = SEMI_STATIC_URL_DATA_CACHE.get("https://www.wota.org.uk/mapping/data/summits.json",
headers=HTTP_HEADERS) headers=HTTP_HEADERS)
if not response.ok: if response.ok:
data = response.json()
if data:
for feature in data.get("features", []):
if feature["properties"]["wotaId"] == ref_id:
sig_ref.name = feature["properties"]["title"]
# Fudge WOTA URLs. Outlying fell (LDO) URLs don't match their ID numbers but require 214 to be
# added to them
sig_ref.url = "https://www.wota.org.uk/MM_" + ref_id
if ref_id.upper().startswith("LDO-"):
number = int(ref_id.upper().replace("LDO-", ""))
sig_ref.url = "https://www.wota.org.uk/MM_LDO-" + str(number + 214)
sig_ref.grid = feature["properties"]["qthLocator"]
sig_ref.latitude = feature["geometry"]["coordinates"][1]
sig_ref.longitude = feature["geometry"]["coordinates"][0]
break
elif not response.from_cache:
logging.warning("Malformed response looking up %s ref %s", sig, ref_id)
elif not response.from_cache:
logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id) logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id)
data = response.json() if response.ok else None
if data:
for feature in data.get("features", []):
if feature["properties"]["wotaId"] == ref_id:
sig_ref.name = feature["properties"]["title"]
# Fudge WOTA URLs. Outlying fell (LDO) URLs don't match their ID numbers but require 214 to be
# added to them
sig_ref.url = "https://www.wota.org.uk/MM_" + ref_id
if ref_id.upper().startswith("LDO-"):
number = int(ref_id.upper().replace("LDO-", ""))
sig_ref.url = "https://www.wota.org.uk/MM_LDO-" + str(number + 214)
sig_ref.grid = feature["properties"]["qthLocator"]
sig_ref.latitude = feature["geometry"]["coordinates"][1]
sig_ref.longitude = feature["geometry"]["coordinates"][0]
break
elif sig.upper() == "ZLOTA": elif sig.upper() == "ZLOTA":
response = SEMI_STATIC_URL_DATA_CACHE.get("https://ontheair.nz/assets/assets.json", headers=HTTP_HEADERS) response = SEMI_STATIC_URL_DATA_CACHE.get("https://ontheair.nz/assets/assets.json", headers=HTTP_HEADERS)
if not response.ok: if response.ok:
data = response.json()
if isinstance(data, list):
for asset in data:
if asset["code"] == ref_id:
sig_ref.name = asset["name"]
sig_ref.url = "https://ontheair.nz/assets/" + ref_id.replace("/", "_")
try:
sig_ref.grid = latlong_to_locator(asset["y"], asset["x"], 6)
except:
logging.debug("Invalid lat/lon received for reference")
sig_ref.latitude = asset["y"]
sig_ref.longitude = asset["x"]
break
elif not response.from_cache:
logging.warning("Malformed response looking up %s ref %s", sig, ref_id)
elif not response.from_cache:
logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id) logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id)
data = response.json() if response.ok else None
if isinstance(data, list):
for asset in data:
if asset["code"] == ref_id:
sig_ref.name = asset["name"]
sig_ref.url = "https://ontheair.nz/assets/ZLI_OT-030" + ref_id.replace("/", "_")
try:
sig_ref.grid = latlong_to_locator(asset["y"], asset["x"], 6)
except:
logging.debug("Invalid lat/lon received for reference")
sig_ref.latitude = asset["y"]
sig_ref.longitude = asset["x"]
break
elif sig.upper() == "BOTA": elif sig.upper() == "BOTA":
if not sig_ref.name: if not sig_ref.name:
sig_ref.name = sig_ref.id sig_ref.name = sig_ref.id
sig_ref.url = "https://www.beachesontheair.com/beaches/" + sig_ref.name.lower().replace(" ", "-") sig_ref.url = "https://www.beachesontheair.com/beaches/" + sig_ref.name.lower().replace(" ", "-")
elif sig.upper() == "LLOTA": elif sig.upper() == "LLOTA":
response = SEMI_STATIC_URL_DATA_CACHE.get("https://llota.app/api/public/references", response = SEMI_STATIC_URL_DATA_CACHE.get("https://llota.app/api/public/references",
headers=HTTP_HEADERS) headers=HTTP_HEADERS)
if not response.ok: if response.ok:
data = response.json()
if isinstance(data, list):
for ref in data:
if ref["reference_code"] == ref_id:
sig_ref.name = str(ref["name"])
sig_ref.url = "https://llota.app/list/ref/" + ref_id
sig_ref.grid = str(ref["grid_locator"])
ll = locator_to_latlong(sig_ref.grid)
sig_ref.latitude = ll[0]
sig_ref.longitude = ll[1]
break
elif not response.from_cache:
logging.warning("Malformed response looking up %s ref %s", sig, ref_id)
elif not response.from_cache:
logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id) logging.warning("HTTP %d looking up %s ref %s", response.status_code, sig, ref_id)
data = response.json() if response.ok else None
if isinstance(data, list):
for ref in data:
if ref["reference_code"] == ref_id:
sig_ref.name = str(ref["name"])
sig_ref.url = "https://llota.app/list/ref/" + ref_id
sig_ref.grid = str(ref["grid_locator"])
ll = locator_to_latlong(sig_ref.grid)
sig_ref.latitude = ll[0]
sig_ref.longitude = ll[1]
break
elif sig.upper() == "WWTOTA": elif sig.upper() == "WWTOTA":
if not sig_ref.name: if not sig_ref.name:
sig_ref.name = sig_ref.id sig_ref.name = sig_ref.id
sig_ref.url = "https://wwtota.com/seznam/karta_rozhledny.php?ref=" + str(sig_ref.name) sig_ref.url = "https://wwtota.com/seznam/karta_rozhledny.php?ref=" + str(sig_ref.name)
elif sig.upper() == "TILES": elif sig.upper() == "TILES":
# Tiles on the Air just uses Maidenhead 6-digit squares, so ID, Name and Grid are all the same # Tiles on the Air just uses Maidenhead 6-digit squares, so ID, Name and Grid are all the same
if not sig_ref.name: if not sig_ref.name:
@@ -193,6 +230,7 @@ def populate_sig_ref_info(sig_ref):
ll = locator_to_latlong(str(sig_ref.grid)) ll = locator_to_latlong(str(sig_ref.grid))
sig_ref.latitude = ll[0] sig_ref.latitude = ll[0]
sig_ref.longitude = ll[1] sig_ref.longitude = ll[1]
elif sig.upper() == "WAB" or sig.upper() == "WAI": elif sig.upper() == "WAB" or sig.upper() == "WAI":
ll = wab_wai_square_to_lat_lon(ref_id) ll = wab_wai_square_to_lat_lon(ref_id)
if ll: if ll:
@@ -202,21 +240,27 @@ def populate_sig_ref_info(sig_ref):
sig_ref.latitude = ll[0] sig_ref.latitude = ll[0]
sig_ref.longitude = ll[1] sig_ref.longitude = ll[1]
except: except:
logging.debug("Invalid lat/lon received for reference") logging.warning("Invalid lat/lon received for WAB/WAI reference")
elif sig.upper() == "DME": elif sig.upper() == "DME":
# Zero-pad to 5 digits to match our source data # Zero-pad to 5 digits to match our source data
row = _DME_INDEX.get(ref_id.zfill(5)) row = _DME_INDEX.get(ref_id.zfill(5))
if row: if row:
sig_ref.name = row["NOMBRE_ACTUAL"] + ", " + row["PROVINCIA"] sig_ref.name = row["NOMBRE_ACTUAL"] + ", " + row["PROVINCIA"]
sig_ref.latitude = float(row["LATITUD_ETRS89_REGCAN95"].replace(",", ".")) if row.get("LATITUD_ETRS89_REGCAN95") else None sig_ref.latitude = float(row["LATITUD_ETRS89_REGCAN95"].replace(",", ".")) if row.get(
sig_ref.longitude = float(row["LONGITUD_ETRS89_REGCAN95"].replace(",", ".")) if row.get("LONGITUD_ETRS89_REGCAN95") else None "LATITUD_ETRS89_REGCAN95") else None
sig_ref.longitude = float(row["LONGITUD_ETRS89_REGCAN95"].replace(",", ".")) if row.get(
"LONGITUD_ETRS89_REGCAN95") else None
if sig_ref.latitude and sig_ref.longitude: if sig_ref.latitude and sig_ref.longitude:
try: try:
sig_ref.grid = latlong_to_locator(sig_ref.latitude, sig_ref.longitude, 6) sig_ref.grid = latlong_to_locator(sig_ref.latitude, sig_ref.longitude, 6)
except Exception: except Exception:
logging.debug("Invalid lat/lon received for reference") logging.warning("Invalid lat/lon received for DME reference")
else:
logging.warning("DME database did not contain data for ref %s", ref_id)
except Exception: except Exception:
logging.warning("Failed to look up sig_ref info for " + sig + " ref " + ref_id, exc_info=True) logging.warning("Exception when looking up sig_ref info for " + sig + " ref " + ref_id, exc_info=True)
return sig_ref return sig_ref
+1 -1
View File
@@ -128,7 +128,7 @@ class GIROIonosonde(SolarConditionsProvider):
to_str = to_time.strftime("%Y.%m.%d+%H:%M:%S") to_str = to_time.strftime("%Y.%m.%d+%H:%M:%S")
url = f"{LGDC_URL}?ursiCode={ursi}&charName=foF2,MUFD,fmin&DMUF=3000&fromDate={from_str}&toDate={to_str}" url = f"{LGDC_URL}?ursiCode={ursi}&charName=foF2,MUFD,fmin&DMUF=3000&fromDate={from_str}&toDate={to_str}"
http_response = requests.get(url, headers=HTTP_HEADERS, timeout=(5, 15)) http_response = requests.get(url, headers=HTTP_HEADERS, timeout=(5, 15))
if http_response.status_code != 200: if not http_response.ok:
logging.warning(f"HTTP {http_response.status_code} when calling Giro ionosonde API.") logging.warning(f"HTTP {http_response.status_code} when calling Giro ionosonde API.")
return None, None, None return None, None, None
return self._parse_all(http_response.text) return self._parse_all(http_response.text)
@@ -40,7 +40,7 @@ class HTTPSolarConditionsProvider(SolarConditionsProvider):
logging.debug("Polling " + self.name + " solar conditions API...") logging.debug("Polling " + self.name + " solar conditions API...")
http_response = requests.get(self._url, headers=HTTP_HEADERS, timeout=(5, 30)) http_response = requests.get(self._url, headers=HTTP_HEADERS, timeout=(5, 30))
# Check response code was good # Check response code was good
if http_response.status_code == 200: if http_response.ok:
new_data = self._http_response_to_solar_conditions(http_response) new_data = self._http_response_to_solar_conditions(http_response)
self.update_data(new_data) self.update_data(new_data)
+1 -1
View File
@@ -45,7 +45,7 @@ class KC2GProp(SolarConditionsProvider):
try: try:
logging.debug("Polling KC2G ionosonde data...") logging.debug("Polling KC2G ionosonde data...")
http_response = requests.get(KC2G_URL, headers=HTTP_HEADERS, timeout=(5, 30)) http_response = requests.get(KC2G_URL, headers=HTTP_HEADERS, timeout=(5, 30))
if http_response.status_code != 200: if not http_response.ok:
logging.warning(f"HTTP {http_response.status_code} when calling KG2G ionosonde API.") logging.warning(f"HTTP {http_response.status_code} when calling KG2G ionosonde API.")
return return
+13 -5
View File
@@ -39,7 +39,7 @@ class GMA(HTTPSpotProvider):
de_call=source_spot["SPOTTER"].upper(), de_call=source_spot["SPOTTER"].upper(),
# Seen GMA spots with no frequency or with "QRT" in this field # Seen GMA spots with no frequency or with "QRT" in this field
freq=float(source_spot["QRG"]) * 1000 if ( freq=float(source_spot["QRG"]) * 1000 if (
source_spot["QRG"] != "" and source_spot["QRG"] != "QRT") else None, source_spot["QRG"] != "" and source_spot["QRG"] != "QRT") else None,
# Filter out some weird mode strings # Filter out some weird mode strings
mode=source_spot["MODE"].upper() if "<>" not in source_spot["MODE"] else None, mode=source_spot["MODE"].upper() if "<>" not in source_spot["MODE"] else None,
comment=source_spot["TEXT"], comment=source_spot["TEXT"],
@@ -58,8 +58,8 @@ class GMA(HTTPSpotProvider):
try: try:
ref_response = SEMI_STATIC_URL_DATA_CACHE.get(self.REF_INFO_URL_ROOT + source_spot["REF"], ref_response = SEMI_STATIC_URL_DATA_CACHE.get(self.REF_INFO_URL_ROOT + source_spot["REF"],
headers=HTTP_HEADERS) headers=HTTP_HEADERS)
# Sometimes this is blank, so handle that # Sometimes this is blank even if it's a 200 response, so handle that
if ref_response.text is not None and ref_response.text != "": if ref_response.ok and ref_response.text is not None and ref_response.text != "":
ref_info = ref_response.json() ref_info = ref_response.json()
# If this is POTA, SOTA or WWFF data we already have it through other means, so ignore. POTA and WWFF # If this is POTA, SOTA or WWFF data we already have it through other means, so ignore. POTA and WWFF
# spots come through with reftype=POTA or reftype=WWFF. SOTA is harder to figure out because both SOTA # spots come through with reftype=POTA or reftype=WWFF. SOTA is harder to figure out because both SOTA
@@ -94,9 +94,17 @@ class GMA(HTTPSpotProvider):
spot.sig_refs[0].sig = ref_info["reftype"] spot.sig_refs[0].sig = ref_info["reftype"]
spot.sig = ref_info["reftype"] spot.sig = ref_info["reftype"]
# Add to our list. Don't worry about de-duping, removing old spots etc. at this point; other code will do # Add to our list. Don't worry about de-duping, removing old spots etc. at this point;
# that for us. # other code will do that for us.
new_spots.append(spot) new_spots.append(spot)
elif not ref_response.from_cache:
if not ref_response.ok:
logging.warning(
f"HTTP {ref_response.status_code} when looking up GMA ref {source_spot["REF"]}")
else:
logging.warning(
f"GMA API returned a malformed response when looking up ref {source_spot["REF"]}")
except: except:
logging.warning("Exception when looking up " + self.REF_INFO_URL_ROOT + source_spot[ logging.warning("Exception when looking up " + self.REF_INFO_URL_ROOT + source_spot[
"REF"] + ", ignoring this spot for now") "REF"] + ", ignoring this spot for now")
+1 -1
View File
@@ -42,7 +42,7 @@ class HTTPSpotProvider(SpotProvider):
logging.debug("Polling " + self.name + " spot API...") logging.debug("Polling " + self.name + " spot API...")
http_response = requests.get(self._url, headers=HTTP_HEADERS, timeout=(5, 30)) http_response = requests.get(self._url, headers=HTTP_HEADERS, timeout=(5, 30))
# Check response code was good # Check response code was good
if http_response.status_code == 200: if http_response.ok:
# Pass off to the subclass for processing # Pass off to the subclass for processing
new_spots = self._http_response_to_spots(http_response) new_spots = self._http_response_to_spots(http_response)
# Submit the new spots for processing. There might not be any spots for the less popular programs. # Submit the new spots for processing. There might not be any spots for the less popular programs.
+1 -1
View File
@@ -76,7 +76,7 @@
</div> </div>
<script src="/js/add-spot.js?v=1784964562"></script> <script src="/js/add-spot.js?v=1784966035"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-add-spot").addClass("active"); $("#nav-link-add-spot").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+1 -1
View File
@@ -75,7 +75,7 @@
</div> </div>
<script src="/js/alerts.js?v=1784964563"></script> <script src="/js/alerts.js?v=1784966035"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-alerts").addClass("active"); $("#nav-link-alerts").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+2 -2
View File
@@ -75,8 +75,8 @@
<script> <script>
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %}; let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
</script> </script>
<script src="/js/spotsbandsandmap.js?v=1784964562"></script> <script src="/js/spotsbandsandmap.js?v=1784966035"></script>
<script src="/js/bands.js?v=1784964562"></script> <script src="/js/bands.js?v=1784966035"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-bands").addClass("active"); $("#nav-link-bands").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+5 -5
View File
@@ -1,6 +1,6 @@
{% extends "skeleton.html" %} {% extends "skeleton.html" %}
{% block head_extra %} {% block head_extra %}
<link rel="stylesheet" href="/css/style.css?v=1784964562" type="text/css"> <link rel="stylesheet" href="/css/style.css?v=1784966035" type="text/css">
<link href="/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet"> <link href="/vendor/css/bootstrap-5.3.8.min.css" rel="stylesheet">
<link href="/vendor/css/fontawesome-6.7.2.min.css" rel="stylesheet"> <link href="/vendor/css/fontawesome-6.7.2.min.css" rel="stylesheet">
<link href="/vendor/css/solid-6.7.2.min.css" rel="stylesheet"> <link href="/vendor/css/solid-6.7.2.min.css" rel="stylesheet">
@@ -10,10 +10,10 @@
<script src="/vendor/js/bootstrap-5.3.8.bundle.min.js"></script> <script src="/vendor/js/bootstrap-5.3.8.bundle.min.js"></script>
<script src="/vendor/js/tinycolor2-1.6.0.min.js"></script> <script src="/vendor/js/tinycolor2-1.6.0.min.js"></script>
<script src="/js/utils.js?v=1784964562"></script> <script src="/js/utils.js?v=1784966035"></script>
<script src="/js/ui-ham.js?v=1784964562"></script> <script src="/js/ui-ham.js?v=1784966035"></script>
<script src="/js/geo.js?v=1784964562"></script> <script src="/js/geo.js?v=1784966035"></script>
<script src="/js/common.js?v=1784964562"></script> <script src="/js/common.js?v=1784966035"></script>
{% end %} {% end %}
{% block body %} {% block body %}
<div class="container"> <div class="container">
+1 -1
View File
@@ -284,7 +284,7 @@
</div> </div>
<script src="/vendor/js/chart-4.4.9.umd.min.js"></script> <script src="/vendor/js/chart-4.4.9.umd.min.js"></script>
<script src="/js/conditions.js?v=1784964562"></script> <script src="/js/conditions.js?v=1784966035"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-conditions").addClass("active"); $("#nav-link-conditions").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+2 -2
View File
@@ -95,8 +95,8 @@
<script> <script>
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %}; let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
</script> </script>
<script src="/js/spotsbandsandmap.js?v=1784964563"></script> <script src="/js/spotsbandsandmap.js?v=1784966035"></script>
<script src="/js/map.js?v=1784964563"></script> <script src="/js/map.js?v=1784966035"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-map").addClass("active"); $("#nav-link-map").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+2 -2
View File
@@ -116,8 +116,8 @@
<script> <script>
let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %}; let spotProvidersEnabledByDefault = {% raw json_encode(web_ui_options["spot-providers-enabled-by-default"]) %};
</script> </script>
<script src="/js/spotsbandsandmap.js?v=1784964562"></script> <script src="/js/spotsbandsandmap.js?v=1784966035"></script>
<script src="/js/spots.js?v=1784964562"></script> <script src="/js/spots.js?v=1784966035"></script>
<script>$(document).ready(function () { <script>$(document).ready(function () {
$("#nav-link-spots").addClass("active"); $("#nav-link-spots").addClass("active");
}); <!-- highlight active page in nav --></script> }); <!-- highlight active page in nav --></script>
+1 -1
View File
@@ -59,7 +59,7 @@
</div> </div>
</div> </div>
<script src="/js/status.js?v=1784964562"></script> <script src="/js/status.js?v=1784966035"></script>
<script> <script>
$(document).ready(function () { $(document).ready(function () {
$("#nav-link-status").addClass("active"); $("#nav-link-status").addClass("active");