From f64373c79e21d9c7b45c2aafc39264df0b0a2912 Mon Sep 17 00:00:00 2001 From: Indu Prakash <6459774+iprak@users.noreply.github.com> Date: Fri, 28 Apr 2023 20:40:05 -0500 Subject: [PATCH] Reworked integration (#32) * Simplied and used native_attr * Corrected/removed unnecessary tests --- custom_components/sample.json | 1023 +++++++++++++++++++ custom_components/weatherapi/coordinator.py | 54 +- custom_components/weatherapi/manifest.json | 2 +- custom_components/weatherapi/weather.py | 39 +- tests/test_coordinator.py | 64 +- 5 files changed, 1063 insertions(+), 119 deletions(-) create mode 100644 custom_components/sample.json diff --git a/custom_components/sample.json b/custom_components/sample.json new file mode 100644 index 0000000..d2279b6 --- /dev/null +++ b/custom_components/sample.json @@ -0,0 +1,1023 @@ +{ + "location": { + "name": "London", + "region": "City of London, Greater London", + "country": "United Kingdom", + "lat": 51.52, + "lon": -0.11, + "tz_id": "Europe/London", + "localtime_epoch": 1682645156, + "localtime": "2023-04-28 2:25" + }, + "current": { + "last_updated_epoch": 1682644500, + "last_updated": "2023-04-28 02:15", + "temp_c": 11.0, + "temp_f": 51.8, + "is_day": 0, + "condition": { + "text": "Overcast", + "icon": "//cdn.weatherapi.com/weather/64x64/night/122.png", + "code": 1009 + }, + "wind_mph": 3.8, + "wind_kph": 6.1, + "wind_degree": 170, + "wind_dir": "S", + "pressure_mb": 1007.0, + "pressure_in": 29.74, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 100, + "cloud": 100, + "feelslike_c": 9.8, + "feelslike_f": 49.7, + "vis_km": 3.8, + "vis_miles": 2.0, + "uv": 1.0, + "gust_mph": 10.5, + "gust_kph": 16.9 + }, + "forecast": { + "forecastday": [ + { + "date": "2023-04-28", + "date_epoch": 1682640000, + "day": { + "maxtemp_c": 17.6, + "maxtemp_f": 63.7, + "mintemp_c": 10.6, + "mintemp_f": 51.1, + "avgtemp_c": 13.7, + "avgtemp_f": 56.6, + "maxwind_mph": 14.1, + "maxwind_kph": 22.7, + "totalprecip_mm": 0.4, + "totalprecip_in": 0.02, + "totalsnow_cm": 0.0, + "avgvis_km": 8.3, + "avgvis_miles": 5.0, + "avghumidity": 82.0, + "daily_will_it_rain": 1, + "daily_chance_of_rain": 89, + "daily_will_it_snow": 0, + "daily_chance_of_snow": 0, + "condition": { + "text": "Patchy rain possible", + "icon": "//cdn.weatherapi.com/weather/64x64/day/176.png", + "code": 1063 + }, + "uv": 3.0 + }, + "astro": { + "sunrise": "05:39 AM", + "sunset": "08:18 PM", + "moonrise": "11:50 AM", + "moonset": "03:40 AM", + "moon_phase": "Waxing Gibbous", + "moon_illumination": "51", + "is_moon_up": 1, + "is_sun_up": 0 + }, + "hour": [ + { + "time_epoch": 1682636400, + "time": "2023-04-28 00:00", + "temp_c": 10.6, + "temp_f": 51.1, + "is_day": 0, + "condition": { + "text": "Fog", + "icon": "//cdn.weatherapi.com/weather/64x64/night/248.png", + "code": 1135 + }, + "wind_mph": 4.9, + "wind_kph": 7.9, + "wind_degree": 138, + "wind_dir": "SE", + "pressure_mb": 1008.0, + "pressure_in": 29.77, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 99, + "cloud": 100, + "feelslike_c": 9.7, + "feelslike_f": 49.5, + "windchill_c": 9.7, + "windchill_f": 49.5, + "heatindex_c": 10.6, + "heatindex_f": 51.1, + "dewpoint_c": 10.5, + "dewpoint_f": 50.9, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 0.0, + "vis_miles": 0.0, + "gust_mph": 8.1, + "gust_kph": 13.0, + "uv": 1.0 + }, + { + "time_epoch": 1682640000, + "time": "2023-04-28 01:00", + "temp_c": 10.7, + "temp_f": 51.3, + "is_day": 0, + "condition": { + "text": "Fog", + "icon": "//cdn.weatherapi.com/weather/64x64/night/248.png", + "code": 1135 + }, + "wind_mph": 4.0, + "wind_kph": 6.5, + "wind_degree": 187, + "wind_dir": "S", + "pressure_mb": 1008.0, + "pressure_in": 29.76, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 99, + "cloud": 100, + "feelslike_c": 10.2, + "feelslike_f": 50.4, + "windchill_c": 10.2, + "windchill_f": 50.4, + "heatindex_c": 10.7, + "heatindex_f": 51.3, + "dewpoint_c": 10.6, + "dewpoint_f": 51.1, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 0.0, + "vis_miles": 0.0, + "gust_mph": 6.7, + "gust_kph": 10.8, + "uv": 1.0 + }, + { + "time_epoch": 1682643600, + "time": "2023-04-28 02:00", + "temp_c": 11.1, + "temp_f": 52.0, + "is_day": 0, + "condition": { + "text": "Fog", + "icon": "//cdn.weatherapi.com/weather/64x64/night/248.png", + "code": 1135 + }, + "wind_mph": 6.3, + "wind_kph": 10.1, + "wind_degree": 219, + "wind_dir": "SW", + "pressure_mb": 1008.0, + "pressure_in": 29.75, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 99, + "cloud": 100, + "feelslike_c": 9.9, + "feelslike_f": 49.8, + "windchill_c": 9.9, + "windchill_f": 49.8, + "heatindex_c": 11.1, + "heatindex_f": 52.0, + "dewpoint_c": 11.0, + "dewpoint_f": 51.8, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 0.0, + "vis_miles": 0.0, + "gust_mph": 10.5, + "gust_kph": 16.9, + "uv": 1.0 + }, + { + "time_epoch": 1682647200, + "time": "2023-04-28 03:00", + "temp_c": 11.6, + "temp_f": 52.9, + "is_day": 0, + "condition": { + "text": "Fog", + "icon": "//cdn.weatherapi.com/weather/64x64/night/248.png", + "code": 1135 + }, + "wind_mph": 7.6, + "wind_kph": 12.2, + "wind_degree": 231, + "wind_dir": "SW", + "pressure_mb": 1008.0, + "pressure_in": 29.76, + "precip_mm": 0.1, + "precip_in": 0.0, + "humidity": 99, + "cloud": 100, + "feelslike_c": 10.2, + "feelslike_f": 50.4, + "windchill_c": 10.2, + "windchill_f": 50.4, + "heatindex_c": 11.6, + "heatindex_f": 52.9, + "dewpoint_c": 11.4, + "dewpoint_f": 52.5, + "will_it_rain": 1, + "chance_of_rain": 78, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 0.0, + "vis_miles": 0.0, + "gust_mph": 12.1, + "gust_kph": 19.4, + "uv": 1.0 + }, + { + "time_epoch": 1682650800, + "time": "2023-04-28 04:00", + "temp_c": 11.6, + "temp_f": 52.9, + "is_day": 0, + "condition": { + "text": "Overcast", + "icon": "//cdn.weatherapi.com/weather/64x64/night/122.png", + "code": 1009 + }, + "wind_mph": 8.3, + "wind_kph": 13.3, + "wind_degree": 230, + "wind_dir": "SW", + "pressure_mb": 1008.0, + "pressure_in": 29.76, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 99, + "cloud": 96, + "feelslike_c": 10.1, + "feelslike_f": 50.2, + "windchill_c": 10.1, + "windchill_f": 50.2, + "heatindex_c": 11.6, + "heatindex_f": 52.9, + "dewpoint_c": 11.4, + "dewpoint_f": 52.5, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 13.0, + "gust_kph": 20.9, + "uv": 1.0 + }, + { + "time_epoch": 1682654400, + "time": "2023-04-28 05:00", + "temp_c": 11.7, + "temp_f": 53.1, + "is_day": 0, + "condition": { + "text": "Overcast", + "icon": "//cdn.weatherapi.com/weather/64x64/night/122.png", + "code": 1009 + }, + "wind_mph": 8.5, + "wind_kph": 13.7, + "wind_degree": 234, + "wind_dir": "SW", + "pressure_mb": 1008.0, + "pressure_in": 29.77, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 97, + "cloud": 100, + "feelslike_c": 10.2, + "feelslike_f": 50.4, + "windchill_c": 10.2, + "windchill_f": 50.4, + "heatindex_c": 11.7, + "heatindex_f": 53.1, + "dewpoint_c": 11.2, + "dewpoint_f": 52.2, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 13.2, + "gust_kph": 21.2, + "uv": 1.0 + }, + { + "time_epoch": 1682658000, + "time": "2023-04-28 06:00", + "temp_c": 11.6, + "temp_f": 52.9, + "is_day": 1, + "condition": { + "text": "Cloudy", + "icon": "//cdn.weatherapi.com/weather/64x64/day/119.png", + "code": 1006 + }, + "wind_mph": 8.7, + "wind_kph": 14.0, + "wind_degree": 231, + "wind_dir": "SW", + "pressure_mb": 1009.0, + "pressure_in": 29.78, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 96, + "cloud": 87, + "feelslike_c": 10.0, + "feelslike_f": 50.0, + "windchill_c": 10.0, + "windchill_f": 50.0, + "heatindex_c": 11.6, + "heatindex_f": 52.9, + "dewpoint_c": 10.9, + "dewpoint_f": 51.6, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 13.6, + "gust_kph": 22.0, + "uv": 3.0 + }, + { + "time_epoch": 1682661600, + "time": "2023-04-28 07:00", + "temp_c": 12.1, + "temp_f": 53.8, + "is_day": 1, + "condition": { + "text": "Cloudy", + "icon": "//cdn.weatherapi.com/weather/64x64/day/119.png", + "code": 1006 + }, + "wind_mph": 10.5, + "wind_kph": 16.9, + "wind_degree": 236, + "wind_dir": "WSW", + "pressure_mb": 1009.0, + "pressure_in": 29.8, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 94, + "cloud": 67, + "feelslike_c": 10.3, + "feelslike_f": 50.5, + "windchill_c": 10.3, + "windchill_f": 50.5, + "heatindex_c": 12.1, + "heatindex_f": 53.8, + "dewpoint_c": 11.2, + "dewpoint_f": 52.2, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 15.9, + "gust_kph": 25.6, + "uv": 3.0 + }, + { + "time_epoch": 1682665200, + "time": "2023-04-28 08:00", + "temp_c": 13.2, + "temp_f": 55.8, + "is_day": 1, + "condition": { + "text": "Overcast", + "icon": "//cdn.weatherapi.com/weather/64x64/day/122.png", + "code": 1009 + }, + "wind_mph": 12.1, + "wind_kph": 19.4, + "wind_degree": 246, + "wind_dir": "WSW", + "pressure_mb": 1010.0, + "pressure_in": 29.81, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 90, + "cloud": 99, + "feelslike_c": 11.5, + "feelslike_f": 52.7, + "windchill_c": 11.5, + "windchill_f": 52.7, + "heatindex_c": 13.2, + "heatindex_f": 55.8, + "dewpoint_c": 11.6, + "dewpoint_f": 52.9, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 15.7, + "gust_kph": 25.2, + "uv": 3.0 + }, + { + "time_epoch": 1682668800, + "time": "2023-04-28 09:00", + "temp_c": 12.7, + "temp_f": 54.9, + "is_day": 1, + "condition": { + "text": "Overcast", + "icon": "//cdn.weatherapi.com/weather/64x64/day/122.png", + "code": 1009 + }, + "wind_mph": 11.0, + "wind_kph": 17.6, + "wind_degree": 249, + "wind_dir": "WSW", + "pressure_mb": 1010.0, + "pressure_in": 29.83, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 88, + "cloud": 94, + "feelslike_c": 11.0, + "feelslike_f": 51.8, + "windchill_c": 11.0, + "windchill_f": 51.8, + "heatindex_c": 12.7, + "heatindex_f": 54.9, + "dewpoint_c": 10.8, + "dewpoint_f": 51.4, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 15.2, + "gust_kph": 24.5, + "uv": 3.0 + }, + { + "time_epoch": 1682672400, + "time": "2023-04-28 10:00", + "temp_c": 13.7, + "temp_f": 56.7, + "is_day": 1, + "condition": { + "text": "Cloudy", + "icon": "//cdn.weatherapi.com/weather/64x64/day/119.png", + "code": 1006 + }, + "wind_mph": 11.0, + "wind_kph": 17.6, + "wind_degree": 254, + "wind_dir": "WSW", + "pressure_mb": 1011.0, + "pressure_in": 29.84, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 84, + "cloud": 85, + "feelslike_c": 12.2, + "feelslike_f": 54.0, + "windchill_c": 12.2, + "windchill_f": 54.0, + "heatindex_c": 13.7, + "heatindex_f": 56.7, + "dewpoint_c": 11.1, + "dewpoint_f": 52.0, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 14.1, + "gust_kph": 22.7, + "uv": 3.0 + }, + { + "time_epoch": 1682676000, + "time": "2023-04-28 11:00", + "temp_c": 15.8, + "temp_f": 60.4, + "is_day": 1, + "condition": { + "text": "Cloudy", + "icon": "//cdn.weatherapi.com/weather/64x64/day/119.png", + "code": 1006 + }, + "wind_mph": 11.9, + "wind_kph": 19.1, + "wind_degree": 271, + "wind_dir": "W", + "pressure_mb": 1011.0, + "pressure_in": 29.85, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 73, + "cloud": 77, + "feelslike_c": 15.8, + "feelslike_f": 60.4, + "windchill_c": 15.8, + "windchill_f": 60.4, + "heatindex_c": 15.8, + "heatindex_f": 60.4, + "dewpoint_c": 10.9, + "dewpoint_f": 51.6, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 14.1, + "gust_kph": 22.7, + "uv": 4.0 + }, + { + "time_epoch": 1682679600, + "time": "2023-04-28 12:00", + "temp_c": 17.0, + "temp_f": 62.6, + "is_day": 1, + "condition": { + "text": "Patchy rain possible", + "icon": "//cdn.weatherapi.com/weather/64x64/day/176.png", + "code": 1063 + }, + "wind_mph": 13.9, + "wind_kph": 22.3, + "wind_degree": 277, + "wind_dir": "W", + "pressure_mb": 1011.0, + "pressure_in": 29.86, + "precip_mm": 0.1, + "precip_in": 0.0, + "humidity": 66, + "cloud": 67, + "feelslike_c": 17.0, + "feelslike_f": 62.6, + "windchill_c": 17.0, + "windchill_f": 62.6, + "heatindex_c": 17.0, + "heatindex_f": 62.6, + "dewpoint_c": 10.6, + "dewpoint_f": 51.1, + "will_it_rain": 1, + "chance_of_rain": 77, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 16.1, + "gust_kph": 25.9, + "uv": 4.0 + }, + { + "time_epoch": 1682683200, + "time": "2023-04-28 13:00", + "temp_c": 17.6, + "temp_f": 63.7, + "is_day": 1, + "condition": { + "text": "Cloudy", + "icon": "//cdn.weatherapi.com/weather/64x64/day/119.png", + "code": 1006 + }, + "wind_mph": 14.1, + "wind_kph": 22.7, + "wind_degree": 283, + "wind_dir": "WNW", + "pressure_mb": 1012.0, + "pressure_in": 29.88, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 60, + "cloud": 82, + "feelslike_c": 17.6, + "feelslike_f": 63.7, + "windchill_c": 17.6, + "windchill_f": 63.7, + "heatindex_c": 17.6, + "heatindex_f": 63.7, + "dewpoint_c": 9.7, + "dewpoint_f": 49.5, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 16.1, + "gust_kph": 25.9, + "uv": 4.0 + }, + { + "time_epoch": 1682686800, + "time": "2023-04-28 14:00", + "temp_c": 17.1, + "temp_f": 62.8, + "is_day": 1, + "condition": { + "text": "Partly cloudy", + "icon": "//cdn.weatherapi.com/weather/64x64/day/116.png", + "code": 1003 + }, + "wind_mph": 13.4, + "wind_kph": 21.6, + "wind_degree": 287, + "wind_dir": "WNW", + "pressure_mb": 1012.0, + "pressure_in": 29.89, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 61, + "cloud": 55, + "feelslike_c": 17.1, + "feelslike_f": 62.8, + "windchill_c": 17.1, + "windchill_f": 62.8, + "heatindex_c": 17.1, + "heatindex_f": 62.8, + "dewpoint_c": 9.6, + "dewpoint_f": 49.3, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 15.7, + "gust_kph": 25.2, + "uv": 5.0 + }, + { + "time_epoch": 1682690400, + "time": "2023-04-28 15:00", + "temp_c": 17.4, + "temp_f": 63.3, + "is_day": 1, + "condition": { + "text": "Patchy rain possible", + "icon": "//cdn.weatherapi.com/weather/64x64/day/176.png", + "code": 1063 + }, + "wind_mph": 13.6, + "wind_kph": 22.0, + "wind_degree": 299, + "wind_dir": "WNW", + "pressure_mb": 1013.0, + "pressure_in": 29.91, + "precip_mm": 0.1, + "precip_in": 0.0, + "humidity": 59, + "cloud": 83, + "feelslike_c": 17.4, + "feelslike_f": 63.3, + "windchill_c": 17.4, + "windchill_f": 63.3, + "heatindex_c": 17.4, + "heatindex_f": 63.3, + "dewpoint_c": 9.4, + "dewpoint_f": 48.9, + "will_it_rain": 0, + "chance_of_rain": 64, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 15.7, + "gust_kph": 25.2, + "uv": 4.0 + }, + { + "time_epoch": 1682694000, + "time": "2023-04-28 16:00", + "temp_c": 17.2, + "temp_f": 63.0, + "is_day": 1, + "condition": { + "text": "Partly cloudy", + "icon": "//cdn.weatherapi.com/weather/64x64/day/116.png", + "code": 1003 + }, + "wind_mph": 12.5, + "wind_kph": 20.2, + "wind_degree": 304, + "wind_dir": "NW", + "pressure_mb": 1013.0, + "pressure_in": 29.93, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 61, + "cloud": 46, + "feelslike_c": 17.2, + "feelslike_f": 63.0, + "windchill_c": 17.2, + "windchill_f": 63.0, + "heatindex_c": 17.2, + "heatindex_f": 63.0, + "dewpoint_c": 9.6, + "dewpoint_f": 49.3, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 14.3, + "gust_kph": 23.0, + "uv": 5.0 + }, + { + "time_epoch": 1682697600, + "time": "2023-04-28 17:00", + "temp_c": 17.1, + "temp_f": 62.8, + "is_day": 1, + "condition": { + "text": "Partly cloudy", + "icon": "//cdn.weatherapi.com/weather/64x64/day/116.png", + "code": 1003 + }, + "wind_mph": 10.5, + "wind_kph": 16.9, + "wind_degree": 311, + "wind_dir": "NW", + "pressure_mb": 1014.0, + "pressure_in": 29.94, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 64, + "cloud": 29, + "feelslike_c": 17.1, + "feelslike_f": 62.8, + "windchill_c": 17.1, + "windchill_f": 62.8, + "heatindex_c": 17.1, + "heatindex_f": 62.8, + "dewpoint_c": 10.2, + "dewpoint_f": 50.4, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 12.1, + "gust_kph": 19.4, + "uv": 5.0 + }, + { + "time_epoch": 1682701200, + "time": "2023-04-28 18:00", + "temp_c": 17.2, + "temp_f": 63.0, + "is_day": 1, + "condition": { + "text": "Patchy rain possible", + "icon": "//cdn.weatherapi.com/weather/64x64/day/176.png", + "code": 1063 + }, + "wind_mph": 7.6, + "wind_kph": 12.2, + "wind_degree": 327, + "wind_dir": "NNW", + "pressure_mb": 1015.0, + "pressure_in": 29.97, + "precip_mm": 0.1, + "precip_in": 0.0, + "humidity": 69, + "cloud": 86, + "feelslike_c": 17.2, + "feelslike_f": 63.0, + "windchill_c": 17.2, + "windchill_f": 63.0, + "heatindex_c": 17.2, + "heatindex_f": 63.0, + "dewpoint_c": 11.5, + "dewpoint_f": 52.7, + "will_it_rain": 1, + "chance_of_rain": 89, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 8.7, + "gust_kph": 14.0, + "uv": 4.0 + }, + { + "time_epoch": 1682704800, + "time": "2023-04-28 19:00", + "temp_c": 14.8, + "temp_f": 58.6, + "is_day": 1, + "condition": { + "text": "Sunny", + "icon": "//cdn.weatherapi.com/weather/64x64/day/113.png", + "code": 1000 + }, + "wind_mph": 5.8, + "wind_kph": 9.4, + "wind_degree": 348, + "wind_dir": "NNW", + "pressure_mb": 1016.0, + "pressure_in": 29.99, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 77, + "cloud": 24, + "feelslike_c": 14.4, + "feelslike_f": 57.9, + "windchill_c": 14.4, + "windchill_f": 57.9, + "heatindex_c": 14.8, + "heatindex_f": 58.6, + "dewpoint_c": 10.7, + "dewpoint_f": 51.3, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 7.4, + "gust_kph": 11.9, + "uv": 4.0 + }, + { + "time_epoch": 1682708400, + "time": "2023-04-28 20:00", + "temp_c": 12.4, + "temp_f": 54.3, + "is_day": 1, + "condition": { + "text": "Partly cloudy", + "icon": "//cdn.weatherapi.com/weather/64x64/day/116.png", + "code": 1003 + }, + "wind_mph": 4.3, + "wind_kph": 6.8, + "wind_degree": 359, + "wind_dir": "N", + "pressure_mb": 1017.0, + "pressure_in": 30.02, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 81, + "cloud": 33, + "feelslike_c": 12.1, + "feelslike_f": 53.8, + "windchill_c": 12.1, + "windchill_f": 53.8, + "heatindex_c": 12.4, + "heatindex_f": 54.3, + "dewpoint_c": 9.3, + "dewpoint_f": 48.7, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 6.9, + "gust_kph": 11.2, + "uv": 4.0 + }, + { + "time_epoch": 1682712000, + "time": "2023-04-28 21:00", + "temp_c": 11.7, + "temp_f": 53.1, + "is_day": 0, + "condition": { + "text": "Clear", + "icon": "//cdn.weatherapi.com/weather/64x64/night/113.png", + "code": 1000 + }, + "wind_mph": 3.1, + "wind_kph": 5.0, + "wind_degree": 11, + "wind_dir": "NNE", + "pressure_mb": 1017.0, + "pressure_in": 30.03, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 84, + "cloud": 24, + "feelslike_c": 11.7, + "feelslike_f": 53.1, + "windchill_c": 11.7, + "windchill_f": 53.1, + "heatindex_c": 11.7, + "heatindex_f": 53.1, + "dewpoint_c": 9.1, + "dewpoint_f": 48.4, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 4.9, + "gust_kph": 7.9, + "uv": 1.0 + }, + { + "time_epoch": 1682715600, + "time": "2023-04-28 22:00", + "temp_c": 11.2, + "temp_f": 52.2, + "is_day": 0, + "condition": { + "text": "Partly cloudy", + "icon": "//cdn.weatherapi.com/weather/64x64/night/116.png", + "code": 1003 + }, + "wind_mph": 1.8, + "wind_kph": 2.9, + "wind_degree": 35, + "wind_dir": "NE", + "pressure_mb": 1017.0, + "pressure_in": 30.04, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 86, + "cloud": 42, + "feelslike_c": 11.2, + "feelslike_f": 52.2, + "windchill_c": 11.2, + "windchill_f": 52.2, + "heatindex_c": 11.2, + "heatindex_f": 52.2, + "dewpoint_c": 9.0, + "dewpoint_f": 48.2, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 2.9, + "gust_kph": 4.7, + "uv": 1.0 + }, + { + "time_epoch": 1682719200, + "time": "2023-04-28 23:00", + "temp_c": 10.7, + "temp_f": 51.3, + "is_day": 0, + "condition": { + "text": "Partly cloudy", + "icon": "//cdn.weatherapi.com/weather/64x64/night/116.png", + "code": 1003 + }, + "wind_mph": 1.8, + "wind_kph": 2.9, + "wind_degree": 35, + "wind_dir": "NE", + "pressure_mb": 1018.0, + "pressure_in": 30.05, + "precip_mm": 0.0, + "precip_in": 0.0, + "humidity": 88, + "cloud": 53, + "feelslike_c": 10.7, + "feelslike_f": 51.3, + "windchill_c": 10.7, + "windchill_f": 51.3, + "heatindex_c": 10.7, + "heatindex_f": 51.3, + "dewpoint_c": 8.7, + "dewpoint_f": 47.7, + "will_it_rain": 0, + "chance_of_rain": 0, + "will_it_snow": 0, + "chance_of_snow": 0, + "vis_km": 10.0, + "vis_miles": 6.0, + "gust_mph": 2.9, + "gust_kph": 4.7, + "uv": 1.0 + } + ] + } + ] + } +} diff --git a/custom_components/weatherapi/coordinator.py b/custom_components/weatherapi/coordinator.py index 6478d76..c731410 100755 --- a/custom_components/weatherapi/coordinator.py +++ b/custom_components/weatherapi/coordinator.py @@ -37,7 +37,6 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.update_coordinator import DataUpdateCoordinator import homeassistant.util.dt as dt_util -from homeassistant.util.unit_system import METRIC_SYSTEM import pytz import requests @@ -203,11 +202,6 @@ def __init__( update_interval=config.update_interval, ) - @property - def is_metric(self): - """Determine if this is the metric unit system.""" - return self._hass.config.units is METRIC_SYSTEM - @property def location(self): """Return the location used for data.""" @@ -299,8 +293,6 @@ def parse_forecast(self, json): _LOGGER.warning("No day forecast found in data.") return entries - is_metric = self.is_metric - for forecastday in forecastday_array: # `date` is in YYYY-MM-DD format # `date_epoch` is unix time @@ -333,21 +325,15 @@ def parse_forecast(self, json): condition_code = condition.get("code") day_entry = Forecast( + condition=parse_condition_code(condition_code, is_day), datetime=datetime_to_iso(forecastday.get("date")), - temperature=to_float( - day.get("maxtemp_c" if is_metric else "maxtemp_f") - ), - templow=to_float( - day.get("mintemp_c" if is_metric else "mintemp_f") - ), - precipitation=to_float( - day.get("totalprecip_mm" if is_metric else "totalprecip_in") - ), precipitation_probability=day.get("daily_chance_of_rain"), - wind_speed=to_float( - day.get("maxwind_kph" if is_metric else "maxwind_mph") - ), - condition=parse_condition_code(condition_code, is_day), + native_precipitation=to_float(day.get("totalprecip_mm")), + # There is no pressure element + native_temperature=to_float(day.get("maxtemp_c")), + native_templow=to_float(day.get("mintemp_c")), + # There is no wind_dir + naive_wind_speed=to_float(day.get("maxwind_kph")), ) day_entry[ATTR_REPORTED_CONDITION] = condition_code @@ -383,11 +369,14 @@ def parse_hour_forecast(self, data: any) -> Forecast: condition_code = condition.get("code") value = Forecast( + condition=parse_condition_code(condition_code, is_day), datetime=hour_forecast_time, - temperature=to_float(data.get("temp_c" if self.is_metric else "temp_f")), precipitation_probability=data.get("chance_of_rain"), - wind_speed=to_float(data.get("wind_mph" if self.is_metric else "wind_kph")), - condition=parse_condition_code(condition_code, is_day), + native_precipitation=to_float(data.get("precip_mm")), + native_pressure=to_float(data.get("pressure_mb")), + native_temperature=to_float(data.get("temp_c")), + wind_bearing=data.get("wind_dir"), + native_wind_speed=to_float(data.get("wind_kph")), ) value[ATTR_REPORTED_CONDITION] = condition_code return value @@ -400,7 +389,6 @@ def parse_current(self, json): _LOGGER.debug(json) - is_metric = self.is_metric condition = json.get("condition", {}) air_quality = json.get("air_quality", {}) is_day = to_int(json.get("is_day", "1")) == 1 @@ -408,19 +396,11 @@ def parse_current(self, json): return { ATTR_WEATHER_HUMIDITY: to_float(json.get("humidity")), - ATTR_WEATHER_TEMPERATURE: to_float( - json.get(("temp_c" if is_metric else "temp_f")) - ), - ATTR_WEATHER_PRESSURE: to_float( - json.get(("pressure_mb" if is_metric else "pressure_in")) - ), - ATTR_WEATHER_WIND_SPEED: to_float( - json.get(("wind_kph" if is_metric else "wind_mph")) - ), + ATTR_WEATHER_TEMPERATURE: to_float(json.get("temp_c")), + ATTR_WEATHER_PRESSURE: to_float(json.get("pressure_mb")), + ATTR_WEATHER_WIND_SPEED: to_float(json.get("wind_kph")), ATTR_WEATHER_WIND_BEARING: json.get("wind_degree"), - ATTR_WEATHER_VISIBILITY: to_float( - json.get("vis_km" if is_metric else "vis_miles") - ), + ATTR_WEATHER_VISIBILITY: to_float(json.get("vis_km")), ATTR_UV: to_float(json.get("uv")), ATTR_REPORTED_CONDITION: condition_code, ATTR_WEATHER_CONDITION: parse_condition_code(condition_code, is_day), diff --git a/custom_components/weatherapi/manifest.json b/custom_components/weatherapi/manifest.json index e9ec1fb..218ffc3 100755 --- a/custom_components/weatherapi/manifest.json +++ b/custom_components/weatherapi/manifest.json @@ -6,7 +6,7 @@ "dependencies": [], "codeowners": ["@iprak"], "issue_tracker": "https://github.com/iprak/weatherapi/issues", - "version": "1.0.1", + "version": "1.1.0", "config_flow": true, "iot_class": "cloud_polling" } diff --git a/custom_components/weatherapi/weather.py b/custom_components/weatherapi/weather.py index 1eb4318..aeece39 100755 --- a/custom_components/weatherapi/weather.py +++ b/custom_components/weatherapi/weather.py @@ -19,15 +19,11 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( CONF_NAME, - LENGTH_KILOMETERS, - LENGTH_MILES, PRECISION_TENTHS, - PRESSURE_PA, - PRESSURE_PSI, - SPEED_KILOMETERS_PER_HOUR, - SPEED_MILES_PER_HOUR, - TEMP_CELSIUS, - TEMP_FAHRENHEIT, + UnitOfPrecipitationDepth, + UnitOfPressure, + UnitOfSpeed, + UnitOfTemperature, ) from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import generate_entity_id @@ -59,6 +55,13 @@ async def async_setup_entry( class WeatherAPIEntity(CoordinatorEntity, WeatherEntity): """Define a WeatherAPI entity.""" + _attr_attribution = ATTRIBUTION + _attr_native_precipitation_unit = UnitOfPrecipitationDepth.MILLIMETERS + _attr_native_pressure_unit = UnitOfPressure.MBAR + _attr_native_temperature_unit = UnitOfTemperature.CELSIUS + _attr_native_wind_speed_unit = UnitOfSpeed.KILOMETERS_PER_HOUR + _attr_precision = PRECISION_TENTHS + def __init__(self, location_name: str, coordinator: WeatherAPIUpdateCoordinator): """Initialize.""" super().__init__(coordinator) @@ -68,26 +71,6 @@ def __init__(self, location_name: str, coordinator: WeatherAPIUpdateCoordinator) ENTITY_ID_FORMAT, f"{DOMAIN}_{self._name}", hass=coordinator.hass ) self._unique_id = f"{self.coordinator.location}_{self._name}" - self._attr_attribution = ATTRIBUTION - - self._attr_precision = PRECISION_TENTHS - - """ - The weatherAPI documentation defines pressure data pieces as pressure_mb - (Pressure in millibars) and pressure_in (Pressure in inches). But values - received turn out to be in Pa and Psi. - """ - - if coordinator.is_metric: - self._attr_native_pressure_unit = PRESSURE_PA - self._attr_native_temperature_unit = TEMP_CELSIUS - self._attr_native_wind_speed_unit = SPEED_KILOMETERS_PER_HOUR - self._attr_native_visibility_unit = LENGTH_KILOMETERS - else: - self._attr_native_pressure_unit = PRESSURE_PSI - self._attr_native_temperature_unit = TEMP_FAHRENHEIT - self._attr_native_wind_speed_unit = SPEED_MILES_PER_HOUR - self._attr_native_visibility_unit = LENGTH_MILES @property def available(self) -> bool: diff --git a/tests/test_coordinator.py b/tests/test_coordinator.py index d113f78..eb0db0a 100755 --- a/tests/test_coordinator.py +++ b/tests/test_coordinator.py @@ -2,14 +2,13 @@ import asyncio from http import HTTPStatus -from unittest.mock import AsyncMock, Mock, PropertyMock, call, patch +from unittest.mock import AsyncMock, Mock, call, patch from homeassistant.components.weather import ( ATTR_CONDITION_CLEAR_NIGHT, ATTR_CONDITION_SUNNY, Forecast, ) -from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM import pytest from custom_components.weatherapi import coordinator @@ -115,23 +114,6 @@ async def test_is_valid_api_key_raises_cannotconnect(hass): await coordinator.is_valid_api_key(hass, "api_key") -@pytest.mark.parametrize( - "is_metric", - [ - (True), - (False), - ], -) -async def test_constructor(is_metric, coordinator_config): - """Test coordinator.""" - hass = Mock() - hass.config.units = METRIC_SYSTEM if is_metric else IMPERIAL_SYSTEM - - coord = coordinator.WeatherAPIUpdateCoordinator(hass, coordinator_config) - assert coord.is_metric == is_metric - assert coord.location == "latitude,longitude" - - async def test_async_update_data_http_error(hass, mock_json, coordinator_config): """Test failed coordinator data update.""" session = Mock() @@ -339,55 +321,31 @@ async def test_get_weather_no_forecastday_data(hass, coordinator_config): @pytest.mark.parametrize( - "is_metric, zone, data, expected", + "zone, data, expected", [ - (True, "UTC", None, None), - (True, "UTC", {}, None), + ("UTC", None, None), + ("UTC", {}, None), ( - True, "UTC", sample_data_for_parse_hour_forecast, Forecast( datetime="2021-11-24T09:00:00+00:00", - temperature=4.9, precipitation_probability=0.2, - wind_speed=19.0, - condition=ATTR_CONDITION_CLEAR_NIGHT, - ), - ), - ( - True, - "US/Eastern", - sample_data_for_parse_hour_forecast, - Forecast( - datetime="2021-11-24T04:00:00-05:00", - temperature=4.9, - precipitation_probability=0.2, - wind_speed=19.0, - condition=ATTR_CONDITION_CLEAR_NIGHT, - ), - ), - ( - False, - "UTC", - sample_data_for_parse_hour_forecast, - Forecast( - datetime="2021-11-24T09:00:00+00:00", - temperature=40.8, - precipitation_probability=0.2, - wind_speed=30.6, + native_precipitation=0.0, + native_pressure=1016.0, + native_temperature=4.9, + wind_bearing="SSW", + native_wind_speed=30.6, condition=ATTR_CONDITION_CLEAR_NIGHT, + reported_condition=1000, ), ), ], ) -def test_parse_hour_forecast(hass, coordinator_config, is_metric, zone, data, expected): +def test_parse_hour_forecast(hass, coordinator_config, zone, data, expected): """Test parse_hour_forecast function.""" coord = coordinator.WeatherAPIUpdateCoordinator(hass, coordinator_config) coord.populate_time_zone(zone) - is_metric_mock = PropertyMock(return_value=is_metric) - coordinator.WeatherAPIUpdateCoordinator.is_metric = is_metric_mock - assert coord.parse_hour_forecast(data) == expected