diff options
Diffstat (limited to 'weather.py')
-rwxr-xr-x | weather.py | 70 |
1 files changed, 59 insertions, 11 deletions
diff --git a/weather.py b/weather.py index 12ae7d6..638d14d 100755 --- a/weather.py +++ b/weather.py @@ -11,35 +11,83 @@ headers = { 'accept': 'application/ld+json' } +# SGR decorations / ANSI escape colors +class term: + RESET = '\033[0m' + BOLD = '\033[1m' + def handle_args(): parser = ArgumentParser() parser.add_argument('lat', help='latitude') parser.add_argument('lon', help='longitude') return parser.parse_args() -def print_alerts(zone): - alerts = requests.get(base_url + f'/alerts/active/zone/{zone}', - headers = headers).json() - print(alerts.get('title')) - print() +def print_alerts(county, zone): + # in some areas, alerts are not published for the zone but only for the county + # you can request both like this rather than making two requests + alerts = requests.get(base_url + f'/alerts/active?zone={county},{zone}', + headers=headers).json() + + # this title was cooler when we requested only one zone + # e.g. it would end with "for Holmes County (MSC051) MS" + # but now it's just "current watches, warnings, and advisories" + print(f'{term.BOLD}{alerts.get("title")}') + print(f'===================={term.RESET}') for alert in alerts.get('@graph'): - print(f'- {alert.get("headline")}') + print(f'{alert.get("headline")}') print(f' Severity: {alert.get("severity")}') - print(f' Expires: {alert.get("expires")}') + print(f' Until: {alert.get("expires")}') print(f'{alert.get("description")}') - print() + # TODO description can be quite long + # short desc appears to be available as parameters.NWSheadline[0] + # and follow up with instruction when it exists + print('--------------------') + + # many more cool fields available. + # verious datetimes: sent, effective, onset, expires, ends + # severity: Minor, Moderate, Severe, Extreme, Unknown + # certainty: Possible, Likely, Observed, Unknown + # urgency: Future, Expected, Immediate, Unknown + # messageType: Alert, Update + + # can construct the headline ourseves as f'{event} issued {sent} [until {end}] by {senderName}' + +def print_forecast(forecast_url): + # TODO pick up gridId AFC (AER/ALU), AFG, AJK, BOX< CAE, DLH, FSD, HGX, HNX, LIX, LWX, MAF, MFR, MLB, MRX, MTR, PIH and reduce gridX and gridY by 1 - known issue + + forecast = requests.get(forecast_url, headers=headers).json() + # TODO retry on 500 - known issue + # TODO query param units=si + # TODO cache for like four hours per location, forecast doesn't change that frequently + + # TODO replace the whole thing with /gridpoints/{point.gridId}/{gridX},{gridY} and create our own forecast + # there is lots more information there that would be useful + # probabilityOfPrecipitation is the neatest one that's not in .../forecast or .../forecast/hourly + # but there's also relativeHumidity, apparentTemperature (and, separately, windChill), skyCover, windGust + # downside, it appears to always convert the F/mph measurements into C/kph for no reason. e.g. all temps are measured in 9ths of C + + print(f'{term.BOLD}Forecast}') + print(f'===================={term.RESET}') + for period in forecast.get('periods'): + # TODO parse isDaytime true/false to squish a day together + print(f'{term.BOLD}{period.get("name")}{term.RESET}:') + print(f' {period.get("temperature")}°{period.get("temperatureUnit")}, wind {period.get("windSpeed")} {period.get("windDirection")}') + print(f' {period.get("detailedForecast")}') def main(): args = handle_args() point = requests.get(base_url + f'/points/{args.lat},{args.lon}', - headers = headers).json() + headers=headers).json() + county = point.get('county').split('/')[-1] zone = point.get('forecastZone').split('/')[-1] - print_alerts(zone) + print_alerts(county, zone) + + # TODO can hazardous weather outlook be gotten programatically? forecast_url = point.get('forecast') - # print_forecast(forecast_url) + print_forecast(forecast_url) # hourly_forecast_url = point.get('forecastHourly') |