Forked from jasonsnell/weatherkit-sampleproject.py
Last active
July 10, 2022 04:40
-
-
Save holgr/2e293d43fc4b86abaf8ae0545206f172 to your computer and use it in GitHub Desktop.
WeatherKit API sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env python3 | |
# Make sure to install the correct PyJWT, not just JWT: pip install PyJWT. See https://stackoverflow.com/questions/33198428/jwt-module-object-has-no-attribute-encode | |
import time | |
import jwt | |
import json | |
import requests | |
from datetime import datetime | |
from collections import defaultdict | |
import matplotlib.pyplot as plt | |
from cryptography.hazmat.primitives import serialization as crypto_serialization | |
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_pem = "path-to-your-downloaded-AuthKey_key_id.p8" | |
with open(private_key_pem, "rb") as key_file: | |
private_key = crypto_serialization.load_pem_private_key(key_file.read(), password=None) | |
key = private_key.private_bytes(crypto_serialization.Encoding.PEM, | |
crypto_serialization.PrivateFormat.PKCS8, | |
crypto_serialization.NoEncryption()) | |
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}, 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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment