Files
spothole/main.py
2025-10-02 09:57:25 +01:00

117 lines
3.9 KiB
Python

# Main script
import logging
import os
import signal
import sys
from datetime import datetime
from time import sleep
import psutil
import pytz
from core.cleanup import CleanupTimer
from core.config import config, MAX_SPOT_AGE, WEB_SERVER_PORT, SERVER_OWNER_CALLSIGN
from core.constants import SOFTWARE_VERSION
from providers.aprsis import APRSIS
from providers.dxcluster import DXCluster
from providers.gma import GMA
from providers.hema import HEMA
from providers.parksnpeaks import ParksNPeaks
from providers.pota import POTA
from providers.rbn import RBN
from providers.sota import SOTA
from providers.wwbota import WWBOTA
from providers.wwff import WWFF
from server.webserver import WebServer
# Globals
spot_list = []
status_data = {}
providers = []
cleanup_timer = None
run = True
# Shutdown function
def shutdown(sig, frame):
logging.info("Stopping program, this may take a few seconds...")
global run
run = False
for p in providers:
if p.enabled:
p.stop()
cleanup_timer.stop()
# Utility method to get a data provider based on its config entry.
def get_provider_from_config(config_providers_entry):
match config_providers_entry["type"]:
case "POTA":
return POTA(config_providers_entry)
case "SOTA":
return SOTA(config_providers_entry)
case "WWFF":
return WWFF(config_providers_entry)
case "GMA":
return GMA(config_providers_entry)
case "WWBOTA":
return WWBOTA(config_providers_entry)
case "HEMA":
return HEMA(config_providers_entry)
case "ParksNPeaks":
return ParksNPeaks(config_providers_entry)
case "DXCluster":
return DXCluster(config_providers_entry)
case "RBN":
return RBN(config_providers_entry)
case "APRS-IS":
return APRSIS(config_providers_entry)
return None
# Main function
if __name__ == '__main__':
# Set up logging
root = logging.getLogger()
root.setLevel(logging.INFO)
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.INFO)
formatter = logging.Formatter("%(message)s")
handler.setFormatter(formatter)
root.addHandler(handler)
logging.info("Starting...")
startup_time = datetime.now(pytz.UTC)
status_data["software-version"] = SOFTWARE_VERSION
status_data["server-owner-callsign"] = SERVER_OWNER_CALLSIGN
# Shut down gracefully on SIGINT
signal.signal(signal.SIGINT, shutdown)
for entry in config["providers"]:
providers.append(get_provider_from_config(entry))
# Set up data providers
for p in providers: p.setup(spot_list=spot_list)
# Start data providers
for p in providers:
if p.enabled:
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)
cleanup_timer.start()
# Set up web server
web_server = WebServer(spot_list=spot_list, status_data=status_data, port=WEB_SERVER_PORT)
web_server.start()
logging.info("Startup complete.")
# While running, update the status information at a regular interval
while run:
sleep(5)
status_data["uptime"] = str(datetime.now(pytz.UTC) - startup_time).split(".")[0]
status_data["mem_use_mb"] = round(psutil.Process(os.getpid()).memory_info().rss / (1024 * 1024), 3)
status_data["num_spots"] = len(spot_list)
status_data["providers"] = list(map(lambda p: {"name": p.name, "enabled": p.enabled, "status": p.status, "last_updated": p.last_update_time, "last_spot": p.last_spot_time}, providers))
status_data["cleanup"] = {"status": cleanup_timer.status, "last_ran": cleanup_timer.last_cleanup_time}
status_data["webserver"] = {"status": web_server.status, "last_api_access": web_server.last_api_access_time, "last_page_access": web_server.last_page_access_time}