mirror of
https://github.com/craigerl/aprsd.git
synced 2024-11-18 06:11:49 -05:00
Added openweathermap weather plugin
This patch adds the openweathermap weather plugin. Also adds a new config option to set the overall units setting from imperial (default) to metric. to change it add the following to the ~/.config/aprsd/aprsd.yaml ... aprsd: units: metric
This commit is contained in:
parent
f8c001dc49
commit
2349024539
@ -11,6 +11,8 @@ ENV VIRTUAL_ENV=$HOME/.venv3
|
||||
|
||||
ENV INSTALL=$HOME/install
|
||||
RUN apk add --update git vim wget py3-pip py3-virtualenv bash fortune
|
||||
RUN apk add --update gcc python3-dev linux-headers musl-dev libffi-dev libc-dev
|
||||
RUN apk add --update openssl-dev
|
||||
|
||||
# Setup Timezone
|
||||
ENV TZ=US/Eastern
|
||||
|
@ -54,14 +54,20 @@ def get_weather_gov_metar(station):
|
||||
return json.loads(response)
|
||||
|
||||
|
||||
def fetch_openweathermap(api_key, lat, lon, exclude=None):
|
||||
def fetch_openweathermap(api_key, lat, lon, units="metric", exclude=None):
|
||||
LOG.debug("Fetch openweathermap for {}, {}".format(lat, lon))
|
||||
if not exclude:
|
||||
exclude = "minutely,hourly,daily,alerts"
|
||||
try:
|
||||
url = (
|
||||
"https://api.openweathermap.org/data/2.5/onecall?"
|
||||
"lat={}&lon={}&appid={}&exclude={}".format(lat, lon, api_key, exclude)
|
||||
"lat={}&lon={}&appid={}&units={}&exclude={}".format(
|
||||
lat,
|
||||
lon,
|
||||
api_key,
|
||||
units,
|
||||
exclude,
|
||||
)
|
||||
)
|
||||
response = requests.get(url)
|
||||
except Exception as e:
|
||||
|
@ -2,8 +2,7 @@ import json
|
||||
import logging
|
||||
import re
|
||||
|
||||
from aprsd import plugin
|
||||
import requests
|
||||
from aprsd import plugin, plugin_utils, utils
|
||||
|
||||
LOG = logging.getLogger("APRSD")
|
||||
|
||||
@ -19,91 +18,42 @@ class WeatherPlugin(plugin.APRSDPluginBase):
|
||||
LOG.info("Weather Plugin")
|
||||
api_key = self.config["aprs.fi"]["apiKey"]
|
||||
try:
|
||||
url = (
|
||||
"http://api.aprs.fi/api/get?"
|
||||
"&what=loc&apikey={}&format=json"
|
||||
"&name={}".format(api_key, fromcall)
|
||||
)
|
||||
response = requests.get(url)
|
||||
# aprs_data = json.loads(response.read())
|
||||
aprs_data = json.loads(response.text)
|
||||
lat = aprs_data["entries"][0]["lat"]
|
||||
lon = aprs_data["entries"][0]["lng"]
|
||||
url2 = (
|
||||
"https://forecast.weather.gov/MapClick.php?lat=%s"
|
||||
"&lon=%s&FcstType=json" % (lat, lon)
|
||||
)
|
||||
response2 = requests.get(url2)
|
||||
# wx_data = json.loads(response2.read())
|
||||
wx_data = json.loads(response2.text)
|
||||
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))
|
||||
except Exception as e:
|
||||
LOG.debug("Weather failed with: " + "%s" % str(e))
|
||||
reply = "Unable to find you (send beacon?)"
|
||||
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
|
||||
|
||||
|
||||
class WxPlugin(plugin.APRSDPluginBase):
|
||||
class USMetarPlugin(plugin.APRSDPluginBase):
|
||||
"""METAR Command"""
|
||||
|
||||
version = "1.0"
|
||||
command_regex = "^[wx]"
|
||||
command_name = "wx (Metar)"
|
||||
|
||||
def get_aprs(self, fromcall):
|
||||
LOG.debug("Fetch aprs.fi location for '{}'".format(fromcall))
|
||||
api_key = self.config["aprs.fi"]["apiKey"]
|
||||
try:
|
||||
url = (
|
||||
"http://api.aprs.fi/api/get?"
|
||||
"&what=loc&apikey={}&format=json"
|
||||
"&name={}".format(api_key, fromcall)
|
||||
)
|
||||
response = requests.get(url)
|
||||
except Exception:
|
||||
raise Exception("Failed to get aprs.fi location")
|
||||
else:
|
||||
response.raise_for_status()
|
||||
return response
|
||||
|
||||
def get_station(self, lat, lon):
|
||||
LOG.debug("Fetch station at {}, {}".format(lat, lon))
|
||||
try:
|
||||
url2 = (
|
||||
"https://forecast.weather.gov/MapClick.php?lat=%s"
|
||||
"&lon=%s&FcstType=json" % (lat, lon)
|
||||
)
|
||||
response = requests.get(url2)
|
||||
except Exception:
|
||||
raise Exception("Failed to get metar station")
|
||||
else:
|
||||
response.raise_for_status()
|
||||
return response
|
||||
|
||||
def get_metar(self, station):
|
||||
LOG.debug("Fetch metar for station '{}'".format(station))
|
||||
try:
|
||||
url = "https://api.weather.gov/stations/{}/observations/latest".format(
|
||||
station,
|
||||
)
|
||||
response = requests.get(url)
|
||||
except Exception:
|
||||
raise Exception("Failed to fetch metar")
|
||||
else:
|
||||
response.raise_for_status()
|
||||
return response
|
||||
command_regex = "^[metar]"
|
||||
command_name = "Metar"
|
||||
|
||||
def command(self, fromcall, message, ack):
|
||||
LOG.info("WX Plugin '{}'".format(message))
|
||||
@ -112,7 +62,7 @@ class WxPlugin(plugin.APRSDPluginBase):
|
||||
searchcall = a.group(1)
|
||||
station = searchcall.upper()
|
||||
try:
|
||||
resp = self.get_metar(station)
|
||||
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"
|
||||
@ -124,36 +74,123 @@ class WxPlugin(plugin.APRSDPluginBase):
|
||||
else:
|
||||
# if no second argument, search for calling station
|
||||
fromcall = fromcall
|
||||
try:
|
||||
resp = self.get_aprs(fromcall)
|
||||
except Exception as e:
|
||||
LOG.debug("Weather failed with: {}".format(str(e)))
|
||||
reply = "Unable to find you (send beacon?)"
|
||||
else:
|
||||
aprs_data = json.loads(resp.text)
|
||||
lat = aprs_data["entries"][0]["lat"]
|
||||
lon = aprs_data["entries"][0]["lng"]
|
||||
|
||||
api_key = self.config["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 metar find station."
|
||||
|
||||
if wx_data["location"]["metar"]:
|
||||
station = wx_data["location"]["metar"]
|
||||
try:
|
||||
resp = self.get_station(lat, lon)
|
||||
resp = plugin_utils.get_weather_gov_metar(station)
|
||||
except Exception as e:
|
||||
LOG.debug("Weather failed with: {}".format(str(e)))
|
||||
reply = "Unable to find you (send beacon?)"
|
||||
reply = "Failed to get Metar"
|
||||
else:
|
||||
wx_data = json.loads(resp.text)
|
||||
|
||||
if wx_data["location"]["metar"]:
|
||||
station = wx_data["location"]["metar"]
|
||||
try:
|
||||
resp = self.get_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"
|
||||
station_data = json.loads(resp.text)
|
||||
reply = station_data["properties"]["rawMessage"]
|
||||
else:
|
||||
# Couldn't find a station
|
||||
reply = "No Metar station found"
|
||||
|
||||
return reply
|
||||
|
||||
|
||||
class OWMWeatherPlugin(plugin.APRSDPluginBase):
|
||||
"""OpenWeatherMap Weather Command"""
|
||||
|
||||
version = "1.0"
|
||||
command_regex = "^[wW]"
|
||||
command_name = "Weather"
|
||||
|
||||
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
|
||||
|
||||
api_key = self.config["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))
|
||||
lat = aprs_data["entries"][0]["lat"]
|
||||
lon = aprs_data["entries"][0]["lng"]
|
||||
|
||||
try:
|
||||
utils.check_config_option(self.config, "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["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
|
||||
|
@ -46,6 +46,7 @@ DEFAULT_CONFIG_DICT = {
|
||||
"aprsd": {
|
||||
"plugin_dir": "~/.config/aprsd/plugins",
|
||||
"enabled_plugins": plugin.CORE_PLUGINS,
|
||||
"units": "imperial",
|
||||
},
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user