From 00c56a7c10550c93043c58daa2b9bc9fd185233e Mon Sep 17 00:00:00 2001 From: Ian Renton Date: Sat, 27 Sep 2025 14:54:14 +0100 Subject: [PATCH] Extract config into yaml --- .gitignore | 1 + README.md | 14 ++++++++++++-- config-example.yml | 12 ++++++++++++ core/config.py | 13 +++++++++++++ core/constants.py | 5 ----- main.py | 6 +++--- providers/dxcluster.py | 5 +++-- providers/provider.py | 5 +++-- requirements.txt | 1 + 9 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 config-example.yml create mode 100644 core/config.py diff --git a/.gitignore b/.gitignore index 7f06553..735cee3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ __pycache__ *.pyc /sota_summit_data_cache.sqlite /gma_ref_info_cache.sqlite +/config.yml diff --git a/README.md b/README.md index 151993d..7dc7835 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# MetaSpot +# Amateur Radio meta spotting tool, name TBD *Work in progress.* @@ -31,4 +31,14 @@ Suggested names so far: * Spot-o-Tron * Basic Universal Radio Program (BURP) * The Spotinator -* DX Cluster API \ No newline at end of file +* Spotcaster +* DX Cluster API +* spotcollector +* Unified Amateur Radio Data Aggregator (U-ARDA) +* (s)pothole +* Spot on API +* API on Spot + +### TODO - Setup instructions - checkout, config.yml, pip +### TODO - systemd +### TODO - nginx \ No newline at end of file diff --git a/config-example.yml b/config-example.yml new file mode 100644 index 0000000..5fd2ef5 --- /dev/null +++ b/config-example.yml @@ -0,0 +1,12 @@ +# Config file example. +# Rename this to "config.yml" before running the software. + +# Your callsign. Used to log into DX clusters and included in User-Agent when querying HTTP servers. Useful so if your +# server goes crazy and causes other people problems, they know who to contact :) +server-owner-callsign: "N0CALL" + +# Port to open the local web server on +web-server-port: 8080 + +# Maximum spot age to keep in the system before deleting it +max-spot-age-sec: 3600 \ No newline at end of file diff --git a/core/config.py b/core/config.py new file mode 100644 index 0000000..52c04f2 --- /dev/null +++ b/core/config.py @@ -0,0 +1,13 @@ +import logging +import os + +import yaml + +# Check you have a config file +if not os.path.isfile("config.yml"): + logging.error("Your config file is missing. Ensure you have copied config-example.yml to config.yml and updated it according to your needs.") + exit() + +# Load config +config = yaml.safe_load(open("config.yml")) +logging.info("Loaded config.") \ No newline at end of file diff --git a/core/constants.py b/core/constants.py index a391d7d..380a243 100644 --- a/core/constants.py +++ b/core/constants.py @@ -4,11 +4,6 @@ from data.band import Band SOFTWARE_NAME = "Metaspot by M0TRT" SOFTWARE_VERSION = "0.1" -# Todo make configurable -SERVER_OWNER_CALLSIGN = "M0TRT" -WEB_SERVER_PORT = 8080 -MAX_SPOT_AGE_SEC = 3600 - # Modes CW_MODES = ["CW"] PHONE_MODES = ["PHONE", "SSB", "USB", "LSB", "AM", "FM", "DV", "DMR", "DSTAR", "C4FM", "M17"] diff --git a/main.py b/main.py index 0ca04d5..e53bd1e 100644 --- a/main.py +++ b/main.py @@ -5,7 +5,7 @@ import sys from time import sleep from core.cleanup import CleanupTimer -from core.constants import MAX_SPOT_AGE_SEC, WEB_SERVER_PORT +from core.config import config from providers.dxcluster import DXCluster from providers.gma import GMA from providers.hema import HEMA @@ -63,11 +63,11 @@ if __name__ == '__main__': for p in providers: p.start() # Set up timer to clear spot list of old data - cleanup_timer = CleanupTimer(spot_list=spot_list, cleanup_interval=60, max_spot_age=MAX_SPOT_AGE_SEC) + cleanup_timer = CleanupTimer(spot_list=spot_list, cleanup_interval=60, max_spot_age=config["max-spot-age-sec"]) cleanup_timer.start() # Set up web server - web_server = WebServer(spot_list=spot_list, port=WEB_SERVER_PORT) + web_server = WebServer(spot_list=spot_list, port=config["web-server-port"]) web_server.start() logging.info("Startup complete.") diff --git a/providers/dxcluster.py b/providers/dxcluster.py index d69436b..11c5852 100644 --- a/providers/dxcluster.py +++ b/providers/dxcluster.py @@ -7,10 +7,11 @@ from time import sleep import pytz import telnetlib3 -from core.constants import SERVER_OWNER_CALLSIGN from data.spot import Spot +from core.config import config from providers.provider import Provider + # Provider for a DX Cluster. Hostname and port provided as parameters. class DXCluster(Provider): CALLSIGN_PATTERN = "([a-z|0-9|/]+)" @@ -49,7 +50,7 @@ class DXCluster(Provider): logging.info("DX Cluster " + self.hostname + " connecting...") self.telnet = telnetlib3.Telnet(self.hostname, self.port) self.telnet.read_until("login: ".encode("utf-8")) - self.telnet.write((SERVER_OWNER_CALLSIGN + "\n").encode("utf-8")) + self.telnet.write((config["server-owner-callsign"] + "\n").encode("utf-8")) connected = True logging.info("DX Cluster " + self.hostname + " connected.") except Exception as e: diff --git a/providers/provider.py b/providers/provider.py index 1145b48..9c3a757 100644 --- a/providers/provider.py +++ b/providers/provider.py @@ -2,14 +2,15 @@ from datetime import datetime import pytz -from core.constants import SOFTWARE_NAME, SOFTWARE_VERSION, SERVER_OWNER_CALLSIGN +from core.constants import SOFTWARE_NAME, SOFTWARE_VERSION +from core.config import config # Generic data provider class. Subclasses of this query the individual APIs for data. class Provider: # HTTP headers used for providers that use HTTP - HTTP_HEADERS = { "User-Agent": SOFTWARE_NAME + " " + SOFTWARE_VERSION + " (operated by " + SERVER_OWNER_CALLSIGN + ")" } + HTTP_HEADERS = { "User-Agent": SOFTWARE_NAME + " " + SOFTWARE_VERSION + " (operated by " + config["server-owner-callsign"] + ")" } # Constructor def __init__(self): diff --git a/requirements.txt b/requirements.txt index b8916dc..4e44785 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +pyyaml~=6.0.3 bottle~=0.13.4 requests-cache~=1.2.1 pyhamtools~=0.12.0