Created
March 21, 2017 15:12
-
-
Save isoraqathedh/e2d58c8cdbfc0bc6f23712e70bcb3720 to your computer and use it in GitHub Desktop.
Display script for i3blocks: weather from Dark Sky API
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/python3 | |
# Display driver for i3blocks | |
# Displays weather information that's cached in a named file. | |
import json | |
import sys | |
import os | |
import math | |
import colorlover as colours | |
import time | |
import notify2 | |
cacheFile = os.path.dirname(os.path.abspath(__file__)) + "/cache.json" | |
# Variables | |
quantity = os.getenv("BLOCK_INSTANCE") or 'temperature' | |
goodQuantities = { | |
'temperature': lambda x: -4 < x < 35, | |
'humidity': lambda x: 0.20 < x <= 0.95, | |
'pressure': lambda x: 950 <= x, | |
'windSpeed': lambda x: 0 <= x < 35, | |
'icon': lambda x: x in ["clear-day", "clear-night", "cloudy", | |
"partly-cloudy-day", "partly-cloudy-night"], | |
'rain': lambda x: x < 15, | |
'rainprob': lambda x: x < 0.95, | |
'visibility': lambda x: x > 0.5, | |
'windBearing': lambda x: True, | |
'cloudCover': lambda x: x > 0.20 | |
} | |
units = { | |
'temperature': "°C", | |
'apparentTemperature': "°C", | |
'humidity': "%", | |
'cloudCover': "%", | |
'pressure': " hPa", | |
'windSpeed': " km/h", | |
'visibility': " km", | |
'windBearing': "°", | |
'precipIntensity': " mm/h" | |
} | |
colourmap = { | |
"scales": { | |
'temperature': ('div', 'RdBu'), | |
'humidity': ('div', 'RdBu'), | |
'pressure': ('div', 'RdBu'), | |
'windSpeed': ('seq', 'Reds'), | |
'visibility': ('seq', 'Reds'), | |
'rain': ('seq', 'Purples'), | |
'cloudCover': ('seq', 'Blues') | |
}, | |
"thresholds": { | |
'temperature': [-1, 4, 10, 22, 28, 32], | |
'apparentTemperature': [-1, 4, 10, 22, 28, 32], | |
'humidity': [0.35, 0.50, 0.70, 0.85], | |
'pressure': [970, 1000, 1020, 1025], | |
'windSpeed': [12, 30, 40, 62, 87, 117], | |
'visibility': [1, 5], | |
'rain': [5, 8, 10, 20], | |
'cloudCover': [0.60, 0.75, 0.90] | |
}, | |
"reverse": ['visibility', 'temperature'] | |
} | |
urgent = 33 | |
# Exit and formatting | |
def i3bexit(main_text, short_text, status=0, colour=None): | |
print(main_text) | |
print(short_text) | |
if colour: | |
print("{}".format(colour)) | |
sys.exit(status) | |
def urgentp(key, value): | |
if goodQuantities[key](value): return 0 | |
else: return urgent | |
def clamp(x): | |
return max(0, min(x, 255)) | |
def colourhexcode(scheme, steps, index, reverse=False): | |
scale = colours.to_numeric(colours.scales[str(steps)][scheme[0]][scheme[1]]) | |
if reverse: | |
scale = scale[::-1] | |
reqcolour = tuple(map(math.floor, scale[index])) | |
return "#{0:02X}{1:02X}{2:02X}".format( | |
clamp(reqcolour[0]), clamp(reqcolour[1]), clamp(reqcolour[2])) | |
def colour(key, value): | |
if not key in colourmap['scales']: | |
return None | |
else: | |
ind = 0 | |
for i in colourmap['thresholds'][key]: | |
if value < i: break | |
else: ind += 1 | |
return colourhexcode(colourmap["scales"][key], | |
len(colourmap["thresholds"][key]) + 1, | |
ind, | |
key in colourmap['reverse']) | |
def weathericon(status): | |
try: | |
return { | |
"clear-day": "☀", | |
"clear-night": "☽", | |
"rain": "☔", | |
"snow": "☃", | |
"sleet": "≅", | |
"wind": "⚑", | |
"fog": "≡", | |
"cloudy": "☁", | |
"partly-cloudy-day": "⛅", | |
"partly-cloudy-night": "⛅ (☽)" | |
}[status] | |
except KeyError: | |
return "" | |
###### BEGIN SCRIPT ###### | |
# Read data | |
with open(cacheFile, 'r') as infile: | |
alldata = json.load(infile) | |
if 'error' in alldata: | |
# If error, exit with nothing. | |
i3bexit("Error", "—", 1) | |
elif os.getenv("BLOCK_BUTTON") == '1': | |
# Give a forecast if the block is clicked | |
notify2.init("i3bweather") | |
hoursToRead = 5 | |
if quantity == 'status': | |
outText = alldata['hourly']['summary'] | |
header = "General weather forecast" | |
elif quantity == 'rain': | |
outText = "\n".join( | |
["{}{}".format(x['precipIntensity'], units['precipIntensity']) | |
for x in alldata['hourly']['data']][:hoursToRead]) | |
header = "Rainfall forecast" | |
elif quantity in units: | |
values = [x[quantity] for x in alldata['hourly']['data']][:hoursToRead] | |
if units[quantity] == '%': | |
values = ["{:.0%}".format(x) for x in values] | |
else: | |
values = ["{}{}".format(x, units[quantity]) | |
for x in values] | |
outText = "\n".join(values) | |
header = "Forecast for {}".format(quantity) | |
notify2.Notification(header, outText, "notification-message-im").show() | |
# Then restore to the old data. | |
data = alldata['currently'] | |
# Special values that require handling | |
if quantity == 'status': | |
i3bexit(weathericon(data['icon']) + " " + data['summary'], | |
data['summary'], | |
urgentp('icon', data['icon'])) | |
elif quantity == 'rain': | |
if ((data['precipProbability'] > 0.5 and not data['precipType'] == "snow") | |
or data['precipIntensity'] > 5): | |
value = data['precipIntensity'] | |
i3bexit("{}{}".format(value, units[quantity]), | |
"{}{}".format(value, units[quantity]), | |
urgentp('rain', value), | |
colour('rain', value)) | |
elif data['precipProbability'] > 0.1: | |
value = data['precipProbability'] | |
i3bexit("\u2614 {.0%}".format(value), | |
"\u2614 {.0%}".format(value), | |
urgentp('rainprob', value)) | |
elif data['cloudCover'] > 0.25: | |
value = math.floor(data['cloudCover'] * 100) | |
i3bexit("\u2601 {.0%}".format(value), | |
"\u2601 {.0%}".format(value), | |
urgentp('cloudCover', value), | |
colour('cloudCover', value)) | |
else: | |
i3bexit("\u2601\u20e0 ", "", urgent) | |
elif quantity == "apparentTemperature": | |
if abs(data[quantity] - data['temperature']) < 1: | |
# Apparent temperature is not worth listing | |
# If it's very close to the real temperature. | |
i3bexit("", "", 0) | |
else: | |
value = data[quantity] if quantity in data else "-" | |
i3bexit("({}{})".format(value, units[quantity]), | |
"", | |
urgentp(quantity, value), | |
colour(quantity, value)) | |
# Default | |
elif quantity in data: | |
value = data[quantity] if quantity in data else "-" | |
if quantity == 'humidity': | |
i3bexit("{:.0%}".format(value), | |
"{:.0%}".format(value), | |
urgentp(quantity, value), | |
colour(quantity,value)) | |
elif quantity == 'visibility' and value >= 15: | |
i3bexit("", "", 0) | |
i3bexit("{}{}".format(value, units[quantity]), | |
"{}{}".format(value, units[quantity]), | |
urgentp(quantity, value), | |
colour(quantity, value)) | |
else: | |
# If the key is bogus or missing, just exit with a dash. | |
i3bexit("—", "", 0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment