Add options API #15

This commit is contained in:
Ian Renton
2025-09-30 21:29:17 +01:00
parent 37692f41a8
commit 4f4c1a9191
5 changed files with 658540 additions and 4 deletions

View File

@@ -4,11 +4,18 @@ from data.band import Band
SOFTWARE_NAME = "Metaspot by M0TRT" SOFTWARE_NAME = "Metaspot by M0TRT"
SOFTWARE_VERSION = "0.1" SOFTWARE_VERSION = "0.1"
# Modes # Sources
SOURCES = ["POTA", "SOTA", "WWFF", "GMA", "WWBOTA", "HEMA", "ParksNPeaks", "Cluster", "RBN", "APRS-IS"]
# Special Interest Groups
SIGS = ["POTA", "SOTA", "WWFF", "GMA", "WWBOTA", "HEMA", "MOTA", "ARLHS", "SiOTA", "WCA"]
# Modes. Note "DIGI" and "DIGITAL" are also supported but are normalised into "DATA".
CW_MODES = ["CW"] CW_MODES = ["CW"]
PHONE_MODES = ["PHONE", "SSB", "USB", "LSB", "AM", "FM", "DV", "DMR", "DSTAR", "C4FM", "M17"] PHONE_MODES = ["PHONE", "SSB", "USB", "LSB", "AM", "FM", "DV", "DMR", "DSTAR", "C4FM", "M17"]
DATA_MODES = ["DIGI", "DATA", "DIGITAL", "FT8", "FT4", "RTTY", "SSTV", "JS8", "HELL", "BPSK", "PSK", "BPSK31", "OLIVIA"] DATA_MODES = ["DATA", "FT8", "FT4", "RTTY", "SSTV", "JS8", "HELL", "BPSK", "PSK", "BPSK31", "OLIVIA"]
ALL_MODES = CW_MODES + PHONE_MODES + DATA_MODES ALL_MODES = CW_MODES + PHONE_MODES + DATA_MODES
MODE_TYPES = ["CW", "PHONE", "DATA"]
# Band definitions # Band definitions
BANDS = [ BANDS = [
@@ -30,6 +37,9 @@ BANDS = [
Band(name="13cm", start_freq=2300000, end_freq=2450000, color="#FF7F50", contrast_color="black")] Band(name="13cm", start_freq=2300000, end_freq=2450000, color="#FF7F50", contrast_color="black")]
UNKNOWN_BAND = Band(name="Unknown", start_freq=0, end_freq=0, color="black", contrast_color="white") UNKNOWN_BAND = Band(name="Unknown", start_freq=0, end_freq=0, color="black", contrast_color="white")
# Continents
CONTINENTS=["EU", "NA", "SA", "AS", "AF", "OC", "AN"]
# DXCC flags (borrowed from https:#github.com/wavelog/wavelog/blob/master/application/libraries/DxccFlag.php) # DXCC flags (borrowed from https:#github.com/wavelog/wavelog/blob/master/application/libraries/DxccFlag.php)
DXCC_FLAGS = { DXCC_FLAGS = {
0: "", # DXCC NONE 0: "", # DXCC NONE

View File

@@ -10,7 +10,7 @@ from core.config import config
from core.constants import BANDS, UNKNOWN_BAND, CW_MODES, PHONE_MODES, DATA_MODES, ALL_MODES from core.constants import BANDS, UNKNOWN_BAND, CW_MODES, PHONE_MODES, DATA_MODES, ALL_MODES
# Lookup helpers from pyhamtools # Lookup helpers from pyhamtools
LOOKUP_LIB_BASIC = LookupLib(lookuptype="countryfile") LOOKUP_LIB_BASIC = LookupLib(lookuptype="countryfile", filename="cty.plist")
CALL_INFO_BASIC = Callinfo(LOOKUP_LIB_BASIC) CALL_INFO_BASIC = Callinfo(LOOKUP_LIB_BASIC)
QRZ_AVAILABLE = config["qrz-password"] != "" QRZ_AVAILABLE = config["qrz-password"] != ""
if QRZ_AVAILABLE: if QRZ_AVAILABLE:

658427
cty.plist Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@ import bottle
import pytz import pytz
from bottle import run, response from bottle import run, response
from core.constants import BANDS, ALL_MODES, MODE_TYPES, SIGS, SOURCES, CONTINENTS
from core.utils import serialize_everything from core.utils import serialize_everything
@@ -26,6 +27,7 @@ class WebServer:
# Set up routing # Set up routing
bottle.get("/api/spots")(self.serve_api_spots) bottle.get("/api/spots")(self.serve_api_spots)
bottle.get("/api/options")(self.serve_api_options)
bottle.get("/api/status")(self.serve_api_status) bottle.get("/api/status")(self.serve_api_status)
bottle.get("/")(self.serve_index) bottle.get("/")(self.serve_index)
bottle.get("/apidocs")(self.serve_apidocs) bottle.get("/apidocs")(self.serve_apidocs)
@@ -49,6 +51,14 @@ class WebServer:
response.content_type = 'application/json' response.content_type = 'application/json'
return spots_json return spots_json
# Options API
def serve_api_options(self):
self.last_api_access_time = datetime.now(pytz.UTC)
self.status = "OK"
status_json = json.dumps(self.get_options(), default=serialize_everything)
response.content_type = 'application/json'
return status_json
# Server status API # Server status API
def serve_api_status(self): def serve_api_status(self):
self.last_api_access_time = datetime.now(pytz.UTC) self.last_api_access_time = datetime.now(pytz.UTC)
@@ -118,3 +128,14 @@ class WebServer:
if "limit" in query.keys(): if "limit" in query.keys():
spots = spots[:int(query.get("limit"))] spots = spots[:int(query.get("limit"))]
return spots return spots
# Return all the "options" for various things that the server is aware of. This can be fetched with an API call.
# The idea is that this will include most of the things that can be provided as queries to the main spots call,
# and thus a client can use this data to configure its filter controls.
def get_options(self):
return {"bands": BANDS,
"modes": ALL_MODES,
"mode_types": MODE_TYPES,
"sigs": SIGS,
"sources": SOURCES,
"continents": CONTINENTS}

View File

@@ -169,6 +169,8 @@ paths:
type: array type: array
items: items:
$ref: '#/components/schemas/Spot' $ref: '#/components/schemas/Spot'
/status: /status:
get: get:
tags: tags:
@@ -228,6 +230,58 @@ paths:
items: items:
$ref: '#/components/schemas/ProviderStatus' $ref: '#/components/schemas/ProviderStatus'
/options:
get:
tags:
- spots
summary: Retieve a list of options for various enumerations.
description: Retrieves the list of options for various enumerated types, which can be found in the spots and also provided back to the API as query parameters. While these enumerated options are defined in this spec anyway, providing them in an API call allows us to define extra parameters, like the colours associated with bands, and also allows clients to set up their filters and features without having to have internal knowledge about, for example, what bands the server knows about.
operationId: options
responses:
'200':
description: Successfully retrieved options.
content:
application/json:
schema:
type: object
properties:
bands:
type: array
description: An array of all the supported bands.
items:
$ref: '#/components/schemas/Band'
modes:
type: array
description: An array of all the supported modes.
items:
type: string
example: "LSB"
mode_types:
type: array
description: An array of all the supported mode types.
items:
type: string
example: "PHONE"
sigs:
type: array
description: An array of all the supported Special Interest Groups.
items:
type: string
example: "POTA"
sources:
type: array
description: An array of all the supported data sources (providers).
items:
type: string
example: "Cluster"
continents:
type: array
description: An array of all the supported continents.
items:
type: string
example: "EU"
components: components:
schemas: schemas:
Spot: Spot:
@@ -486,4 +540,28 @@ components:
last_spot: last_spot:
type: string type: string
description: The time of the latest spot received by this provider. description: The time of the latest spot received by this provider.
example: 2025-09-28T20:31:00+00:00 example: 2025-09-28T20:31:00+00:00
Band:
type: object
properties:
name:
type: string
description: The name of the band
example: 40m
start_freq:
type: int
description: The start frequency of this band, in kHz.
example: 7000
end_freq:
type: int
description: The end frequency of this band, in kHz.
example: 7200
color:
type: string
description: The color associated with this mode, as used on PSK Reporter.
example: "#5959ff"
contrast_color:
type: string
description: Black or white, whichever provides the best contrast against the band colour.
example: white