def command(self, fromcall, message, ack): api_key = self.config["services"]["aprs.fi"]["apiKey"] try: aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall) except Exception as ex: LOG.error("Failed to fetch aprs.fi data {}".format(ex)) return "Failed to fetch location" # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: utils.check_config_option( self.config, ["services", "openweathermap", "apiKey"], ) except Exception as ex: LOG.error("Failed to find config openweathermap:apiKey {}".format(ex)) return "No openweathermap apiKey found" api_key = self.config["services"]["openweathermap"]["apiKey"] try: results = plugin_utils.fetch_openweathermap(api_key, lat, lon) except Exception as ex: LOG.error("Couldn't fetch openweathermap api '{}'".format(ex)) # default to UTC localzone = pytz.timezone("UTC") else: tzone = results["timezone"] localzone = pytz.timezone(tzone) return self.build_date_str(localzone)
def command(self, fromcall, message, ack): api_key = self.config["services"]["aprs.fi"]["apiKey"] try: aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall) except Exception as ex: LOG.error("Failed to fetch aprs.fi data {}".format(ex)) return "Failed to fetch location" # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: utils.check_config_option(self.config, "opencagedata", "apiKey") except Exception as ex: LOG.error("Failed to find config opencage:apiKey {}".format(ex)) return "No opencage apiKey found" try: opencage_key = self.config["opencagedata"]["apiKey"] geocoder = OpenCageGeocode(opencage_key) results = geocoder.reverse_geocode(lat, lon) except Exception as ex: LOG.error("Couldn't fetch opencagedata api '{}'".format(ex)) # Default to UTC instead localzone = pytz.timezone("UTC") else: tzone = results[0]["annotations"]["timezone"]["name"] localzone = pytz.timezone(tzone) return self.build_date_str(localzone)
def process(self, packet): fromcall = packet.get("from") message = packet.get("message_text", None) # ack = packet.get("msgNo", "0") api_key = self.config["services"]["aprs.fi"]["apiKey"] # optional second argument is a callsign to search a = re.search(r"^.*\s+(.*)", message) if a is not None: searchcall = a.group(1) searchcall = searchcall.upper() else: # if no second argument, search for calling station searchcall = fromcall try: aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) except Exception as ex: LOG.error(f"Failed to fetch aprs.fi data {ex}") return "Failed to fetch location" # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) if not len(aprs_data["entries"]): LOG.error("Didn't get any entries from aprs.fi") return "Failed to fetch aprs.fi location" lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: self.config.exists("opencagedata.apiKey") except Exception as ex: LOG.error(f"Failed to find config opencage:apiKey {ex}") return "No opencage apiKey found" try: opencage_key = self.config["opencagedata"]["apiKey"] geocoder = OpenCageGeocode(opencage_key) results = geocoder.reverse_geocode(lat, lon) except Exception as ex: LOG.error(f"Couldn't fetch opencagedata api '{ex}'") # Default to UTC instead localzone = pytz.timezone("UTC") else: tzone = results[0]["annotations"]["timezone"]["name"] localzone = pytz.timezone(tzone) return self.build_date_str(localzone)
def process(self, packet): fromcall = packet.get("from") message = packet.get("message_text", None) # ack = packet.get("msgNo", "0") # optional second argument is a callsign to search a = re.search(r"^.*\s+(.*)", message) if a is not None: searchcall = a.group(1) searchcall = searchcall.upper() else: # if no second argument, search for calling station searchcall = fromcall api_key = self.config["services"]["aprs.fi"]["apiKey"] try: aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) except Exception as ex: LOG.error(f"Failed to fetch aprs.fi data {ex}") return "Failed to fetch location" LOG.debug(f"LocationPlugin: aprs_data = {aprs_data}") if not len(aprs_data["entries"]): LOG.error("Didn't get any entries from aprs.fi") return "Failed to fetch aprs.fi location" lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: self.config.exists(["services", "openweathermap", "apiKey"], ) except Exception as ex: LOG.error(f"Failed to find config openweathermap:apiKey {ex}") return "No openweathermap apiKey found" api_key = self.config["services"]["openweathermap"]["apiKey"] try: results = plugin_utils.fetch_openweathermap(api_key, lat, lon) except Exception as ex: LOG.error(f"Couldn't fetch openweathermap api '{ex}'") # default to UTC localzone = pytz.timezone("UTC") else: tzone = results["timezone"] localzone = pytz.timezone(tzone) return self.build_date_str(localzone)
def command(self, fromcall, message, ack): LOG.info("Weather Plugin") try: utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"]) except Exception as ex: LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) return "No aprs.fi apikey found" api_key = self.config["services"]["aprs.fi"]["apiKey"] try: aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall) except Exception as ex: LOG.error("Failed to fetch aprs.fi data {}".format(ex)) return "Failed to fetch location" # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon) except Exception as ex: LOG.error("Couldn't fetch forecast.weather.gov '{}'".format(ex)) return "Unable to get weather" reply = ( "%sF(%sF/%sF) %s. %s, %s." % ( wx_data["currentobservation"]["Temp"], wx_data["data"]["temperature"][0], wx_data["data"]["temperature"][1], wx_data["data"]["weather"][0], wx_data["time"]["startPeriodName"][1], wx_data["data"]["weather"][1], ) ).rstrip() LOG.debug("reply: '{}' ".format(reply)) return reply
def process(self, packet): LOG.info("Weather Plugin") fromcall = packet.get("from") # message = packet.get("message_text", None) # ack = packet.get("msgNo", "0") api_key = self.config["services"]["aprs.fi"]["apiKey"] try: aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall) except Exception as ex: LOG.error(f"Failed to fetch aprs.fi data {ex}") return "Failed to fetch aprs.fi location" LOG.debug(f"LocationPlugin: aprs_data = {aprs_data}") if not len(aprs_data["entries"]): LOG.error("Didn't get any entries from aprs.fi") return "Failed to fetch aprs.fi location" lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon) except Exception as ex: LOG.error(f"Couldn't fetch forecast.weather.gov '{ex}'") return "Unable to get weather" reply = ("%sF(%sF/%sF) %s. %s, %s." % ( wx_data["currentobservation"]["Temp"], wx_data["data"]["temperature"][0], wx_data["data"]["temperature"][1], wx_data["data"]["weather"][0], wx_data["time"]["startPeriodName"][1], wx_data["data"]["weather"][1], )).rstrip() LOG.debug(f"reply: '{reply}' ") return reply
def process(self, packet): LOG.info("Location Plugin") fromcall = packet.get("from") message = packet.get("message_text", None) # ack = packet.get("msgNo", "0") api_key = self.config["services"]["aprs.fi"]["apiKey"] # optional second argument is a callsign to search a = re.search(r"^.*\s+(.*)", message) if a is not None: searchcall = a.group(1) searchcall = searchcall.upper() else: # if no second argument, search for calling station searchcall = fromcall try: aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) except Exception as ex: LOG.error(f"Failed to fetch aprs.fi '{ex}'") return "Failed to fetch aprs.fi location" LOG.debug(f"LocationPlugin: aprs_data = {aprs_data}") if not len(aprs_data["entries"]): LOG.error("Didn't get any entries from aprs.fi") return "Failed to fetch aprs.fi location" lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: # altitude not always provided alt = float(aprs_data["entries"][0]["altitude"]) except Exception: alt = 0 altfeet = int(alt * 3.28084) aprs_lasttime_seconds = aprs_data["entries"][0]["lasttime"] # aprs_lasttime_seconds = aprs_lasttime_seconds.encode( # "ascii", errors="ignore" # ) # unicode to ascii delta_seconds = time.time() - int(aprs_lasttime_seconds) delta_hours = delta_seconds / 60 / 60 try: wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon) except Exception as ex: LOG.error(f"Couldn't fetch forecast.weather.gov '{ex}'") wx_data = {"location": {"areaDescription": "Unknown Location"}} if "location" not in wx_data: LOG.error(f"Couldn't fetch forecast.weather.gov '{wx_data}'") wx_data = {"location": {"areaDescription": "Unknown Location"}} reply = "{}: {} {}' {},{} {}h ago".format( searchcall, wx_data["location"]["areaDescription"], str(altfeet), str(lat), str(lon), str("%.1f" % round(delta_hours, 1)), ).rstrip() return reply
def process(self, packet): LOG.info("SlackCommandPlugin") fromcall = packet["from"] message = packet["message_text"] is_setup = self.setup_slack() if not is_setup: return # get last location of a callsign, get descriptive name from weather service try: self.config.exists(["services", "aprs.fi", "apiKey"]) except Exception as ex: LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) return "No aprs.fi apikey found" api_key = self.config["services"]["aprs.fi"]["apiKey"] # optional second argument is a callsign to search a = re.search(r"^.*\s+(.*)", message) if a is not None: searchcall = a.group(1) searchcall = searchcall.upper() else: # if no second argument, search for calling station searchcall = fromcall try: aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) except Exception as ex: LOG.error("Failed to fetch aprs.fi '{}'".format(ex)) return "Failed to fetch aprs.fi location" LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) if not len(aprs_data["entries"]): LOG.error("Didn't get any entries from aprs.fi") return "Failed to fetch aprs.fi location" lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: # altitude not always provided alt = float(aprs_data["entries"][0]["altitude"]) except Exception: alt = 0 altfeet = int(alt * 3.28084) aprs_lasttime_seconds = aprs_data["entries"][0]["lasttime"] delta_seconds = time.time() - int(aprs_lasttime_seconds) delta_hours = delta_seconds / 60 / 60 wx_data = None try: wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon) except Exception: LOG.warning("Couldn't fetch forecast.weather.gov") callsign_url = "<http://aprs.fi/info/a/{}|{}>".format( searchcall, searchcall) aprs_url = "<http://aprs.fi/#!mt=roadmap&z=15&lat={}&lng={}|" " http://aprs.fi/>".format( lat, lon, ) message = {} message["username"] = "******" message["icon_emoji"] = ":satellite_antenna:" message["attachments"] = [{}] message["text"] = "{} - Location".format(callsign_url) message["channel"] = "#random" attachment = message["attachments"][0] attachment["fallback"] = message["text"] attachment["fields"] = [] # if the coordinates are outside of the US, we don't get this # aread description if wx_data and "location" in wx_data and "areaDescription" in wx_data[ "location"]: attachment["fields"].append( { "title": "Location", "value": wx_data["location"]["areaDescription"], "short": True, }, ) attachment["fields"].append( { "title": "Map Location", "value": aprs_url, "short": True }, ) attachment["fields"].append( { "title": "Altitude", "value": altfeet, "short": True, "fallback": "Altitude - {}".format(altfeet), }, ) attachment["fields"].append( { "title": "Time", "value": "{} h ago".format(round(delta_hours, 1)), "short": True, "fallback": "Time {} h ago".format(round(delta_hours, 1)), }, ) LOG.debug(message) # self.swc.chat_postMessage(**message) for channel in self.slack_channels: message["channel"] = channel self.swc.chat_postMessage(**message) # Don't have aprsd try and send a reply return messaging.NULL_MESSAGE
def command(self, fromcall, message, ack): LOG.info("Location Plugin") # get last location of a callsign, get descriptive name from weather service try: utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"]) except Exception as ex: LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) return "No aprs.fi apikey found" api_key = self.config["services"]["aprs.fi"]["apiKey"] # optional second argument is a callsign to search a = re.search(r"^.*\s+(.*)", message) if a is not None: searchcall = a.group(1) searchcall = searchcall.upper() else: # if no second argument, search for calling station searchcall = fromcall try: aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) except Exception as ex: LOG.error("Failed to fetch aprs.fi '{}'".format(ex)) return "Failed to fetch aprs.fi location" LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) if not len(aprs_data["entries"]): LOG.error("Didn't get any entries from aprs.fi") return "Failed to fetch aprs.fi location" lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: # altitude not always provided alt = float(aprs_data["entries"][0]["altitude"]) except Exception: alt = 0 altfeet = int(alt * 3.28084) aprs_lasttime_seconds = aprs_data["entries"][0]["lasttime"] # aprs_lasttime_seconds = aprs_lasttime_seconds.encode( # "ascii", errors="ignore" # ) # unicode to ascii delta_seconds = time.time() - int(aprs_lasttime_seconds) delta_hours = delta_seconds / 60 / 60 try: wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon) except Exception as ex: LOG.error("Couldn't fetch forecast.weather.gov '{}'".format(ex)) wx_data = {"location": {"areaDescription": "Unknown Location"}} if "location" not in wx_data: LOG.error( "Couldn't fetch forecast.weather.gov '{}'".format(wx_data)) wx_data = {"location": {"areaDescription": "Unknown Location"}} reply = "{}: {} {}' {},{} {}h ago".format( searchcall, wx_data["location"]["areaDescription"], str(altfeet), str(lat), str(lon), str("%.1f" % round(delta_hours, 1)), ).rstrip() return reply
def command(self, fromcall, message, ack): LOG.info("WX Plugin '{}'".format(message)) a = re.search(r"^.*\s+(.*)", message) if a is not None: searchcall = a.group(1) station = searchcall.upper() try: resp = plugin_utils.get_weather_gov_metar(station) except Exception as e: LOG.debug("Weather failed with: {}".format(str(e))) reply = "Unable to find station METAR" else: station_data = json.loads(resp.text) reply = station_data["properties"]["rawMessage"] return reply else: # if no second argument, search for calling station fromcall = fromcall try: utils.check_config_option( self.config, ["services", "aprs.fi", "apiKey"], ) except Exception as ex: LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) return "No aprs.fi apikey found" api_key = self.config["services"]["aprs.fi"]["apiKey"] try: aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall) except Exception as ex: LOG.error("Failed to fetch aprs.fi data {}".format(ex)) return "Failed to fetch location" # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) if not len(aprs_data["entries"]): LOG.error("Found no entries from aprs.fi!") return "Failed to fetch location" lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon) except Exception as ex: LOG.error("Couldn't fetch forecast.weather.gov '{}'".format(ex)) return "Unable to metar find station." if wx_data["location"]["metar"]: station = wx_data["location"]["metar"] try: resp = plugin_utils.get_weather_gov_metar(station) except Exception as e: LOG.debug("Weather failed with: {}".format(str(e))) reply = "Failed to get Metar" else: station_data = json.loads(resp.text) reply = station_data["properties"]["rawMessage"] else: # Couldn't find a station reply = "No Metar station found" return reply
def command(self, fromcall, message, ack): LOG.info("OWMWeather Plugin '{}'".format(message)) a = re.search(r"^.*\s+(.*)", message) if a is not None: searchcall = a.group(1) searchcall = searchcall.upper() else: searchcall = fromcall try: utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"]) except Exception as ex: LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) return "No aprs.fi apikey found" api_key = self.config["services"]["aprs.fi"]["apiKey"] try: aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) except Exception as ex: LOG.error("Failed to fetch aprs.fi data {}".format(ex)) return "Failed to fetch location" # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) if not len(aprs_data["entries"]): LOG.error("Found no entries from aprs.fi!") return "Failed to fetch location" lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: utils.check_config_option(self.config, ["services", "avwx", "apiKey"]) except Exception as ex: LOG.error("Failed to find config avwx:apiKey {}".format(ex)) return "No avwx apiKey found" try: utils.check_config_option(self.config, ["services", "avwx", "base_url"]) except Exception as ex: LOG.debut("Didn't find avwx:base_url {}".format(ex)) base_url = "https://avwx.rest" else: base_url = self.config["services"]["avwx"]["base_url"] api_key = self.config["services"]["avwx"]["apiKey"] token = "TOKEN {}".format(api_key) headers = {"Authorization": token} try: coord = "{},{}".format(lat, lon) url = ( "{}/api/station/near/{}?" "n=1&airport=false&reporting=true&format=json".format(base_url, coord) ) LOG.debug("Get stations near me '{}'".format(url)) response = requests.get(url, headers=headers) except Exception as ex: LOG.error(ex) raise Exception("Failed to get the weather '{}'".format(ex)) else: wx_data = json.loads(response.text) # LOG.debug(wx_data) station = wx_data[0]["station"]["icao"] try: url = ( "{}/api/metar/{}?options=info,translate,summary" "&airport=true&reporting=true&format=json&onfail=cache".format( base_url, station, ) ) LOG.debug("Get METAR '{}'".format(url)) response = requests.get(url, headers=headers) except Exception as ex: LOG.error(ex) raise Exception("Failed to get metar {}".format(ex)) else: metar_data = json.loads(response.text) # LOG.debug(metar_data) return metar_data["raw"]
def command(self, fromcall, message, ack): LOG.info("OWMWeather Plugin '{}'".format(message)) a = re.search(r"^.*\s+(.*)", message) if a is not None: searchcall = a.group(1) searchcall = searchcall.upper() else: searchcall = fromcall try: utils.check_config_option(self.config, ["services", "aprs.fi", "apiKey"]) except Exception as ex: LOG.error("Failed to find config aprs.fi:apikey {}".format(ex)) return "No aprs.fi apikey found" api_key = self.config["services"]["aprs.fi"]["apiKey"] try: aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) except Exception as ex: LOG.error("Failed to fetch aprs.fi data {}".format(ex)) return "Failed to fetch location" # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) if not len(aprs_data["entries"]): LOG.error("Found no entries from aprs.fi!") return "Failed to fetch location" lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: utils.check_config_option( self.config, ["services", "openweathermap", "apiKey"], ) except Exception as ex: LOG.error("Failed to find config openweathermap:apiKey {}".format(ex)) return "No openweathermap apiKey found" try: utils.check_config_option(self.config, ["aprsd", "units"]) except Exception: LOG.debug("Couldn't find untis in aprsd:services:units") units = "metric" else: units = self.config["aprsd"]["units"] api_key = self.config["services"]["openweathermap"]["apiKey"] try: wx_data = plugin_utils.fetch_openweathermap( api_key, lat, lon, units=units, exclude="minutely,hourly", ) except Exception as ex: LOG.error("Couldn't fetch openweathermap api '{}'".format(ex)) # default to UTC return "Unable to get weather" if units == "metric": degree = "C" else: degree = "F" if "wind_gust" in wx_data["current"]: wind = "{:.0f}@{}G{:.0f}".format( wx_data["current"]["wind_speed"], wx_data["current"]["wind_deg"], wx_data["current"]["wind_gust"], ) else: wind = "{:.0f}@{}".format( wx_data["current"]["wind_speed"], wx_data["current"]["wind_deg"], ) # LOG.debug(wx_data["current"]) # LOG.debug(wx_data["daily"]) reply = "{} {:.1f}{}/{:.1f}{} Wind {} {}%".format( wx_data["current"]["weather"][0]["description"], wx_data["current"]["temp"], degree, wx_data["current"]["dew_point"], degree, wind, wx_data["current"]["humidity"], ) return reply
def process(self, packet): fromcall = packet.get("from") message = packet.get("message_text", None) # ack = packet.get("msgNo", "0") LOG.info(f"WX Plugin '{message}'") a = re.search(r"^.*\s+(.*)", message) if a is not None: searchcall = a.group(1) station = searchcall.upper() try: resp = plugin_utils.get_weather_gov_metar(station) except Exception as e: LOG.debug(f"Weather failed with: {str(e)}") reply = "Unable to find station METAR" else: station_data = json.loads(resp.text) reply = station_data["properties"]["rawMessage"] return reply else: # if no second argument, search for calling station fromcall = fromcall try: self.config.exists(["services", "aprs.fi", "apiKey"]) except Exception as ex: LOG.error(f"Failed to find config aprs.fi:apikey {ex}") return "No aprs.fi apikey found" api_key = self.config["services"]["aprs.fi"]["apiKey"] try: aprs_data = plugin_utils.get_aprs_fi(api_key, fromcall) except Exception as ex: LOG.error(f"Failed to fetch aprs.fi data {ex}") return "Failed to fetch aprs.fi location" # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) if not len(aprs_data["entries"]): LOG.error("Found no entries from aprs.fi!") return "Failed to fetch aprs.fi location" lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: wx_data = plugin_utils.get_weather_gov_for_gps(lat, lon) except Exception as ex: LOG.error(f"Couldn't fetch forecast.weather.gov '{ex}'") return "Unable to metar find station." if wx_data["location"]["metar"]: station = wx_data["location"]["metar"] try: resp = plugin_utils.get_weather_gov_metar(station) except Exception as e: LOG.debug(f"Weather failed with: {str(e)}") reply = "Failed to get Metar" else: station_data = json.loads(resp.text) reply = station_data["properties"]["rawMessage"] else: # Couldn't find a station reply = "No Metar station found" return reply
def process(self, packet): fromcall = packet.get("from") message = packet.get("message_text", None) # ack = packet.get("msgNo", "0") LOG.info(f"AVWXWeather Plugin '{message}'") a = re.search(r"^.*\s+(.*)", message) if a is not None: searchcall = a.group(1) searchcall = searchcall.upper() else: searchcall = fromcall try: self.config.exists(["services", "aprs.fi", "apiKey"]) except Exception as ex: LOG.error(f"Failed to find config aprs.fi:apikey {ex}") return "No aprs.fi apikey found" api_key = self.config["services"]["aprs.fi"]["apiKey"] try: aprs_data = plugin_utils.get_aprs_fi(api_key, searchcall) except Exception as ex: LOG.error(f"Failed to fetch aprs.fi data {ex}") return "Failed to fetch location" # LOG.debug("LocationPlugin: aprs_data = {}".format(aprs_data)) if not len(aprs_data["entries"]): LOG.error("Found no entries from aprs.fi!") return "Failed to fetch location" lat = aprs_data["entries"][0]["lat"] lon = aprs_data["entries"][0]["lng"] try: self.config.exists(["services", "avwx", "apiKey"]) except Exception as ex: LOG.error(f"Failed to find config avwx:apiKey {ex}") return "No avwx apiKey found" try: self.config.exists(self.config, ["services", "avwx", "base_url"]) except Exception as ex: LOG.debug(f"Didn't find avwx:base_url {ex}") base_url = "https://avwx.rest" else: base_url = self.config["services"]["avwx"]["base_url"] api_key = self.config["services"]["avwx"]["apiKey"] token = f"TOKEN {api_key}" headers = {"Authorization": token} try: coord = f"{lat},{lon}" url = ("{}/api/station/near/{}?" "n=1&airport=false&reporting=true&format=json".format( base_url, coord)) LOG.debug(f"Get stations near me '{url}'") response = requests.get(url, headers=headers) except Exception as ex: LOG.error(ex) raise Exception(f"Failed to get the weather '{ex}'") else: wx_data = json.loads(response.text) # LOG.debug(wx_data) station = wx_data[0]["station"]["icao"] try: url = ( "{}/api/metar/{}?options=info,translate,summary" "&airport=true&reporting=true&format=json&onfail=cache".format( base_url, station, )) LOG.debug(f"Get METAR '{url}'") response = requests.get(url, headers=headers) except Exception as ex: LOG.error(ex) raise Exception(f"Failed to get metar {ex}") else: metar_data = json.loads(response.text) # LOG.debug(metar_data) return metar_data["raw"]