mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2025-10-27 08:49:27 +00:00
Add "de_" variants of grid/lat/lon #42
This commit is contained in:
@@ -159,7 +159,7 @@ DXCC_FLAGS = {
|
||||
107: "\U0001F1EC\U0001F1F3", # GUINEA
|
||||
108: "\U0001F1E7\U0001F1F7", # BRAZIL
|
||||
109: "\U0001F1EC\U0001F1FC", # GUINEA-BISSAU
|
||||
110: "", # HAWAII
|
||||
110: "\U0001F1FA\U0001F1F8", # HAWAII
|
||||
111: "\U0001F1ED\U0001F1F2", # HEARD ISLAND
|
||||
112: "\U0001F1E8\U0001F1F1", # CHILE
|
||||
113: "", # IFNI
|
||||
|
||||
177
data/spot.py
177
data/spot.py
@@ -10,29 +10,26 @@ from pyhamtools.locator import locator_to_latlong, latlong_to_locator
|
||||
from core.constants import DXCC_FLAGS
|
||||
from core.lookup_helper import lookup_helper
|
||||
|
||||
|
||||
# Data class that defines a spot.
|
||||
@dataclass
|
||||
class Spot:
|
||||
# Unique identifier for the spot
|
||||
id: str = None
|
||||
|
||||
|
||||
# DX (spotted) operator info
|
||||
|
||||
# Callsign of the operator that has been spotted
|
||||
dx_call: str = None
|
||||
# Callsign of the operator that has spotted them
|
||||
de_call: str = None
|
||||
# Name of the operator that has been spotted
|
||||
dx_name: str = None
|
||||
# Country of the DX operator
|
||||
dx_country: str = None
|
||||
# Country of the spotter
|
||||
de_country: str = None
|
||||
# Country flag of the DX operator
|
||||
dx_flag: str = None
|
||||
# Country flag of the spotter
|
||||
de_flag: str = None
|
||||
# Continent of the DX operator
|
||||
dx_continent: str = None
|
||||
# Continent of the spotter
|
||||
de_continent: str = None
|
||||
# DXCC ID of the DX operator
|
||||
dx_dxcc_id: int = None
|
||||
# DXCC ID of the spotter
|
||||
@@ -44,6 +41,42 @@ class Spot:
|
||||
# If this is an APRS spot, what SSID was the DX operator using?
|
||||
# This is a string not an int for now, as I often see non-numeric ones somehow
|
||||
dx_aprs_ssid: str = None
|
||||
# Maidenhead grid locator for the DX. This could be from a geographical reference e.g. POTA, or just from the
|
||||
# country
|
||||
dx_grid: str = None
|
||||
# Latitude & longitude of the DX, in degrees. This could be from a geographical reference e.g. POTA, or from a QRZ
|
||||
# lookup
|
||||
dx_latitude: float = None
|
||||
dx_longitude: float = None
|
||||
# DX Location source. Indicates how accurate the location might be. Values: "SPOT", "QRZ, "DXCC", "NONE"
|
||||
dx_location_source: str = "NONE"
|
||||
# DX Location good. Indicates that the software thinks the location data is good enough to plot on a map.
|
||||
dx_location_good: bool = False
|
||||
|
||||
|
||||
# DE (Spotter) info
|
||||
|
||||
# Callsign of the spotter
|
||||
de_call: str = None
|
||||
# Country of the spotter
|
||||
de_country: str = None
|
||||
# Country flag of the spotter
|
||||
de_flag: str = None
|
||||
# Continent of the spotter
|
||||
de_continent: str = None
|
||||
# Maidenhead grid locator for the spotter. This is not going to be from a xOTA reference so it will likely just be
|
||||
# a QRZ or DXCC lookup. If the spotter is also portable, this is probably wrong, but it's good enough for some
|
||||
# simple mapping.
|
||||
de_grid: str = None
|
||||
# Latitude & longitude of the DX, in degrees. This is not going to be from a xOTA reference so it will likely just
|
||||
# be a QRZ or DXCC lookup. If the spotter is also portable, this is probably wrong, but it's good enough for some
|
||||
# simple mapping.
|
||||
de_latitude: float = None
|
||||
de_longitude: float = None
|
||||
|
||||
|
||||
# General QSO info
|
||||
|
||||
# Reported mode, such as SSB, PHONE, CW, FT8...
|
||||
mode: str = None
|
||||
# Inferred mode "family". One of "CW", "PHONE" or "DIGI".
|
||||
@@ -54,18 +87,14 @@ class Spot:
|
||||
freq: float = None
|
||||
# Band, defined by the frequency, e.g. "40m" or "70cm"
|
||||
band: str = None
|
||||
# Time of the spot, UTC seconds since UNIX epoch
|
||||
time: float = None
|
||||
# Time of the spot, ISO 8601
|
||||
time_iso: str = None
|
||||
# Time that this software received the spot, UTC seconds since UNIX epoch. This is used with the "since_received"
|
||||
# call to our API to receive all data that is new to us, even if by a quirk of the API it might be older than the
|
||||
# list time the client polled the API.
|
||||
received_time: float = None
|
||||
# Time that this software received the spot, ISO 8601
|
||||
received_time_iso: str = None
|
||||
# Comment left by the spotter, if any
|
||||
comment: str = None
|
||||
# QRT state. Some APIs return spots marked as QRT. Otherwise we can check the comments.
|
||||
qrt: bool = False
|
||||
|
||||
|
||||
# Special Interest Group info
|
||||
|
||||
# Special Interest Group (SIG), e.g. outdoor activity programme such as POTA
|
||||
sig: str = None
|
||||
# SIG references. We allow multiple here for e.g. n-fer activations, unlike ADIF SIG_INFO
|
||||
@@ -76,17 +105,24 @@ class Spot:
|
||||
activation_score: int = None
|
||||
# Icon, from the Font Awesome set. This is fairly opinionated but is here to help the Spothole web UI and Field Spotter. Does not include the "fa-" prefix.
|
||||
icon: str = "question"
|
||||
# Maidenhead grid locator for the spot. This could be from a geographical reference e.g. POTA, or just from the country
|
||||
grid: str = None
|
||||
# Latitude & longitude, in degrees. This could be from a geographical reference e.g. POTA, or from a QRZ lookup
|
||||
latitude: float = None
|
||||
longitude: float = None
|
||||
# Location source. Indicates how accurate the location might be. Values: "SPOT", "QRZ, "DXCC", "NONE"
|
||||
location_source: str = "NONE"
|
||||
# Location good. Indicates that the software thinks the location data is good enough to plot on a map.
|
||||
location_good: bool = False
|
||||
# QRT state. Some APIs return spots marked as QRT. Otherwise we can check the comments.
|
||||
qrt: bool = False
|
||||
|
||||
|
||||
# Timing info
|
||||
|
||||
# Time of the spot, UTC seconds since UNIX epoch
|
||||
time: float = None
|
||||
# Time of the spot, ISO 8601
|
||||
time_iso: str = None
|
||||
# Time that this software received the spot, UTC seconds since UNIX epoch. This is used with the "since_received"
|
||||
# call to our API to receive all data that is new to us, even if by a quirk of the API it might be older than the
|
||||
# list time the client polled the API.
|
||||
received_time: float = None
|
||||
# Time that this software received the spot, ISO 8601
|
||||
received_time_iso: str = None
|
||||
|
||||
|
||||
# Source info
|
||||
|
||||
# Where we got the spot from, e.g. "POTA", "Cluster"...
|
||||
source: str = None
|
||||
# The ID the source gave it, if any.
|
||||
@@ -131,15 +167,17 @@ class Spot:
|
||||
if self.de_call and "-" in self.de_call:
|
||||
self.de_call = self.de_call.split("-")[0]
|
||||
|
||||
# Spotter country, continent, zones etc. from callsign
|
||||
if self.de_call and not self.de_country:
|
||||
self.de_country = lookup_helper.infer_country_from_callsign(self.de_call)
|
||||
if self.de_call and not self.de_continent:
|
||||
self.de_continent = lookup_helper.infer_continent_from_callsign(self.de_call)
|
||||
if self.de_call and not self.de_dxcc_id:
|
||||
self.de_dxcc_id = lookup_helper.infer_dxcc_id_from_callsign(self.de_call)
|
||||
if self.de_dxcc_id and self.de_dxcc_id in DXCC_FLAGS and not self.de_flag:
|
||||
self.de_flag = DXCC_FLAGS[self.de_dxcc_id]
|
||||
# Spotter country, continent, zones etc. from callsign.
|
||||
# DE of "RBNHOLE" and "SOTAMAT" are not things we can look up location for
|
||||
if self.de_call != "RBNHOLE" and self.de_call != "SOTAMAT":
|
||||
if self.de_call and not self.de_country:
|
||||
self.de_country = lookup_helper.infer_country_from_callsign(self.de_call)
|
||||
if self.de_call and not self.de_continent:
|
||||
self.de_continent = lookup_helper.infer_continent_from_callsign(self.de_call)
|
||||
if self.de_call and not self.de_dxcc_id:
|
||||
self.de_dxcc_id = lookup_helper.infer_dxcc_id_from_callsign(self.de_call)
|
||||
if self.de_dxcc_id and self.de_dxcc_id in DXCC_FLAGS and not self.de_flag:
|
||||
self.de_flag = DXCC_FLAGS[self.de_dxcc_id]
|
||||
|
||||
# Band from frequency
|
||||
if self.freq and not self.band:
|
||||
@@ -165,15 +203,15 @@ class Spot:
|
||||
if self.mode and not self.mode_type:
|
||||
self.mode_type = lookup_helper.infer_mode_type_from_mode(self.mode)
|
||||
|
||||
# Grid to lat/lon and vice versa
|
||||
if self.grid and not self.latitude:
|
||||
ll = locator_to_latlong(self.grid)
|
||||
self.latitude = ll[0]
|
||||
self.longitude = ll[1]
|
||||
if self.latitude and self.longitude and not self.grid:
|
||||
self.grid = latlong_to_locator(self.latitude, self.longitude, 8)
|
||||
if self.latitude:
|
||||
self.location_source = "SPOT"
|
||||
# DX Grid to lat/lon and vice versa
|
||||
if self.dx_grid and not self.dx_latitude:
|
||||
ll = locator_to_latlong(self.dx_grid)
|
||||
self.dx_latitude = ll[0]
|
||||
self.dx_longitude = ll[1]
|
||||
if self.dx_latitude and self.dx_longitude and not self.dx_grid:
|
||||
self.dx_grid = latlong_to_locator(self.dx_latitude, self.dx_longitude, 8)
|
||||
if self.dx_latitude:
|
||||
self.dx_location_source = "SPOT"
|
||||
|
||||
# QRT comment detection
|
||||
if self.comment and not self.qrt:
|
||||
@@ -184,26 +222,45 @@ class Spot:
|
||||
# the one from the park reference they're at.
|
||||
if self.dx_call and not self.dx_name:
|
||||
self.dx_name = lookup_helper.infer_name_from_callsign(self.dx_call)
|
||||
if self.dx_call and not self.latitude:
|
||||
if self.dx_call and not self.dx_latitude:
|
||||
latlon = lookup_helper.infer_latlon_from_callsign_qrz(self.dx_call)
|
||||
if latlon:
|
||||
self.latitude = latlon[0]
|
||||
self.longitude = latlon[1]
|
||||
self.grid = lookup_helper.infer_grid_from_callsign_qrz(self.dx_call)
|
||||
self.location_source = "QRZ"
|
||||
self.dx_latitude = latlon[0]
|
||||
self.dx_longitude = latlon[1]
|
||||
self.dx_grid = lookup_helper.infer_grid_from_callsign_qrz(self.dx_call)
|
||||
self.dx_location_source = "QRZ"
|
||||
|
||||
# Last resort for getting a position, use the DXCC entity.
|
||||
if self.dx_call and not self.latitude:
|
||||
# Last resort for getting a DX position, use the DXCC entity.
|
||||
if self.dx_call and not self.dx_latitude:
|
||||
latlon = lookup_helper.infer_latlon_from_callsign_dxcc(self.dx_call)
|
||||
if latlon:
|
||||
self.latitude = latlon[0]
|
||||
self.longitude = latlon[1]
|
||||
self.grid = lookup_helper.infer_grid_from_callsign_dxcc(self.dx_call)
|
||||
self.location_source = "DXCC"
|
||||
self.dx_latitude = latlon[0]
|
||||
self.dx_longitude = latlon[1]
|
||||
self.dx_grid = lookup_helper.infer_grid_from_callsign_dxcc(self.dx_call)
|
||||
self.dx_location_source = "DXCC"
|
||||
|
||||
# Location is "good" if it is from a spot, or from QRZ if the callsign doesn't contain a slash, so the operator
|
||||
# DX Location is "good" if it is from a spot, or from QRZ if the callsign doesn't contain a slash, so the operator
|
||||
# is likely at home.
|
||||
self.location_good = self.location_source == "SPOT" or (self.location_source == "QRZ" and not "/" in self.dx_call)
|
||||
self.dx_location_good = self.dx_location_source == "SPOT" or (
|
||||
self.dx_location_source == "QRZ" and not "/" in self.dx_call)
|
||||
|
||||
# DE of "RBNHOLE" and "SOTAMAT" are not things we can look up location for
|
||||
if self.de_call != "RBNHOLE" and self.de_call != "SOTAMAT":
|
||||
# DE operator position lookup, using QRZ.com.
|
||||
if self.de_call and not self.de_latitude:
|
||||
latlon = lookup_helper.infer_latlon_from_callsign_qrz(self.de_call)
|
||||
if latlon:
|
||||
self.de_latitude = latlon[0]
|
||||
self.de_longitude = latlon[1]
|
||||
self.de_grid = lookup_helper.infer_grid_from_callsign_qrz(self.de_call)
|
||||
|
||||
# Last resort for getting a DE position, use the DXCC entity.
|
||||
if self.de_call and not self.de_latitude:
|
||||
latlon = lookup_helper.infer_latlon_from_callsign_dxcc(self.de_call)
|
||||
if latlon:
|
||||
self.de_latitude = latlon[0]
|
||||
self.de_longitude = latlon[1]
|
||||
self.de_grid = lookup_helper.infer_grid_from_callsign_dxcc(self.de_call)
|
||||
|
||||
# Always create an ID based on a hash of every parameter *except* received_time. This is used as the index
|
||||
# to a map, which as a byproduct avoids us having multiple duplicate copies of the object that are identical
|
||||
|
||||
@@ -45,8 +45,8 @@ class APRSIS(SpotProvider):
|
||||
dx_aprs_ssid=dx_aprs_ssid,
|
||||
de_call=data["via"],
|
||||
comment=data["comment"] if "comment" in data else None,
|
||||
latitude=data["latitude"] if "latitude" in data else None,
|
||||
longitude=data["longitude"] if "longitude" in data else None,
|
||||
dx_latitude=data["latitude"] if "latitude" in data else None,
|
||||
dx_longitude=data["longitude"] if "longitude" in data else None,
|
||||
icon="tower-cell",
|
||||
time=datetime.now(pytz.UTC).timestamp()) # APRS-IS spots are live so we can assume spot time is "now"
|
||||
|
||||
|
||||
@@ -38,9 +38,9 @@ class GMA(HTTPSpotProvider):
|
||||
sig_refs_names=[source_spot["NAME"]],
|
||||
time=datetime.strptime(source_spot["DATE"] + source_spot["TIME"], "%Y%m%d%H%M").replace(
|
||||
tzinfo=pytz.UTC).timestamp(),
|
||||
latitude=float(source_spot["LAT"]) if (source_spot["LAT"] and source_spot["LAT"] != "") else None,
|
||||
dx_latitude=float(source_spot["LAT"]) if (source_spot["LAT"] and source_spot["LAT"] != "") else None,
|
||||
# Seen GMA spots with no (or empty) lat/lon
|
||||
longitude=float(source_spot["LON"]) if (source_spot["LON"] and source_spot["LON"] != "") else None)
|
||||
dx_longitude=float(source_spot["LON"]) if (source_spot["LON"] and source_spot["LON"] != "") else None)
|
||||
|
||||
# GMA doesn't give what programme (SIG) the reference is for until we separately look it up.
|
||||
ref_response = self.REF_INFO_CACHE.get(self.REF_INFO_URL_ROOT + source_spot["REF"],
|
||||
|
||||
@@ -56,8 +56,8 @@ class HEMA(HTTPSpotProvider):
|
||||
sig_refs_names=[spot_items[4]],
|
||||
icon="mound",
|
||||
time=datetime.strptime(spot_items[0], "%d/%m/%Y %H:%M").replace(tzinfo=pytz.UTC).timestamp(),
|
||||
latitude=float(spot_items[7]),
|
||||
longitude=float(spot_items[8]))
|
||||
dx_latitude=float(spot_items[7]),
|
||||
dx_longitude=float(spot_items[8]))
|
||||
|
||||
# Add to our list. Don't worry about de-duping, removing old spots etc. at this point; other code will do
|
||||
# that for us.
|
||||
|
||||
@@ -63,9 +63,9 @@ class ParksNPeaks(HTTPSpotProvider):
|
||||
siota_dr = csv.DictReader(siota_csv_data.content.decode().splitlines())
|
||||
for row in siota_dr:
|
||||
if row["SILO_CODE"] == spot.sig_refs[0]:
|
||||
spot.latitude = float(row["LAT"])
|
||||
spot.longitude = float(row["LON"])
|
||||
spot.grid = row["LOCATOR"]
|
||||
spot.dx_latitude = float(row["LAT"])
|
||||
spot.dx_longitude = float(row["LON"])
|
||||
spot.dx_grid = row["LOCATOR"]
|
||||
break
|
||||
|
||||
# ZLOTA name/lat/lon lookup
|
||||
@@ -74,8 +74,8 @@ class ParksNPeaks(HTTPSpotProvider):
|
||||
for asset in zlota_data:
|
||||
if asset["code"] == spot.sig_refs[0]:
|
||||
spot.sig_refs_names = [asset["name"]]
|
||||
spot.latitude = asset["y"]
|
||||
spot.longitude = asset["x"]
|
||||
spot.dx_latitude = asset["y"]
|
||||
spot.dx_longitude = asset["x"]
|
||||
# Junk the "DE call", PNP always returns "ZLOTA" as the spotter for ZLOTA spots
|
||||
spot.de_call = None
|
||||
break
|
||||
|
||||
@@ -31,9 +31,9 @@ class POTA(HTTPSpotProvider):
|
||||
sig_refs_names=[source_spot["name"]],
|
||||
icon="tree",
|
||||
time=datetime.strptime(source_spot["spotTime"], "%Y-%m-%dT%H:%M:%S").replace(tzinfo=pytz.UTC).timestamp(),
|
||||
grid=source_spot["grid6"],
|
||||
latitude=source_spot["latitude"],
|
||||
longitude=source_spot["longitude"])
|
||||
dx_grid=source_spot["grid6"],
|
||||
dx_latitude=source_spot["latitude"],
|
||||
dx_longitude=source_spot["longitude"])
|
||||
|
||||
# Add to our list. Don't worry about de-duping, removing old spots etc. at this point; other code will do
|
||||
# that for us.
|
||||
|
||||
@@ -58,9 +58,9 @@ class SOTA(HTTPSpotProvider):
|
||||
try:
|
||||
summit_response = self.SUMMIT_DATA_CACHE.get(self.SUMMIT_URL_ROOT + source_spot["summitCode"], headers=HTTP_HEADERS)
|
||||
summit_data = summit_response.json()
|
||||
spot.grid = summit_data["locator"]
|
||||
spot.latitude = summit_data["latitude"]
|
||||
spot.longitude = summit_data["longitude"]
|
||||
spot.dx_grid = summit_data["locator"]
|
||||
spot.dx_latitude = summit_data["latitude"]
|
||||
spot.dx_longitude = summit_data["longitude"]
|
||||
except Exception:
|
||||
logging.warn("Looking up summit " + source_spot["summitCode"] + " from the SOTA API failed. No summit data was available.")
|
||||
|
||||
|
||||
@@ -23,22 +23,22 @@ class WWBOTA(SSESpotProvider):
|
||||
ref_names.append(ref["name"])
|
||||
|
||||
spot = Spot(source=self.name,
|
||||
dx_call=source_spot["call"].upper(),
|
||||
de_call=source_spot["spotter"].upper(),
|
||||
freq=float(source_spot["freq"]) * 1000000,
|
||||
mode=source_spot["mode"].upper(),
|
||||
comment=source_spot["comment"],
|
||||
sig="WWBOTA",
|
||||
sig_refs=refs,
|
||||
sig_refs_names=ref_names,
|
||||
icon="radiation",
|
||||
time=datetime.fromisoformat(source_spot["time"]).timestamp(),
|
||||
# WWBOTA spots can contain multiple references for bunkers being activated simultaneously. For
|
||||
# now, we will just pick the first one to use as our grid, latitude and longitude.
|
||||
grid=source_spot["references"][0]["locator"],
|
||||
latitude=source_spot["references"][0]["lat"],
|
||||
longitude=source_spot["references"][0]["long"],
|
||||
qrt=source_spot["type"] == "QRT")
|
||||
dx_call=source_spot["call"].upper(),
|
||||
de_call=source_spot["spotter"].upper(),
|
||||
freq=float(source_spot["freq"]) * 1000000,
|
||||
mode=source_spot["mode"].upper(),
|
||||
comment=source_spot["comment"],
|
||||
sig="WWBOTA",
|
||||
sig_refs=refs,
|
||||
sig_refs_names=ref_names,
|
||||
icon="radiation",
|
||||
time=datetime.fromisoformat(source_spot["time"]).timestamp(),
|
||||
# WWBOTA spots can contain multiple references for bunkers being activated simultaneously. For
|
||||
# now, we will just pick the first one to use as our grid, latitude and longitude.
|
||||
dx_grid=source_spot["references"][0]["locator"],
|
||||
dx_latitude=source_spot["references"][0]["lat"],
|
||||
dx_longitude=source_spot["references"][0]["long"],
|
||||
qrt=source_spot["type"] == "QRT")
|
||||
|
||||
# WWBOTA does support a special "Test" spot type, we need to avoid adding that.
|
||||
return spot if source_spot["type"] != "Test" else None
|
||||
|
||||
@@ -31,8 +31,8 @@ class WWFF(HTTPSpotProvider):
|
||||
sig_refs_names=[source_spot["reference_name"]],
|
||||
icon="seedling",
|
||||
time=datetime.fromtimestamp(source_spot["spot_time"], tz=pytz.UTC).timestamp(),
|
||||
latitude=source_spot["latitude"],
|
||||
longitude=source_spot["longitude"])
|
||||
dx_latitude=source_spot["latitude"],
|
||||
dx_longitude=source_spot["longitude"])
|
||||
|
||||
# Add to our list. Don't worry about de-duping, removing old spots etc. at this point; other code will do
|
||||
# that for us.
|
||||
|
||||
@@ -461,10 +461,6 @@ components:
|
||||
type: string
|
||||
description: Callsign of the operator that has been spotted
|
||||
example: M0TRT
|
||||
de_call:
|
||||
type: string
|
||||
description: Callsign of the operator that has spotted them
|
||||
example: M0TEST
|
||||
dx_name:
|
||||
type: string
|
||||
description: Name of the operator that has been spotted
|
||||
@@ -473,18 +469,10 @@ components:
|
||||
type: string
|
||||
description: Country of the DX operator
|
||||
example: United Kingdom
|
||||
de_country:
|
||||
type: string
|
||||
description: Country of the spotter
|
||||
example: United Kingdom
|
||||
dx_flag:
|
||||
type: string
|
||||
description: Country flag of the DX operator
|
||||
example: ""
|
||||
de_flag:
|
||||
type: string
|
||||
description: Country flag of the spotter
|
||||
example: ""
|
||||
dx_continent:
|
||||
type: string
|
||||
description: Continent of the DX operator
|
||||
@@ -497,26 +485,10 @@ components:
|
||||
- OC
|
||||
- AN
|
||||
example: EU
|
||||
de_continent:
|
||||
type: string
|
||||
enum:
|
||||
- EU
|
||||
- NA
|
||||
- SA
|
||||
- AS
|
||||
- AF
|
||||
- OC
|
||||
- AN
|
||||
description: Continent of the spotter
|
||||
example: EU
|
||||
dx_dxcc_id:
|
||||
type: integer
|
||||
description: DXCC ID of the DX operator
|
||||
example: 235
|
||||
de_dxcc_id:
|
||||
type: integer
|
||||
description: DXCC ID of the spotter
|
||||
example: 235
|
||||
dx_cq_zone:
|
||||
type: integer
|
||||
description: CQ zone of the DX operator
|
||||
@@ -529,6 +501,71 @@ components:
|
||||
type: string
|
||||
description: If this is an APRS spot, what SSID was the DX operator using?
|
||||
example: ""
|
||||
dx_grid:
|
||||
type: string
|
||||
description: Maidenhead grid locator for the DX spot. This could be from a geographical reference e.g. POTA, or just from the country
|
||||
example: IO91aa
|
||||
dx_latitude:
|
||||
type: number
|
||||
description: Latitude of the DX spot, in degrees. This could be from a geographical reference e.g. POTA, or from a QRZ lookup
|
||||
example: 51.2345
|
||||
dx_longitude:
|
||||
type: number
|
||||
description: Longitude of the DX spot, in degrees. This could be from a geographical reference e.g. POTA, or from a QRZ lookup
|
||||
example: -1.2345
|
||||
dx_location_source:
|
||||
type: string
|
||||
description: Where we got the DX location (grid/latitude/longitude) from. If this was from the spot itself, it's likely quite accurate, but if we had to fall back to QRZ lookup, or even a location based on the DXCC itself, it will be a lot less accurate.
|
||||
enum:
|
||||
- SPOT
|
||||
- QRZ
|
||||
- DXCC
|
||||
- NONE
|
||||
example: SPOT
|
||||
dx_location_good:
|
||||
type: boolean
|
||||
description: Does the software think the location is good enough to put a marker on a map? This is true if the source is "SPOT", or alternatively if the source is "QRZ" and the callsign doesn't have a slash in it (i.e. operator likely at home).
|
||||
example: true
|
||||
de_call:
|
||||
type: string
|
||||
description: Callsign of the operator that has spotted them
|
||||
example: M0TEST
|
||||
de_country:
|
||||
type: string
|
||||
description: Country of the spotter
|
||||
example: United Kingdom
|
||||
de_flag:
|
||||
type: string
|
||||
description: Country flag of the spotter
|
||||
example: ""
|
||||
de_continent:
|
||||
type: string
|
||||
enum:
|
||||
- EU
|
||||
- NA
|
||||
- SA
|
||||
- AS
|
||||
- AF
|
||||
- OC
|
||||
- AN
|
||||
description: Continent of the spotter
|
||||
example: EU
|
||||
de_dxcc_id:
|
||||
type: integer
|
||||
description: DXCC ID of the spotter
|
||||
example: 235
|
||||
de_grid:
|
||||
type: string
|
||||
description: Maidenhead grid locator for the spotter. This is not going to be from a xOTA reference so it will likely just be a QRZ or DXCC lookup. If the spotter is also portable, this is probably wrong, but it's good enough for some simple mapping.
|
||||
example: IO91aa
|
||||
de_latitude:
|
||||
type: number
|
||||
description: Latitude of the spotter, in degrees. This is not going to be from a xOTA reference so it will likely just be a QRZ or DXCC lookup. If the spotter is also portable, this is probably wrong, but it's good enough for some simple mapping.
|
||||
example: 51.2345
|
||||
de_longitude:
|
||||
type: number
|
||||
description: Longitude of the DX spotspotter, in degrees. This is not going to be from a xOTA reference so it will likely just be a QRZ or DXCC lookup. If the spotter is also portable, this is probably wrong, but it's good enough for some simple mapping.
|
||||
example: -1.2345
|
||||
mode:
|
||||
type: string
|
||||
description: Reported mode.
|
||||
@@ -651,31 +688,6 @@ components:
|
||||
type: string
|
||||
descripton: Icon, from the Font Awesome set. This is fairly opinionated but is here to help the Spothole web UI and Field Spotter. Does not include the "fa-" prefix.
|
||||
example: tree
|
||||
grid:
|
||||
type: string
|
||||
description: Maidenhead grid locator for the spot. This could be from a geographical reference e.g. POTA, or just from the country
|
||||
example: IO91aa
|
||||
latitude:
|
||||
type: number
|
||||
description: Latitude, in degrees. This could be from a geographical reference e.g. POTA, or from a QRZ lookup
|
||||
example: 51.2345
|
||||
longitude:
|
||||
type: number
|
||||
description: Latitude, in degrees. This could be from a geographical reference e.g. POTA, or from a QRZ lookup
|
||||
example: -1.2345
|
||||
location_source:
|
||||
type: string
|
||||
description: Where we got the location (grid/latitude/longitude) from. If this was from the spot itself, it's likely quite accurate, but if we had to fall back to QRZ lookup, or even a location based on the DXCC itself, it will be a lot less accurate.
|
||||
enum:
|
||||
- SPOT
|
||||
- QRZ
|
||||
- DXCC
|
||||
- NONE
|
||||
example: SPOT
|
||||
location_good:
|
||||
type: boolean
|
||||
description: Does the software think the location is good enough to put a marker on a map? This is true if the source is "SPOT", or alternatively if the source is "QRZ" and the callsign doesn't have a slash in it (i.e. operator likely at home).
|
||||
example: true
|
||||
qrt:
|
||||
type: boolean
|
||||
description: QRT state. Some APIs return spots marked as QRT. Otherwise we can check the comments.
|
||||
|
||||
@@ -134,11 +134,11 @@ function updateTable() {
|
||||
|
||||
// Format bearing text
|
||||
var bearingText = "---<span class='bearing-q hideonmobile'><i class='fa-solid fa-circle-question' title='The position was not reported via the spotting service, and we could not determine one. A bearing to this DX is not available.'></i></span>";
|
||||
if (userPos != null && s["latitude"] != null && s["longitude"] != null) {
|
||||
var bearing = calcBearing(userPos[0], userPos[1], s["latitude"], s["longitude"]);
|
||||
if (userPos != null && s["dx_latitude"] != null && s["dx_longitude"] != null) {
|
||||
var bearing = calcBearing(userPos[0], userPos[1], s["dx_latitude"], s["dx_longitude"]);
|
||||
bearingText = bearing.toFixed(0).padStart(3, '0') + "°";
|
||||
if (s["location_good"] == null || s["location_good"] == false) {
|
||||
if (s["location_source"] == "QRZ") {
|
||||
if (s["dx_location_good"] == null || s["dx_location_good"] == false) {
|
||||
if (s["dx_location_source"] == "QRZ") {
|
||||
bearingText = bearingText + "<span class='bearing-q hideonmobile'><i class='fa-solid fa-circle-question' title='The position was not reported via the spotting service. We had to fall back to a QRZ \"home\" location for a portable/mobile/alternative spot, so this bearing may not be accurate if the DX is close to you..'></i></span>";
|
||||
} else {
|
||||
bearingText = bearingText + "<span class='bearing-q hideonmobile'><i class='fa-solid fa-circle-question' title='The position was not reported via the spotting service. We had to fall back to just using the centre of a DXCC entity, so this bearing may not be accurate if the DX is close to you.'></i></span>";
|
||||
|
||||
Reference in New Issue
Block a user