-
-
Save jasonsnell/2757e58081a1ae377a9c0feed875976b to your computer and use it in GitHub Desktop.
| #! /usr/bin/env python3 | |
| import time | |
| import jwt | |
| import json | |
| import requests | |
| from datetime import datetime | |
| from collections import defaultdict | |
| import matplotlib.pyplot as plt | |
| theDayCondition = defaultdict(lambda: -99999) | |
| hitemp = defaultdict(lambda: -99999) | |
| lotemp = defaultdict(lambda: 99999) | |
| datelist = defaultdict(lambda: 99999) | |
| diff = {} | |
| theDates = [1, 2, 3, 4, 5, 6, 7, 8] | |
| # all these variables below need to be customized | |
| lat = "your-latitude" | |
| lon = "your-longitude" | |
| chartSavePath = '/Users/your-user-name/Desktop/' | |
| team_id = "your_team_id" | |
| service_id = "com.yourdomain.weatherproject" | |
| key_id = "your_key_id" | |
| private_key = "-----YOUR PRIVATE KEY-----" | |
| def symbolFromConditions(theCondition, theRequest): | |
| # SFSymbols look weird but they theoretically will print properly! | |
| conditionSymbol = "" | |
| if theCondition == "Clear": | |
| symbolName = "sun.max" | |
| theSFSymbol = "" | |
| elif theCondition == "MostlyClear": | |
| symbolName = "sun.min" | |
| theSFSymbol = "" | |
| elif theCondition == "PartlyCloudy": | |
| symbolName = "cloud.sun" | |
| theSFSymbol = "" | |
| elif theCondition == "MostlyCloudy": | |
| symbolName = "cloud" | |
| theSFSymbol = "" | |
| elif theCondition == "Cloudy": | |
| symbolName = "cloud" | |
| theSFSymbol = "" | |
| elif theCondition == "Hazy": | |
| symbolName = "sun.haze" | |
| theSFSymbol = "" | |
| elif theCondition == "ScatteredThunderstorms": | |
| symbolName = "cloud.sun.bolt" | |
| theSFSymbol = "" | |
| elif theCondition == "Drizzle": | |
| symbolName = "cloud.drizzle" | |
| theSFSymbol = "" | |
| elif theCondition == "rain": | |
| symbolName = "cloud.rain" | |
| theSFSymbol = "" | |
| elif theCondition == "HeavyRain": | |
| symbolName = "cloud.heavyrain" | |
| theSFSymbol = "" | |
| else: | |
| symbolName = theCondition | |
| theSFSymbol = theCondition | |
| if theRequest == "sf": | |
| return theSFSymbol | |
| else: | |
| return (f':{symbolName}: ') | |
| expiry = (int(time.time()) + 60) | |
| encoded_jwt = jwt.encode({"iss": team_id, "iat": int(time.time()), "exp": expiry, "sub": service_id}, private_key, algorithm="ES256", headers={"kid": key_id, "id": (team_id + '.' + service_id)}) | |
| dailyurl = f"https://weatherkit.apple.com/api/v1/weather/en/{lat}/{lon}?dataSets=forecastDaily&timezone=America/Los_Angeles" | |
| d = requests.get(dailyurl, headers={"Authorization":("Bearer " + encoded_jwt)}) | |
| if len(d.content) < 1: | |
| raise Exception("File not retrieved") | |
| # dailyForecast is the variable containing the entire forecast payload | |
| dailyForecast = json.loads(d.content) | |
| todayHiC = dailyForecast['forecastDaily']['days'][0]['temperatureMax'] | |
| todayLoC = dailyForecast['forecastDaily']['days'][0]['temperatureMin'] | |
| todayHiF = int((todayHiC * 9/5) + 32) | |
| todayLoF = int((todayLoC * 9/5) + 32) | |
| todayCondition = dailyForecast['forecastDaily']['days'][0]['restOfDayForecast']['conditionCode'] | |
| todayPrecip = dailyForecast['forecastDaily']['days'][0]['restOfDayForecast']['precipitationType'] | |
| if todayPrecip != "clear": | |
| conditionSymbol = symbolFromConditions(todayPrecip, '') | |
| else: | |
| conditionSymbol = symbolFromConditions(todayCondition, '') | |
| print (f'{conditionSymbol} {todayHiF}°/{todayLoF}°') | |
| for dayItem in range(1,9): | |
| thisHiC = dailyForecast['forecastDaily']['days'][dayItem]['temperatureMax'] | |
| hitemp[dayItem] = int((thisHiC * 9/5) + 32) | |
| theDay = dailyForecast['forecastDaily']['days'][dayItem]['forecastStart'] | |
| theDayProper = datetime.strptime(theDay, "%Y-%m-%dT%H:%M:%SZ") | |
| datelist[dayItem] = datetime.strftime(theDayProper, "%a") | |
| theDayCondition[dayItem] = dailyForecast['forecastDaily']['days'][dayItem]['conditionCode'] | |
| thatPrecip = dailyForecast['forecastDaily']['days'][dayItem]['precipitationType'] | |
| # print(thatPrecip) | |
| if thatPrecip != "clear": | |
| theDayCondition[dayItem] = symbolFromConditions(thatPrecip, 'sf') | |
| else: | |
| theDayCondition[dayItem] = symbolFromConditions(theDayCondition[dayItem], 'sf') | |
| theHighs = list(hitemp.values()) | |
| theDateList = list(datelist.values()) | |
| theConditionsList = list(theDayCondition.values()) | |
| himin = min(theHighs) - 8 | |
| # Graphing | |
| fig, ax = plt.subplots() | |
| font = {'fontname': 'SF Pro'} | |
| ax.bar(theDates, theHighs, color="#333", alpha=0) | |
| ax.bar_label(ax.containers[0], color="black", fontweight='bold') | |
| ax.set_aspect(aspect=0.12) | |
| ax.set_yticks([]) | |
| for i in range(0,8): | |
| plt.text((i+1),(himin + 2),str(theConditionsList[i]), color="black", horizontalalignment='center', size='x-large', fontweight='bold', **font) | |
| plt.box(False) | |
| plt.ylim(ymin=himin) | |
| plt.xticks(theDates, theDateList, color="black", fontweight='bold') | |
| plt.savefig(f'{chartSavePath}forecast.png', dpi=300, bbox_inches='tight', | |
| pad_inches=0.05) |
Ok, thanks.
I'm very new to WeatherKit and trying to use your example script as a start to replace my DarkSky script that runs headless on a RaspberryPi. I'm simply trying to get the UV index for my lat/lon
It seems that installing the jwt library is the problem. Any suggestions or help would be appreciated. Thanks Jason
I am not a python expert but "pip install pyjwt" or "pip3 install pyjwt" to install that module
Thanks Jason. I was able to figure out the error; I needed to load the private_key as a file -NOT- embed the key in my code. The original Python script that you wrote was extremely helpful for my project as I move on from DarkSky to WeatherKit. I now need to polish my Python script a little but at least I have it working. Thanks again!
Is there a reason you import "requests" twice? (Line 3 and line 7.)