import logging import re from datetime import datetime import pytz from core.config import SERVER_OWNER_CALLSIGN from data.spot import Spot from providers.spot.telnet_spot_provider import TelnetSpotProvider logger = logging.getLogger(__name__) class RBN(TelnetSpotProvider): """Spot provider for the Reverse Beacon Network. Connects to a single port, if you want both CW/RTTY (port 7000) and FT8 (port 7001) you need to instantiate two copies of this. The port is provided in config.""" _LINE_PATTERN = re.compile( r"^DX de ([a-z0-9/]+)-.*:\s+([0-9.]+)\s+([a-z0-9/]+)\s+(.*)\s+(\d{4}Z)", re.IGNORECASE, ) def __init__(self, provider_config): """Constructor requires port number.""" name = provider_config.get("name", "RBN") super().__init__( name, provider_config, host="telnet.reversebeacon.net", port=provider_config["port"], login_prompt="Please enter your call: ", login_response=SERVER_OWNER_CALLSIGN, ) def _parse_line(self, line): match = self._LINE_PATTERN.match(line) if not match: return None spot_time = datetime.strptime(match.group(5), "%H%MZ").replace(tzinfo=pytz.UTC) spot_datetime = datetime.combine( datetime.now(pytz.UTC).date(), spot_time.time(), tzinfo=pytz.UTC, ) return Spot( source=self.name, dx_call=match.group(3), de_call=match.group(1), freq=float(match.group(2)) * 1000, comment=match.group(4).strip(), time=spot_datetime.timestamp(), )