From b1346e26ea17bc7c961838bba538ee5965bc7ed9 Mon Sep 17 00:00:00 2001 From: Ian Renton Date: Sat, 27 Sep 2025 11:46:06 +0100 Subject: [PATCH] PNP support --- README.md | 16 ++++++++++++-- main.py | 15 +++++++------- providers/parksnpeaks.py | 45 ++++++++++++++++++++++++++++++++++++++++ providers/wwbota.py | 1 + 4 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 providers/parksnpeaks.py diff --git a/README.md b/README.md index 50e70b8..e541cd4 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,21 @@ Currently supports: * GMA * HEMA * UKBOTA +* Parks n Peaks Future plans: -* Parks n Peaks * RBN -* APRS +* APRS? * Packet? + +Suggested names so far: +* All in 1 Spots +* All the Spots +* Spots Combiner 9000 +* 927 +* Activation Central +* DX Hub +* DX Aggregator +* Collect-o-Matic +* Spot-o-Tron +* Basic Universal Radio Program (BURP) \ No newline at end of file diff --git a/main.py b/main.py index b676a9d..4698d47 100644 --- a/main.py +++ b/main.py @@ -4,6 +4,7 @@ import signal 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.sota import SOTA from providers.wwbota import WWBOTA @@ -23,14 +24,14 @@ if __name__ == '__main__': # Create providers providers = [ - # POTA(), - # SOTA(), - # WWFF(), - # WWBOTA(), - # GMA(), + POTA(), + SOTA(), + WWFF(), + WWBOTA(), + GMA(), HEMA(), - # todo PNP - # DXCluster("hrd.wa9pie.net", 8000), + ParksNPeaks(), + DXCluster("hrd.wa9pie.net", 8000), # DXCluster("dxc.w3lpl.net", 22) ] # Set up spot list diff --git a/providers/parksnpeaks.py b/providers/parksnpeaks.py new file mode 100644 index 0000000..176fd1a --- /dev/null +++ b/providers/parksnpeaks.py @@ -0,0 +1,45 @@ +from datetime import datetime + +import pytz + +from data.spot import Spot +from providers.http_provider import HTTPProvider + + +# Provider for Parks n Peaks +class ParksNPeaks(HTTPProvider): + POLL_INTERVAL_SEC = 120 + SPOTS_URL = "https://www.parksnpeaks.org/api/ALL" + + def __init__(self): + super().__init__(self.SPOTS_URL, self.POLL_INTERVAL_SEC) + + def name(self): + return "ParksNPeaks" + + def http_response_to_spots(self, http_response): + new_spots = [] + # Iterate through source data + for source_spot in http_response.json(): + print(source_spot) + # Convert to our spot format + spot = Spot(source=self.name(), + source_id=source_spot["actID"], + dx_call=source_spot["actCallsign"].upper(), + de_call=source_spot["actSpoter"].upper(), # typo exists in API + freq=float(source_spot["actFreq"]) * 1000, + mode=source_spot["actMode"].upper(), + comment=source_spot["actComments"], + sig=source_spot["actClass"], + sig_refs=[source_spot["actSiteID"]], + time=datetime.strptime(source_spot["actTime"], "%Y-%m-%d %H:%M:%S").replace(tzinfo=pytz.UTC)) + + # If this is POTA, SOTA or WWFF data we already have it through other means, so ignore. + if spot.sig not in ["POTA", "SOTA", "WWFF"]: + print("PNP spot found with sig " + spot.sig + ", developer needs to figure out how to look this up for grid/lat/lon!") + # Fill in any missing data + spot.infer_missing() + # Add to our list. Don't worry about de-duping, removing old spots etc. at this point; other code will do + # that for us. + new_spots.append(spot) + return new_spots \ No newline at end of file diff --git a/providers/wwbota.py b/providers/wwbota.py index d788aa3..d20aeb6 100644 --- a/providers/wwbota.py +++ b/providers/wwbota.py @@ -5,6 +5,7 @@ from providers.http_provider import HTTPProvider # Provider for Worldwide Bunkers on the Air +# todo switch to event source API as per Steve change to Field Spotter class WWBOTA(HTTPProvider): POLL_INTERVAL_SEC = 120 SPOTS_URL = "https://api.wwbota.org/spots/"