Weatherbit alerts API

This commit is contained in:
piotr
2022-06-21 03:29:46 +02:00
parent 996ad78f9a
commit 0588c18c9f
6 changed files with 368 additions and 37 deletions

View File

@@ -137,6 +137,7 @@ SKELETON_PANEL: dict = {
},
"openweather": {
"appid": "",
"weatherbit-api-key": "",
"lat": None,
"long": None,
"lang": "en",
@@ -914,9 +915,8 @@ class EditorWrapper(object):
if self.delete_weather_data:
tmp_dir = temp_dir()
for item in ["nwg-openweather-weather", "nwg-openweather-forecast"]:
for item in ["nwg-openweather-weather", "nwg-openweather-forecast", "nwg-weatherbit-alerts"]:
f = "{}-{}".format(os.path.join(tmp_dir, item), self.panel["openweather"]["module-id"])
# f = os.path.join(tmp_dir, item)
if os.path.exists(f):
eprint("Deleting {}".format(f))
os.remove(f)
@@ -1723,6 +1723,7 @@ class EditorWrapper(object):
defaults = {
"module-id": str(time.time()),
"appid": "",
"weatherbit-api-key": "",
"lat": None,
"long": None,
"lang": "en",
@@ -1770,6 +1771,12 @@ class EditorWrapper(object):
key_visibility_switch = builder.get_object("key-visibility-switch")
key_visibility_switch.connect("toggled", switch_entry_visibility, self.ow_appid)
self.weatherbit_api_key = builder.get_object("weatherbit-api-key")
self.weatherbit_api_key.set_text(settings["weatherbit-api-key"])
key_visibility_switch1 = builder.get_object("key-visibility-switch1")
key_visibility_switch1.connect("toggled", switch_entry_visibility, self.weatherbit_api_key)
# Try to obtain geolocation if unset
if not settings["lat"] or not settings["long"]:
# Try nwg-shell settings
@@ -1916,6 +1923,7 @@ class EditorWrapper(object):
settings = self.panel["openweather"]
settings["appid"] = self.ow_appid.get_text()
settings["weatherbit-api-key"] = self.weatherbit_api_key.get_text()
settings["lat"] = round(self.ow_lat.get_value(), 4)
settings["long"] = round(self.ow_long.get_value(), 4)
settings["lang"] = self.ow_lang.get_text()

View File

@@ -8,7 +8,7 @@
<property name="label-xalign">0.5</property>
<property name="shadow-type">out</property>
<child>
<!-- n-columns=3 n-rows=33 -->
<!-- n-columns=3 n-rows=35 -->
<object class="GtkGrid" id="grid">
<property name="visible">True</property>
<property name="can-focus">False</property>
@@ -773,6 +773,7 @@ Creative Commons Attribution-ShareAlike 4.0</property>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">&lt;a href="https://openweathermap.org/appid"&gt;https://openweathermap.org/appid&lt;/a&gt;</property>
<property name="use-markup">True</property>
</object>
@@ -781,38 +782,6 @@ Creative Commons Attribution-ShareAlike 4.0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="module-id">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="margin-top">6</property>
<property name="label" translatable="yes">module.id</property>
<attributes>
<attribute name="style" value="oblique"/>
</attributes>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">32</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="margin-top">6</property>
<property name="label" translatable="yes">Module ID:</property>
<attributes>
<attribute name="style" value="oblique"/>
</attributes>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">32</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="show-volume">
<property name="label" translatable="yes">Show precipitation volume</property>
@@ -827,6 +796,107 @@ Creative Commons Attribution-ShareAlike 4.0</property>
<property name="top-attach">31</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="module-id">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="margin-top">6</property>
<property name="label" translatable="yes">module.id</property>
<attributes>
<attribute name="style" value="oblique"/>
</attributes>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">34</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="margin-top">6</property>
<property name="label" translatable="yes">Module ID:</property>
<attributes>
<attribute name="style" value="oblique"/>
</attributes>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">34</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Alerts</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">32</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="halign">start</property>
<property name="label" translatable="yes">&lt;a href="https://www.weatherbit.io/account/create"&gt;https://www.weatherbit.io/account/create&lt;/a&gt;</property>
<property name="use-markup">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">32</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Weatherbit API key:</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">33</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="weatherbit-api-key">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="tooltip-text" translatable="yes">Paste your API key (appid) here.</property>
<property name="visibility">False</property>
<property name="invisible-char">●</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">33</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="key-visibility-switch1">
<property name="label" translatable="yes">show</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">33</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="6"
height="16"
viewBox="0 0 1.5874999 4.2333333"
version="1.1"
id="svg5"
xml:space="preserve"
sodipodi:docname="exclamation.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
showgrid="false"
inkscape:zoom="36.630209"
inkscape:cx="10.797099"
inkscape:cy="7.3300155"
inkscape:window-width="1918"
inkscape:window-height="1018"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showguides="true"><sodipodi:guide
position="1.5875,3.8866258"
orientation="-1,0"
id="guide5215"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
position="-1.6210715,4.2333331"
orientation="0,1"
id="guide2784"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /></sodipodi:namedview><defs
id="defs2" /><g
inkscape:label="Warstwa 1"
inkscape:groupmode="layer"
id="layer1"><text
xml:space="preserve"
style="font-size:3.25507px;line-height:1.25;font-family:sans-serif;fill:#444444;fill-opacity:0.811765;stroke-width:0.152581"
x="0.28444344"
y="3.4721246"
id="text1215"
transform="scale(1.1180032,0.89445183)"><tspan
sodipodi:role="line"
id="tspan1213"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#444444;fill-opacity:0.811765;stroke-width:0.152581"
x="0.28444344"
y="3.4721246">!</tspan></text><text
xml:space="preserve"
style="font-size:3.25507px;line-height:1.25;font-family:sans-serif;fill:#c86400;fill-opacity:1;stroke-width:0.152581"
x="0.23405394"
y="3.4159362"
id="text1215-2"
transform="scale(1.1180032,0.89445183)"><tspan
sodipodi:role="line"
id="tspan1213-9"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#c86400;fill-opacity:1;stroke-width:0.152581"
x="0.23405394"
y="3.4159362">!</tspan></text></g></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="6"
height="16"
viewBox="0 0 1.5874999 4.2333333"
version="1.1"
id="svg5"
xml:space="preserve"
sodipodi:docname="exclamation.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
showgrid="false"
inkscape:zoom="36.630209"
inkscape:cx="10.797099"
inkscape:cy="7.2754158"
inkscape:window-width="1918"
inkscape:window-height="1018"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showguides="true"><sodipodi:guide
position="1.5875,3.8866258"
orientation="-1,0"
id="guide5215"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
position="-1.6210715,4.2333331"
orientation="0,1"
id="guide2784"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /></sodipodi:namedview><defs
id="defs2" /><g
inkscape:label="Warstwa 1"
inkscape:groupmode="layer"
id="layer1"><text
xml:space="preserve"
style="font-size:3.25507px;line-height:1.25;font-family:sans-serif;fill:#444444;fill-opacity:0.811765;stroke-width:0.152581"
x="0.26079586"
y="3.4129782"
id="text1215"
transform="scale(1.1180032,0.89445183)"><tspan
sodipodi:role="line"
id="tspan1213"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#444444;fill-opacity:0.811765;stroke-width:0.152581"
x="0.26079586"
y="3.4129782">!</tspan></text></g></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="6"
height="16"
viewBox="0 0 1.5874999 4.2333333"
version="1.1"
id="svg5"
xml:space="preserve"
sodipodi:docname="exclamation.svg"
inkscape:version="1.2 (dc2aedaf03, 2022-05-15)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
showgrid="false"
inkscape:zoom="36.630209"
inkscape:cx="10.797099"
inkscape:cy="7.3300155"
inkscape:window-width="1918"
inkscape:window-height="1018"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showguides="true"><sodipodi:guide
position="1.5875,3.8866258"
orientation="-1,0"
id="guide5215"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
position="-1.6210715,4.2333331"
orientation="0,1"
id="guide2784"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /></sodipodi:namedview><defs
id="defs2" /><g
inkscape:label="Warstwa 1"
inkscape:groupmode="layer"
id="layer1"><text
xml:space="preserve"
style="font-size:3.25507px;line-height:1.25;font-family:sans-serif;fill:#efefef;fill-opacity:0.81176472;stroke-width:0.152581"
x="0.26079586"
y="3.4129782"
id="text1215"
transform="scale(1.1180032,0.89445183)"><tspan
sodipodi:role="line"
id="tspan1213"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#efefef;fill-opacity:0.81176472;stroke-width:0.152581"
x="0.26079586"
y="3.4129782">!</tspan></text></g></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -3,8 +3,8 @@
import json
import os
import stat
import sys
import subprocess
import sys
import threading
from datetime import datetime
@@ -70,6 +70,7 @@ def on_button_press(window, event):
class OpenWeather(Gtk.EventBox):
def __init__(self, settings, icons_path=""):
defaults = {"appid": "",
"weatherbit-api-key": "",
"lat": None,
"long": None,
"lang": "en",
@@ -140,11 +141,13 @@ class OpenWeather(Gtk.EventBox):
self.box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
self.add(self.box)
self.image = Gtk.Image()
self.alert_image = Gtk.Image()
self.label = Gtk.Label.new("No weather data")
self.icon_path = None
self.weather = None
self.forecast = None
self.alerts = None
self.connect('button-press-event', self.on_button_press)
self.add_events(Gdk.EventMask.SCROLL_MASK)
@@ -166,8 +169,10 @@ class OpenWeather(Gtk.EventBox):
tmp_dir = temp_dir()
self.weather_file = "{}-{}".format(os.path.join(tmp_dir, "nwg-openweather-weather"), settings["module-id"])
self.forecast_file = "{}-{}".format(os.path.join(tmp_dir, "nwg-openweather-forecast"), settings["module-id"])
self.alerts_file = "{}-{}".format(os.path.join(tmp_dir, "nwg-weatherbit-alerts"), settings["module-id"])
eprint("Weather file: {}".format(self.weather_file))
eprint("Forecast file: {}".format(self.forecast_file))
eprint("Alerts file: {}".format(self.alerts_file))
# Try to obtain geolocation if unset
if not settings["lat"] or not settings["long"]:
@@ -191,6 +196,12 @@ class OpenWeather(Gtk.EventBox):
self.forecast_request = "https://api.openweathermap.org/data/2.5/forecast?lat={}&lon={}&units={}&lang={}&appid={}".format(
settings["lat"], settings["long"], settings["units"], settings["lang"], settings["appid"])
self.alerts_request = "https://api.weatherbit.io/v2.0/alerts?lat={}&lon={}&key={}".format(settings["lat"],
settings["long"],
settings[
"weatherbit-api-key"]) if \
settings["weatherbit-api-key"] else ""
self.build_box()
self.refresh()
@@ -202,15 +213,19 @@ class OpenWeather(Gtk.EventBox):
def build_box(self):
if self.settings["icon-placement"] == "start":
self.box.pack_start(self.alert_image, False, False, 0)
self.box.pack_start(self.image, False, False, 2)
self.box.pack_start(self.label, False, False, 2)
if self.settings["icon-placement"] != "start":
self.box.pack_start(self.alert_image, False, False, 0)
self.box.pack_start(self.image, False, False, 2)
def get_data(self):
self.get_weather()
self.get_forecast()
if self.settings["weatherbit-api-key"]:
self.get_alerts()
GLib.idle_add(self.update_widget)
return True
@@ -270,6 +285,21 @@ class OpenWeather(Gtk.EventBox):
eprint(hms(), "Loading forecast data from file")
self.forecast = load_json(self.forecast_file)
def get_alerts(self):
if not os.path.isfile(self.alerts_file) or int(file_age(self.alerts_file) > self.settings["interval"] - 1):
eprint(hms(), "Requesting alerts data")
try:
r = requests.get(self.alerts_request)
self.alerts = json.loads(r.text)
if "alerts" in self.alerts:
save_json(self.alerts, self.alerts_file)
except Exception as e:
self.alerts = None
eprint(e)
elif not self.alerts and os.path.isfile(self.alerts_file):
eprint(hms(), "Loading alerts data from file")
self.alerts = load_json(self.alerts_file)
def update_widget(self):
if self.weather and self.weather["cod"] and self.weather["cod"] in [200, "200"]:
if "icon" in self.weather["weather"][0]:
@@ -282,6 +312,16 @@ class OpenWeather(Gtk.EventBox):
self.icon_path = new_path
except:
print("Failed setting image from {}".format(new_path))
if self.alerts and self.alerts["alerts"]:
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(os.path.join(self.weather_icons, "exclamation.svg"),
self.settings["icon-size"], self.settings["icon-size"])
self.alert_image.set_from_pixbuf(pixbuf)
print(self.alerts["alerts"][0]["title"])
else:
self.alert_image = Gtk.Image()
self.alert_image.set_size_request(0, 0)
lbl_content = ""
if "name" in self.weather:
desc = self.weather["name"] if not self.settings["loc-name"] else self.settings["loc-name"]
@@ -450,6 +490,19 @@ class OpenWeather(Gtk.EventBox):
hbox.pack_start(lbl, True, True, 0)
vbox.pack_start(hbox, False, False, 6)
# Alerts, if any
if self.alerts and "alerts" in self.alerts:
try:
hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)
lbl = Gtk.Label()
lbl.set_line_wrap(True)
lbl.set_justify(Gtk.Justification.CENTER)
lbl.set_markup('<span bgcolor="#cc0000"> {} </span>'.format(self.alerts["alerts"][0]["title"]))
hbox.pack_start(lbl, True, False, 6)
vbox.pack_start(hbox, False, False, 6)
except:
pass
# 5-DAY FORECAST
if self.forecast["cod"] in [200, "200"]:
lbl = Gtk.Label()
@@ -602,7 +655,7 @@ class OpenWeather(Gtk.EventBox):
if "snow" in data and "3h" in data["snow"]:
lbl = Gtk.Label()
lbl.set_markup('<span font_size="{}">{} mm</span>'.format(self.settings["popup-text-size"],
round(data["rain"]["3h"], 2)))
round(data["snow"]["3h"], 2)))
box.pack_start(lbl, False, False, 0)
grid.attach(box, 12, i, 1, 1)