Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[weather.metoffice] v4.1.0 #2499

Merged
merged 1 commit into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading