import logging from pyhamtools.locator import locator_to_latlong, latlong_to_locator from core.data_store import DATA_STORE from core.geo_utils import wab_wai_square_to_lat_lon def populate_sig_ref_info(sig_ref): """Look up details of a SIG reference (e.g. POTA park) such as name, lat/lon, and grid. Takes in a sig_ref object which must at minimum have a "sig" and an "id". The rest of the object will be populated and returned. This makes use of SIG ref data in the data store, live lookups from the web, or just automatic calculation depending on which SIG we are getting data for. Any data currently in the object will be kept, only missing data in the object will be populated if it can be determined.""" if sig_ref.sig is None or sig_ref.sig == "" or sig_ref.id is None or sig_ref.id == "": logging.debug("Failed to look up sig_ref info, sig or id were not set.") return sig_ref sig = sig_ref.sig ref_id = sig_ref.id try: ### FUDGES ### # # DME fudge. Our database has leading zeros padding to 5 digits which is the expected format, but not all # activators add leading zeros. if sig.upper() == "DME": ref_id = ref_id.zfill(5) # KRMNPA & SANPCPA fudge. These don't have their own reference system, they just use VKFF references, so pretend # the sig is WWFF and carry on if sig.upper() == "KRMNPA" or sig.upper() == "SANPCPA": sig = "WWFF" ### SKIPS ### # # If the SIG is HEMA, we have no current lookup for this so just skip the lookup here. if sig.upper() == "HEMA": return sig_ref ### PROGRAMMATIC DATA GENERATION INSTEAD OF LOOKUPS ### # # If the SIG is Tiles, WAB, WAI or BOTA (Beaches), we don't have anything to look up from the data store, we can # calculate all the information we are going to get directly. if sig.upper() == "TILES": # Tiles on the Air just uses Maidenhead 6-digit squares, so ID, Name and Grid are all the same if not sig_ref.name: sig_ref.name = sig_ref.id if not sig_ref.grid: sig_ref.grid = sig_ref.id if sig_ref.grid and not sig_ref.latitude: ll = locator_to_latlong(str(sig_ref.grid)) sig_ref.latitude = ll[0] sig_ref.longitude = ll[1] return sig_ref elif sig.upper() == "WAB" or sig.upper() == "WAI": ll = wab_wai_square_to_lat_lon(ref_id) if ll: sig_ref.name = ref_id try: sig_ref.grid = latlong_to_locator(ll[0], ll[1], 6) sig_ref.latitude = ll[0] sig_ref.longitude = ll[1] except: logging.warning("Invalid lat/lon received for WAB/WAI reference") return sig_ref elif sig.upper() == "BOTA": # For BOTA all we can ever generate is the URL, there is no data file or lookup for lat/longs if not sig_ref.name: sig_ref.name = sig_ref.id sig_ref.url = "https://www.beachesontheair.com/beaches/" + sig_ref.name.lower().replace(" ", "-") return sig_ref ### ACTUAL LOOKUP ### # # OK, this is something we have to look up. Now check to see if our data store contains SIG ref information for # this SIG. If so, check for the reference data and use that. key = sig + ":" + ref_id lookup_data = DATA_STORE.sigrefs.get(key) if key in DATA_STORE.sigrefs else None if lookup_data: # Copy new sig ref data into existing object where data was previously missing for key, value in lookup_data.__dict__.items(): if value is not None and sig_ref.__dict__.get(key) is None: sig_ref.__dict__[key] = value else: # Maybe a super new reference we don't know about yet, but more likely a typo or a test reference, # just silently ignore it. logging.debug("%s database did not contain data for ref %s", sig, ref_id) except Exception: logging.error("Exception when looking up sig_ref info for " + sig + " ref " + ref_id, exc_info=True) return sig_ref