Add data providers for most other programmes

This commit is contained in:
Ian Renton
2025-09-27 10:00:12 +01:00
parent 7bdf6cf203
commit 27a61393cf
14 changed files with 439 additions and 102 deletions

View File

@@ -1,19 +1,23 @@
import logging
import re
from datetime import datetime, timezone
from threading import Thread
from time import sleep
import pytz
import telnetlib3
from core.constants import SERVER_OWNER_CALLSIGN
from data.spot import Spot
from providers.provider import Provider
import telnetlib3
import re
callsign_pattern = "([a-z|0-9|/]+)"
frequency_pattern = "([0-9|.]+)"
pattern = re.compile("^DX de "+callsign_pattern+":\\s+"+frequency_pattern+"\\s+"+callsign_pattern+"\\s+(.*)\\s+(\\d{4}Z)", re.IGNORECASE)
# Provider for a DX Cluster. Hostname and port provided as parameters.
class DXCluster(Provider):
CALLSIGN_PATTERN = "([a-z|0-9|/]+)"
FREQUENCY_PATTERM = "([0-9|.]+)"
LINE_PATTERN = re.compile(
"^DX de " + CALLSIGN_PATTERN + ":\\s+" + FREQUENCY_PATTERM + "\\s+" + CALLSIGN_PATTERN + "\\s+(.*)\\s+(\\d{4}Z)",
re.IGNORECASE)
# Constructor requires hostname and port
def __init__(self, hostname, port):
@@ -25,7 +29,7 @@ class DXCluster(Provider):
self.run = True
def name(self):
return "DX Cluster " + self.hostname + " " + str(self.port)
return "DX Cluster " + self.hostname
def start(self):
self.thread = Thread(target=self.handle)
@@ -37,29 +41,50 @@ class DXCluster(Provider):
self.thread.join()
def handle(self):
self.status = "Connecting"
self.telnet = telnetlib3.Telnet(self.hostname, self.port)
self.telnet.read_until("login: ".encode("ascii"))
self.telnet.write((SERVER_OWNER_CALLSIGN + "\n").encode("ascii"))
self.status = "Waiting for Data"
while self.run:
# Check new telnet info against regular expression
telnet_output = self.telnet.read_until("\n".encode("ascii"))
match = pattern.match(telnet_output.decode("ascii"))
if match:
spot_time = datetime.strptime(match.group(5), "%H%MZ")
spot_datetime = datetime.combine(datetime.today(), spot_time.time()).replace(tzinfo=pytz.UTC)
spot = Spot(source=self.name(),
dx_call=match.group(3),
de_call=match.group(1),
freq=float(match.group(2)),
comment=match.group(4).strip(),
time=spot_datetime)
# Fill in any blanks
spot.infer_missing()
# Add to our list
self.submit([spot])
connected = False
while not connected and self.run:
try:
self.status = "Connecting"
self.telnet = telnetlib3.Telnet(self.hostname, self.port)
self.telnet.read_until("login: ".encode("ascii"))
self.telnet.write((SERVER_OWNER_CALLSIGN + "\n").encode("ascii"))
connected = True
except Exception as e:
self.status = "Error"
logging.exception("Exception while connecting to DX Cluster Provider (" + self.hostname + ").")
sleep(5)
self.status = "OK"
self.last_update_time = datetime.now(timezone.utc)
self.status = "Waiting for Data"
while connected and self.run:
try:
# Check new telnet info against regular expression
telnet_output = self.telnet.read_until("\n".encode("ascii"))
match = self.LINE_PATTERN.match(telnet_output.decode("ascii"))
if match:
spot_time = datetime.strptime(match.group(5), "%H%MZ")
spot_datetime = datetime.combine(datetime.today(), spot_time.time()).replace(tzinfo=pytz.UTC)
spot = Spot(source=self.name(),
dx_call=match.group(3),
de_call=match.group(1),
freq=float(match.group(2)),
comment=match.group(4).strip(),
time=spot_datetime)
# Fill in any blanks
spot.infer_missing()
# Add to our list
self.submit([spot])
self.status = "OK"
self.last_update_time = datetime.now(timezone.utc)
except Exception as e:
connected = False
if self.run:
self.status = "Error"
logging.exception("Exception in DX Cluster Provider (" + self.hostname + ")")
sleep(5)
else:
self.status = "Shutting down"
self.status = "Disconnected"