Skip to content

Commit

Permalink
[weather.metoffice] v4.1.0 (#2499)
Browse files Browse the repository at this point in the history
  • Loading branch information
powlo authored Aug 18, 2023
1 parent 941d975 commit 1e0626c
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 15 deletions.
2 changes: 1 addition & 1 deletion weather.metoffice/addon.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon id="weather.metoffice" version="4.0.0" name="Met Office" provider-name="powlo">
<addon id="weather.metoffice" version="4.1.0" name="Met Office" provider-name="powlo">
<requires>
<import addon="xbmc.python" version="3.0.0" />
<import addon="script.module.pytz" version="2014.2" />
Expand Down
6 changes: 5 additions & 1 deletion weather.metoffice/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ v3.0.0
v4.0.0
- Cleaned up memory leaks
- Removed unused imaging code.
- Removed default API key and nudged user to get their own.
- Removed default API key and nudged user to get their own.

v4.1.0
- Added feels like calculation.
- Updated geoip providers.
2 changes: 1 addition & 1 deletion weather.metoffice/resources/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<setting id="ApiKey" label="32003" type="text" default="a5408080-80af-44ea-b3a6-b86d320dc706" />
<setting id="GeoLocation" label="32004" type="bool" default="true" />
<setting id="GeoIPProvider" label="32005" type="enum"
values="www.ip-api.com|www.freegeoip.net|www.geoiplookup.net" enable="eq(-1,true)" default="0" />
values="www.ip-api.com|www.geoiplookup.net|www.ipapi.co" enable="eq(-1,true)" default="0" />
<setting id="EraseCache" label="32006" type="bool" default="false" />
</category>
</settings>
7 changes: 7 additions & 0 deletions weather.metoffice/src/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# * http://www.gnu.org/copyleft/gpl.html
import socket
import sys
import traceback
from urllib.error import HTTPError

import xbmc
Expand Down Expand Up @@ -54,7 +55,13 @@ def main():
properties.daily()
properties.threehourly()
properties.sunrisesunset()
except KeyError:
# Expect KeyErrors to come from parsing JSON responses.
# This is considered an intermittent error, so exception is eaten.
utilities.log(traceback.format_exc(), xbmc.LOGERROR)
except HTTPError:
# HTTPErrors are most likely to occur when the user hasn't set their API
# key, so allow the script to raise to produce a parp.
utilities.log(
(
"Error fetching data.\n"
Expand Down
4 changes: 2 additions & 2 deletions weather.metoffice/src/metoffice/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,12 @@ def addon():
GEOIP_PROVIDERS = [
{"url": "http://ip-api.com/json/", "latitude": "lat", "longitude": "lon"},
{
"url": "http://freegeoip.net/json/",
"url": "https://api.geoiplookup.net/?json=true",
"latitude": "latitude",
"longitude": "longitude",
},
{
"url": "http://geoiplookup.net/geoapi.php?output=json",
"url": "https://ipapi.co/json/",
"latitude": "latitude",
"longitude": "longitude",
},
Expand Down
22 changes: 21 additions & 1 deletion weather.metoffice/src/metoffice/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,13 @@ def observation():
)
window().setProperty("Current.FeelsLike", "n/a")
# if we get Wind, then convert it to kmph.
window().setProperty("Current.Wind", utilities.mph_to_kmph(latest_obs, "S"))
wind_speed = latest_obs.get("S")
if wind_speed:
window().setProperty(
"Current.Wind", str(round(utilities.mph_to_kph(float(wind_speed)), 0))
)
else:
window().setProperty("Current.Wind", "n/a")
window().setProperty("Current.WindDirection", latest_obs.get("D", "n/a"))
window().setProperty("Current.WindGust", latest_obs.get("G", "n/a"))
window().setProperty(
Expand All @@ -83,6 +89,20 @@ def observation():
"Current.DewPoint",
str(round(float(latest_obs.get("Dp", "n/a")))).split(".")[0],
)
humidity = latest_obs.get("H")
temperature = latest_obs.get("T")
if humidity and temperature and wind_speed:
ws_mps = utilities.mph_to_mps(float(wind_speed))
feels_like = utilities.feels_like(
float(temperature), float(humidity) / 100, ws_mps
)
window().setProperty(
"Current.FeelsLike",
str(round(feels_like)),
)
else:
window().setProperty("Current.FeelsLike", "n/a")

window().setProperty(
"Current.Humidity",
str(round(float(latest_obs.get("H", "n/a")))).split(".")[0],
Expand Down
97 changes: 88 additions & 9 deletions weather.metoffice/src/metoffice/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,8 @@
import xbmc
import xbmcgui

from .constants import (
ADDON_BROWSER_WINDOW_ID,
TEMPERATUREUNITS,
WEATHER_WINDOW_ID,
addon,
dialog,
)
from .constants import (ADDON_BROWSER_WINDOW_ID, TEMPERATUREUNITS,
WEATHER_WINDOW_ID, addon, dialog)


def log(msg, level=xbmc.LOGINFO):
Expand Down Expand Up @@ -119,6 +114,86 @@ def haversine_distance(lat1, lon1, lat2, lon2):
return EARTH_RADIUS * c


def feels_like(temp, humidity, windspeed):
# https://blog.metoffice.gov.uk/2012/02/15/what-is-feels-like-temperature/
# Using these facts we use a formula to adjust the air temperature based
# on our understanding of wind chill at lower temperatures, heat index at
# higher temperatures and a combination of the two in between.

# Inspect temperature and humidity to determine which functions below
# should be applied.

# But for now just use the 'simplified' apparent temperature.
return apparent_temperature_simplified(temp, humidity, windspeed)


def water_vapour_pressure(t, rh):
# Temperature (t) is a float from 0 to 100 representing a temperature in degrees C.
# Relative humidity (rh) is a float from 0.00 to 1.00 representing a percentage.
return rh * 6.105 * math.e ** (17.27 * t / (237.7 + t))


def apparent_temperature_simplified(t, rh, ws):
# A version of apparent temperature that doesn't need Q factor.
# From the Land of Oz.
# https://www.vcalc.com/wiki/rklarsen/Australian+Apparent+Temperature+%28AT%29
hPa = water_vapour_pressure(t, rh)
return t + (0.33 * hPa) - (0.70 * ws) - 4.00


def apparent_temperature(t, rh, ws, Q=0):
# https://calculator.academy/apparent-temperature-calculator/
# temp in degrees C
# humidity ...
# windspeed in metres per second
# TODO: Q is a fudge factor based on absorbed solar radiation.
hPa = water_vapour_pressure(t, rh)
return t + 0.38 * hPa - 0.70 * ws + 0.70 * (Q / (ws + 10)) - 4.25


def wind_chill(temp, windspeed):
# Use wind chill at lower winter temperatures.
return (
13.12
+ 0.6215 * temp
- 11.37 * windspeed**0.16
+ 0.3965 * temp * windspeed**0.16
)


def heat_index(t, r):
# Use heat index for high summer temperatures.
"""
See: https://en.wikipedia.org/wiki/Heat_index
The formula below approximates the heat index in degrees Fahrenheit,
to within ±1.3 °F (0.7 °C). It is the result of a multivariate fit
(temperature equal to or greater than 80 °F (27 °C)
"""

# NB!!! rh here is a percentage expressed as 0 - 100!

c1 = -8.78469475556
c2 = 1.61139411
c3 = 2.33854883889
c4 = -0.14611605
c5 = -0.012308094
c6 = -0.0164248277778
c7 = 0.002211732
c8 = 0.00072546
c9 = -0.000003582
return (
c1
+ c2 * t
+ c3 * r
+ c4 * t * r
+ c5 * (t**2)
+ c6 * (r**2)
+ c7 * (t**2) * r
+ c8 * t * (r**2)
+ c9 * (t**2) * (r**2)
)


def rownd(x):
try:
return str(round(float(x), 0)).split(".")[0]
Expand All @@ -142,13 +217,17 @@ def localised_temperature(t):


@f_or_nla
def mph_to_kmph(obj, key):
def mph_to_kph(x):
"""
Convert miles per hour to kilomenters per hour
Required because Kodi assumes that wind speed is provided in
kilometers per hour.
"""
return str(round(float(obj[key]) * 1.609344, 0))
return x * 1.609344


def mph_to_mps(x):
return x / 2.237


def gettext(s):
Expand Down

0 comments on commit 1e0626c

Please sign in to comment.