diff --git a/core/constants.py b/core/constants.py
index e4ae1ab..8b7f964 100644
--- a/core/constants.py
+++ b/core/constants.py
@@ -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
diff --git a/data/spot.py b/data/spot.py
index 0cf8b34..0b3c4ee 100644
--- a/data/spot.py
+++ b/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
@@ -217,4 +274,4 @@ class Spot:
# JSON serialise
def to_json(self):
- return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True)
\ No newline at end of file
+ return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True)
diff --git a/spotproviders/aprsis.py b/spotproviders/aprsis.py
index dd75b56..5581088 100644
--- a/spotproviders/aprsis.py
+++ b/spotproviders/aprsis.py
@@ -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"
diff --git a/spotproviders/gma.py b/spotproviders/gma.py
index ea5fc4a..f306972 100644
--- a/spotproviders/gma.py
+++ b/spotproviders/gma.py
@@ -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"],
diff --git a/spotproviders/hema.py b/spotproviders/hema.py
index 26b148c..3355a1c 100644
--- a/spotproviders/hema.py
+++ b/spotproviders/hema.py
@@ -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.
diff --git a/spotproviders/parksnpeaks.py b/spotproviders/parksnpeaks.py
index 321f8af..5348ea1 100644
--- a/spotproviders/parksnpeaks.py
+++ b/spotproviders/parksnpeaks.py
@@ -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
diff --git a/spotproviders/pota.py b/spotproviders/pota.py
index 5a59b95..ac2a90a 100644
--- a/spotproviders/pota.py
+++ b/spotproviders/pota.py
@@ -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.
diff --git a/spotproviders/sota.py b/spotproviders/sota.py
index 5380dcf..104b75d 100644
--- a/spotproviders/sota.py
+++ b/spotproviders/sota.py
@@ -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.")
diff --git a/spotproviders/wwbota.py b/spotproviders/wwbota.py
index 3c26c0a..4906089 100644
--- a/spotproviders/wwbota.py
+++ b/spotproviders/wwbota.py
@@ -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
diff --git a/spotproviders/wwff.py b/spotproviders/wwff.py
index 32e01cf..4b089f7 100644
--- a/spotproviders/wwff.py
+++ b/spotproviders/wwff.py
@@ -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.
diff --git a/webassets/apidocs/openapi.yml b/webassets/apidocs/openapi.yml
index d086c68..b0c8e7a 100644
--- a/webassets/apidocs/openapi.yml
+++ b/webassets/apidocs/openapi.yml
@@ -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.
diff --git a/webassets/js/spots.js b/webassets/js/spots.js
index 8ed78d8..8ffa820 100644
--- a/webassets/js/spots.js
+++ b/webassets/js/spots.js
@@ -134,11 +134,11 @@ function updateTable() {
// Format bearing text
var bearingText = "---";
- 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 + "";
} else {
bearingText = bearingText + "";