import json import logging from datetime import datetime import pytz from core.activity_utils import get_activity_by_name from core.enums import ActivityName, Mode from data.activity_ref import ActivityRef from data.spot import Spot from providers.spot.websocket_spot_provider import WebsocketSpotProvider logger = logging.getLogger(__name__) class XOTA(WebsocketSpotProvider): """Spot provider for servers based on the "xOTA" software at https://github.com/nischu/xOTA/ The provider typically doesn't give us a lat/lon or activity explicitly, so our own config provides an activity which we can then use for lookups. This functionality is implemented for Toilets on the Air events, of which there are several - so a plain lookup of a "TOTA reference" doesn't make sense, it depends on which TOTA, which is why we also provide an activity_ref_prefix in our config. This is applied to the reference ID, so e.g. "T-01" at C3 might become "C3 T-01". This allows us to provide location lookups for TOTA at several conferences.""" ACTIVITY: ActivityName | None = None def __init__(self, provider_config): name = provider_config.get("name", "xOTA") super().__init__(name, provider_config, provider_config["url"]) found_activity = get_activity_by_name(provider_config.get("activity")) self.ACTIVITY = found_activity.name if found_activity else None if not self.ACTIVITY: logger.error( "XOTA provider has no activity reference, this is a config problem - your config needs to specify a known activity type!" ) self._activity_ref_prefix = ( str(provider_config["activity_ref_prefix"]) if "activity_ref_prefix" in provider_config else "" ) def _ws_message_to_spot(self, b): string = b.decode("utf-8") source_spot = json.loads(string) ref_id = f"{self._activity_ref_prefix} {source_spot['reference']['title']}" activity = self.ACTIVITY activities = [] activity_refs = [] if activity is not None: activities = [activity] activity_refs = [ActivityRef(id=ref_id, activity=activity, url=source_spot["reference"]["website"])] spot = Spot( source=self.name, source_id=source_spot["id"], dx_call=source_spot["stationCallSign"].upper(), freq=float(source_spot["freq"]) * 1000, mode=Mode.from_name(source_spot["mode"].upper()), activities=activities, activity_refs=activity_refs, time=datetime.now(pytz.UTC).timestamp(), qrt=source_spot["state"] != "active", ) return spot