Improve tests for AccuWeather integration (#38621)

* Add more tests

* Add tests for sensor platform

* Add more tests

* More tests

* Simplify parsing of attributes

* Change Quality scale to platinum

* Patch the library in the manual update entity test

* Add unsupported condition icon test

* Do not patch _async_get_data

* Apply suggestions from code review

* Update config_flow.py

* Apply suggestions from code review

* Apply suggestions from code review

* Apply suggestions from code review

* Update tests/components/accuweather/test_weather.py

* Apply suggestions from code review

* Add return_value

Co-authored-by: Chris Talkington <chris@talkingtontech.com>
This commit is contained in:
Maciej Bieniek 2020-08-09 16:21:36 +02:00 committed by GitHub
parent ca3842b150
commit a7e19c8896
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 1844 additions and 11 deletions

View file

@ -8,10 +8,6 @@ omit =
homeassistant/scripts/*.py
# omit pieces of code that rely on external devices being present
homeassistant/components/accuweather/__init__.py
homeassistant/components/accuweather/const.py
homeassistant/components/accuweather/sensor.py
homeassistant/components/accuweather/weather.py
homeassistant/components/acer_projector/switch.py
homeassistant/components/actiontec/device_tracker.py
homeassistant/components/acmeda/__init__.py

View file

@ -34,7 +34,7 @@ class AccuWeatherFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
if user_input is not None:
websession = async_get_clientsession(self.hass)
try:
with timeout(10):
async with timeout(10):
accuweather = AccuWeather(
user_input[CONF_API_KEY],
websession,

View file

@ -4,5 +4,6 @@
"documentation": "https://www.home-assistant.io/integrations/accuweather/",
"requirements": ["accuweather==0.0.9"],
"codeowners": ["@bieniu"],
"config_flow": true
"config_flow": true,
"quality_scale": "platinum"
}

View file

@ -154,11 +154,7 @@ class AccuWeatherSensor(Entity):
def device_state_attributes(self):
"""Return the state attributes."""
if self.forecast_day is not None:
if self.kind == "WindGustDay":
self._attrs["direction"] = self.coordinator.data[ATTR_FORECAST][
self.forecast_day
][self.kind]["Direction"]["English"]
elif self.kind == "WindGustNight":
if self.kind in ["WindGustDay", "WindGustNight"]:
self._attrs["direction"] = self.coordinator.data[ATTR_FORECAST][
self.forecast_day
][self.kind]["Direction"]["English"]

View file

@ -1 +1,48 @@
"""Tests for AccuWeather."""
import json
from homeassistant.components.accuweather.const import DOMAIN
from tests.async_mock import patch
from tests.common import MockConfigEntry, load_fixture
async def init_integration(
hass, forecast=False, unsupported_icon=False
) -> MockConfigEntry:
"""Set up the AccuWeather integration in Home Assistant."""
options = {}
if forecast:
options["forecast"] = True
entry = MockConfigEntry(
domain=DOMAIN,
title="Home",
unique_id="0123456",
data={
"api_key": "32-character-string-1234567890qw",
"latitude": 55.55,
"longitude": 122.12,
"name": "Home",
},
options=options,
)
current = json.loads(load_fixture("accuweather/current_conditions_data.json"))
forecast = json.loads(load_fixture("accuweather/forecast_data.json"))
if unsupported_icon:
current["WeatherIcon"] = 999
with patch(
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
return_value=current,
), patch(
"homeassistant.components.accuweather.AccuWeather.async_get_forecast",
return_value=forecast,
):
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
return entry

View file

@ -0,0 +1,59 @@
"""Test init of AccuWeather integration."""
from homeassistant.components.accuweather.const import DOMAIN
from homeassistant.config_entries import (
ENTRY_STATE_LOADED,
ENTRY_STATE_NOT_LOADED,
ENTRY_STATE_SETUP_RETRY,
)
from homeassistant.const import STATE_UNAVAILABLE
from tests.async_mock import patch
from tests.common import MockConfigEntry
from tests.components.accuweather import init_integration
async def test_async_setup_entry(hass):
"""Test a successful setup entry."""
await init_integration(hass)
state = hass.states.get("weather.home")
assert state is not None
assert state.state != STATE_UNAVAILABLE
assert state.state == "sunny"
async def test_config_not_ready(hass):
"""Test for setup failure if connection to AccuWeather is missing."""
entry = MockConfigEntry(
domain=DOMAIN,
title="Home",
unique_id="0123456",
data={
"api_key": "32-character-string-1234567890qw",
"latitude": 55.55,
"longitude": 122.12,
"name": "Home",
},
)
with patch(
"homeassistant.components.accuweather.AccuWeather._async_get_data",
side_effect=ConnectionError(),
):
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state == ENTRY_STATE_SETUP_RETRY
async def test_unload_entry(hass):
"""Test successful unload of entry."""
entry = await init_integration(hass)
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
assert entry.state == ENTRY_STATE_LOADED
assert await hass.config_entries.async_unload(entry.entry_id)
await hass.async_block_till_done()
assert entry.state == ENTRY_STATE_NOT_LOADED
assert not hass.data.get(DOMAIN)

View file

@ -0,0 +1,598 @@
"""Test sensor of AccuWeather integration."""
from datetime import timedelta
import json
from homeassistant.components.accuweather.const import (
ATTRIBUTION,
CONCENTRATION_PARTS_PER_CUBIC_METER,
DOMAIN,
LENGTH_MILIMETERS,
)
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.const import (
ATTR_ATTRIBUTION,
ATTR_DEVICE_CLASS,
ATTR_ENTITY_ID,
ATTR_ICON,
ATTR_UNIT_OF_MEASUREMENT,
DEVICE_CLASS_TEMPERATURE,
LENGTH_METERS,
SPEED_KILOMETERS_PER_HOUR,
STATE_UNAVAILABLE,
TEMP_CELSIUS,
TIME_HOURS,
UNIT_PERCENTAGE,
UV_INDEX,
)
from homeassistant.setup import async_setup_component
from homeassistant.util.dt import utcnow
from tests.async_mock import patch
from tests.common import async_fire_time_changed, load_fixture
from tests.components.accuweather import init_integration
async def test_sensor_without_forecast(hass):
"""Test states of the sensor without forecast."""
await init_integration(hass)
registry = await hass.helpers.entity_registry.async_get_registry()
state = hass.states.get("sensor.home_cloud_ceiling")
assert state
assert state.state == "3200"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_ICON) == "mdi:weather-fog"
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == LENGTH_METERS
entry = registry.async_get("sensor.home_cloud_ceiling")
assert entry
assert entry.unique_id == "0123456-ceiling"
state = hass.states.get("sensor.home_precipitation")
assert state
assert state.state == "0.0"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == LENGTH_MILIMETERS
assert state.attributes.get(ATTR_ICON) == "mdi:weather-rainy"
assert state.attributes.get("type") is None
entry = registry.async_get("sensor.home_precipitation")
assert entry
assert entry.unique_id == "0123456-precipitation"
state = hass.states.get("sensor.home_pressure_tendency")
assert state
assert state.state == "falling"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_ICON) == "mdi:gauge"
assert state.attributes.get(ATTR_DEVICE_CLASS) == "accuweather__pressure_tendency"
entry = registry.async_get("sensor.home_pressure_tendency")
assert entry
assert entry.unique_id == "0123456-pressuretendency"
state = hass.states.get("sensor.home_realfeel_temperature")
assert state
assert state.state == "25.1"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TEMPERATURE
entry = registry.async_get("sensor.home_realfeel_temperature")
assert entry
assert entry.unique_id == "0123456-realfeeltemperature"
state = hass.states.get("sensor.home_uv_index")
assert state
assert state.state == "6"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UV_INDEX
assert state.attributes.get("level") == "High"
entry = registry.async_get("sensor.home_uv_index")
assert entry
assert entry.unique_id == "0123456-uvindex"
async def test_sensor_with_forecast(hass):
"""Test states of the sensor with forecast."""
await init_integration(hass, forecast=True)
registry = await hass.helpers.entity_registry.async_get_registry()
state = hass.states.get("sensor.home_hours_of_sun_0d")
assert state
assert state.state == "7.2"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_ICON) == "mdi:weather-partly-cloudy"
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TIME_HOURS
entry = registry.async_get("sensor.home_hours_of_sun_0d")
assert entry
assert entry.unique_id == "0123456-hoursofsun-0"
state = hass.states.get("sensor.home_realfeel_temperature_max_0d")
assert state
assert state.state == "29.8"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TEMPERATURE
entry = registry.async_get("sensor.home_realfeel_temperature_max_0d")
assert entry
state = hass.states.get("sensor.home_realfeel_temperature_min_0d")
assert state
assert state.state == "15.1"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TEMPERATURE
entry = registry.async_get("sensor.home_realfeel_temperature_min_0d")
assert entry
assert entry.unique_id == "0123456-realfeeltemperaturemin-0"
state = hass.states.get("sensor.home_thunderstorm_probability_day_0d")
assert state
assert state.state == "40"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_ICON) == "mdi:weather-lightning"
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UNIT_PERCENTAGE
entry = registry.async_get("sensor.home_thunderstorm_probability_day_0d")
assert entry
assert entry.unique_id == "0123456-thunderstormprobabilityday-0"
state = hass.states.get("sensor.home_thunderstorm_probability_night_0d")
assert state
assert state.state == "40"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_ICON) == "mdi:weather-lightning"
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UNIT_PERCENTAGE
entry = registry.async_get("sensor.home_thunderstorm_probability_night_0d")
assert entry
assert entry.unique_id == "0123456-thunderstormprobabilitynight-0"
state = hass.states.get("sensor.home_uv_index_0d")
assert state
assert state.state == "5"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_ICON) == "mdi:weather-sunny"
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UV_INDEX
assert state.attributes.get("level") == "Moderate"
entry = registry.async_get("sensor.home_uv_index_0d")
assert entry
assert entry.unique_id == "0123456-uvindex-0"
async def test_sensor_disabled(hass):
"""Test sensor disabled by default."""
await init_integration(hass)
registry = await hass.helpers.entity_registry.async_get_registry()
entry = registry.async_get("sensor.home_apparent_temperature")
assert entry
assert entry.unique_id == "0123456-apparenttemperature"
assert entry.disabled
assert entry.disabled_by == "integration"
# Test enabling entity
updated_entry = registry.async_update_entity(
entry.entity_id, **{"disabled_by": None}
)
assert updated_entry != entry
assert updated_entry.disabled is False
async def test_sensor_enabled_without_forecast(hass):
"""Test enabling an advanced sensor."""
registry = await hass.helpers.entity_registry.async_get_registry()
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-apparenttemperature",
suggested_object_id="home_apparent_temperature",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-cloudcover",
suggested_object_id="home_cloud_cover",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-dewpoint",
suggested_object_id="home_dew_point",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-realfeeltemperatureshade",
suggested_object_id="home_realfeel_temperature_shade",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-wetbulbtemperature",
suggested_object_id="home_wet_bulb_temperature",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-windchilltemperature",
suggested_object_id="home_wind_chill_temperature",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-windgust",
suggested_object_id="home_wind_gust",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-cloudcoverday-0",
suggested_object_id="home_cloud_cover_day_0d",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-cloudcovernight-0",
suggested_object_id="home_cloud_cover_night_0d",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-grass-0",
suggested_object_id="home_grass_pollen_0d",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-mold-0",
suggested_object_id="home_mold_pollen_0d",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-ozone-0",
suggested_object_id="home_ozone_0d",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-ragweed-0",
suggested_object_id="home_ragweed_pollen_0d",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-realfeeltemperatureshademax-0",
suggested_object_id="home_realfeel_temperature_shade_max_0d",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-realfeeltemperatureshademin-0",
suggested_object_id="home_realfeel_temperature_shade_min_0d",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-tree-0",
suggested_object_id="home_tree_pollen_0d",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-windgustday-0",
suggested_object_id="home_wind_gust_day_0d",
disabled_by=None,
)
registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"0123456-windgustnight-0",
suggested_object_id="home_wind_gust_night_0d",
disabled_by=None,
)
await init_integration(hass, forecast=True)
state = hass.states.get("sensor.home_apparent_temperature")
assert state
assert state.state == "22.8"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TEMPERATURE
entry = registry.async_get("sensor.home_apparent_temperature")
assert entry
assert entry.unique_id == "0123456-apparenttemperature"
state = hass.states.get("sensor.home_cloud_cover")
assert state
assert state.state == "10"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UNIT_PERCENTAGE
assert state.attributes.get(ATTR_ICON) == "mdi:weather-cloudy"
entry = registry.async_get("sensor.home_cloud_cover")
assert entry
assert entry.unique_id == "0123456-cloudcover"
state = hass.states.get("sensor.home_dew_point")
assert state
assert state.state == "16.2"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TEMPERATURE
entry = registry.async_get("sensor.home_dew_point")
assert entry
assert entry.unique_id == "0123456-dewpoint"
state = hass.states.get("sensor.home_realfeel_temperature_shade")
assert state
assert state.state == "21.1"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TEMPERATURE
entry = registry.async_get("sensor.home_realfeel_temperature_shade")
assert entry
assert entry.unique_id == "0123456-realfeeltemperatureshade"
state = hass.states.get("sensor.home_wet_bulb_temperature")
assert state
assert state.state == "18.6"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TEMPERATURE
entry = registry.async_get("sensor.home_wet_bulb_temperature")
assert entry
assert entry.unique_id == "0123456-wetbulbtemperature"
state = hass.states.get("sensor.home_wind_chill_temperature")
assert state
assert state.state == "22.8"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TEMPERATURE
entry = registry.async_get("sensor.home_wind_chill_temperature")
assert entry
assert entry.unique_id == "0123456-windchilltemperature"
state = hass.states.get("sensor.home_wind_gust")
assert state
assert state.state == "20.3"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == SPEED_KILOMETERS_PER_HOUR
assert state.attributes.get(ATTR_ICON) == "mdi:weather-windy"
entry = registry.async_get("sensor.home_wind_gust")
assert entry
assert entry.unique_id == "0123456-windgust"
state = hass.states.get("sensor.home_cloud_cover_day_0d")
assert state
assert state.state == "58"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UNIT_PERCENTAGE
assert state.attributes.get(ATTR_ICON) == "mdi:weather-cloudy"
entry = registry.async_get("sensor.home_cloud_cover_day_0d")
assert entry
assert entry.unique_id == "0123456-cloudcoverday-0"
state = hass.states.get("sensor.home_cloud_cover_night_0d")
assert state
assert state.state == "65"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UNIT_PERCENTAGE
assert state.attributes.get(ATTR_ICON) == "mdi:weather-cloudy"
entry = registry.async_get("sensor.home_cloud_cover_night_0d")
assert entry
state = hass.states.get("sensor.home_grass_pollen_0d")
assert state
assert state.state == "0"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert (
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== CONCENTRATION_PARTS_PER_CUBIC_METER
)
assert state.attributes.get("level") == "Low"
assert state.attributes.get(ATTR_ICON) == "mdi:grass"
entry = registry.async_get("sensor.home_grass_pollen_0d")
assert entry
assert entry.unique_id == "0123456-grass-0"
state = hass.states.get("sensor.home_mold_pollen_0d")
assert state
assert state.state == "0"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert (
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== CONCENTRATION_PARTS_PER_CUBIC_METER
)
assert state.attributes.get("level") == "Low"
assert state.attributes.get(ATTR_ICON) == "mdi:blur"
entry = registry.async_get("sensor.home_mold_pollen_0d")
assert entry
assert entry.unique_id == "0123456-mold-0"
state = hass.states.get("sensor.home_ozone_0d")
assert state
assert state.state == "32"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get("level") == "Good"
assert state.attributes.get(ATTR_ICON) == "mdi:vector-triangle"
entry = registry.async_get("sensor.home_ozone_0d")
assert entry
assert entry.unique_id == "0123456-ozone-0"
state = hass.states.get("sensor.home_ragweed_pollen_0d")
assert state
assert state.state == "0"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert (
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== CONCENTRATION_PARTS_PER_CUBIC_METER
)
assert state.attributes.get("level") == "Low"
assert state.attributes.get(ATTR_ICON) == "mdi:sprout"
entry = registry.async_get("sensor.home_ragweed_pollen_0d")
assert entry
assert entry.unique_id == "0123456-ragweed-0"
state = hass.states.get("sensor.home_realfeel_temperature_shade_max_0d")
assert state
assert state.state == "28.0"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TEMPERATURE
entry = registry.async_get("sensor.home_realfeel_temperature_shade_max_0d")
assert entry
assert entry.unique_id == "0123456-realfeeltemperatureshademax-0"
state = hass.states.get("sensor.home_realfeel_temperature_shade_min_0d")
assert state
assert state.state == "15.1"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_CELSIUS
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TEMPERATURE
entry = registry.async_get("sensor.home_realfeel_temperature_shade_min_0d")
assert entry
assert entry.unique_id == "0123456-realfeeltemperatureshademin-0"
state = hass.states.get("sensor.home_tree_pollen_0d")
assert state
assert state.state == "0"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert (
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== CONCENTRATION_PARTS_PER_CUBIC_METER
)
assert state.attributes.get("level") == "Low"
assert state.attributes.get(ATTR_ICON) == "mdi:tree-outline"
entry = registry.async_get("sensor.home_tree_pollen_0d")
assert entry
assert entry.unique_id == "0123456-tree-0"
state = hass.states.get("sensor.home_wind_gust_day_0d")
assert state
assert state.state == "29.6"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == SPEED_KILOMETERS_PER_HOUR
assert state.attributes.get("direction") == "S"
assert state.attributes.get(ATTR_ICON) == "mdi:weather-windy"
entry = registry.async_get("sensor.home_wind_gust_day_0d")
assert entry
assert entry.unique_id == "0123456-windgustday-0"
state = hass.states.get("sensor.home_wind_gust_night_0d")
assert state
assert state.state == "18.5"
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == SPEED_KILOMETERS_PER_HOUR
assert state.attributes.get("direction") == "WSW"
assert state.attributes.get(ATTR_ICON) == "mdi:weather-windy"
entry = registry.async_get("sensor.home_wind_gust_night_0d")
assert entry
assert entry.unique_id == "0123456-windgustnight-0"
async def test_availability(hass):
"""Ensure that we mark the entities unavailable correctly when service is offline."""
await init_integration(hass)
state = hass.states.get("sensor.home_cloud_ceiling")
assert state
assert state.state != STATE_UNAVAILABLE
assert state.state == "3200"
future = utcnow() + timedelta(minutes=60)
with patch(
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
side_effect=ConnectionError(),
):
async_fire_time_changed(hass, future)
await hass.async_block_till_done()
state = hass.states.get("sensor.home_cloud_ceiling")
assert state
assert state.state == STATE_UNAVAILABLE
future = utcnow() + timedelta(minutes=120)
with patch(
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
return_value=json.loads(
load_fixture("accuweather/current_conditions_data.json")
),
):
async_fire_time_changed(hass, future)
await hass.async_block_till_done()
state = hass.states.get("sensor.home_cloud_ceiling")
assert state
assert state.state != STATE_UNAVAILABLE
assert state.state == "3200"
async def test_manual_update_entity(hass):
"""Test manual update entity via service homeasasistant/update_entity."""
await init_integration(hass, forecast=True)
await async_setup_component(hass, "homeassistant", {})
current = json.loads(load_fixture("accuweather/current_conditions_data.json"))
forecast = json.loads(load_fixture("accuweather/forecast_data.json"))
with patch(
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
return_value=current,
) as mock_current, patch(
"homeassistant.components.accuweather.AccuWeather.async_get_forecast",
return_value=forecast,
) as mock_forecast:
await hass.services.async_call(
"homeassistant",
"update_entity",
{ATTR_ENTITY_ID: ["sensor.home_cloud_ceiling"]},
blocking=True,
)
assert mock_current.call_count == 1
assert mock_forecast.call_count == 1

View file

@ -0,0 +1,155 @@
"""Test weather of AccuWeather integration."""
from datetime import timedelta
import json
from homeassistant.components.accuweather.const import ATTRIBUTION
from homeassistant.components.weather import (
ATTR_FORECAST,
ATTR_FORECAST_CONDITION,
ATTR_FORECAST_PRECIPITATION,
ATTR_FORECAST_PRECIPITATION_PROBABILITY,
ATTR_FORECAST_TEMP,
ATTR_FORECAST_TEMP_LOW,
ATTR_FORECAST_TIME,
ATTR_FORECAST_WIND_BEARING,
ATTR_FORECAST_WIND_SPEED,
ATTR_WEATHER_HUMIDITY,
ATTR_WEATHER_OZONE,
ATTR_WEATHER_PRESSURE,
ATTR_WEATHER_TEMPERATURE,
ATTR_WEATHER_VISIBILITY,
ATTR_WEATHER_WIND_BEARING,
ATTR_WEATHER_WIND_SPEED,
)
from homeassistant.const import ATTR_ATTRIBUTION, ATTR_ENTITY_ID, STATE_UNAVAILABLE
from homeassistant.setup import async_setup_component
from homeassistant.util.dt import utcnow
from tests.async_mock import patch
from tests.common import async_fire_time_changed, load_fixture
from tests.components.accuweather import init_integration
async def test_weather_without_forecast(hass):
"""Test states of the weather without forecast."""
await init_integration(hass)
registry = await hass.helpers.entity_registry.async_get_registry()
state = hass.states.get("weather.home")
assert state
assert state.state == "sunny"
assert not state.attributes.get(ATTR_FORECAST)
assert state.attributes.get(ATTR_WEATHER_HUMIDITY) == 67
assert not state.attributes.get(ATTR_WEATHER_OZONE)
assert state.attributes.get(ATTR_WEATHER_PRESSURE) == 1012.0
assert state.attributes.get(ATTR_WEATHER_TEMPERATURE) == 22.6
assert state.attributes.get(ATTR_WEATHER_VISIBILITY) == 16.1
assert state.attributes.get(ATTR_WEATHER_WIND_BEARING) == 180
assert state.attributes.get(ATTR_WEATHER_WIND_SPEED) == 14.5
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
entry = registry.async_get("weather.home")
assert entry
assert entry.unique_id == "0123456"
async def test_weather_with_forecast(hass):
"""Test states of the weather with forecast."""
await init_integration(hass, forecast=True)
registry = await hass.helpers.entity_registry.async_get_registry()
state = hass.states.get("weather.home")
assert state
assert state.state == "sunny"
assert state.attributes.get(ATTR_WEATHER_HUMIDITY) == 67
assert state.attributes.get(ATTR_WEATHER_OZONE) == 32
assert state.attributes.get(ATTR_WEATHER_PRESSURE) == 1012.0
assert state.attributes.get(ATTR_WEATHER_TEMPERATURE) == 22.6
assert state.attributes.get(ATTR_WEATHER_VISIBILITY) == 16.1
assert state.attributes.get(ATTR_WEATHER_WIND_BEARING) == 180
assert state.attributes.get(ATTR_WEATHER_WIND_SPEED) == 14.5
assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION
forecast = state.attributes.get(ATTR_FORECAST)[0]
assert forecast.get(ATTR_FORECAST_CONDITION) == "lightning-rainy"
assert forecast.get(ATTR_FORECAST_PRECIPITATION) == 4.8
assert forecast.get(ATTR_FORECAST_PRECIPITATION_PROBABILITY) == 58
assert forecast.get(ATTR_FORECAST_TEMP) == 29.5
assert forecast.get(ATTR_FORECAST_TEMP_LOW) == 15.4
assert forecast.get(ATTR_FORECAST_TIME) == "2020-07-26T05:00:00+00:00"
assert forecast.get(ATTR_FORECAST_WIND_BEARING) == 166
assert forecast.get(ATTR_FORECAST_WIND_SPEED) == 13.0
entry = registry.async_get("weather.home")
assert entry
assert entry.unique_id == "0123456"
async def test_availability(hass):
"""Ensure that we mark the entities unavailable correctly when service is offline."""
await init_integration(hass)
state = hass.states.get("weather.home")
assert state
assert state.state != STATE_UNAVAILABLE
assert state.state == "sunny"
future = utcnow() + timedelta(minutes=60)
with patch(
"homeassistant.components.accuweather.AccuWeather._async_get_data",
side_effect=ConnectionError(),
):
async_fire_time_changed(hass, future)
await hass.async_block_till_done()
state = hass.states.get("weather.home")
assert state
assert state.state == STATE_UNAVAILABLE
future = utcnow() + timedelta(minutes=120)
with patch(
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
return_value=json.loads(
load_fixture("accuweather/current_conditions_data.json")
),
):
async_fire_time_changed(hass, future)
await hass.async_block_till_done()
state = hass.states.get("weather.home")
assert state
assert state.state != STATE_UNAVAILABLE
assert state.state == "sunny"
async def test_manual_update_entity(hass):
"""Test manual update entity via service homeasasistant/update_entity."""
await init_integration(hass, forecast=True)
await async_setup_component(hass, "homeassistant", {})
current = json.loads(load_fixture("accuweather/current_conditions_data.json"))
forecast = json.loads(load_fixture("accuweather/forecast_data.json"))
with patch(
"homeassistant.components.accuweather.AccuWeather.async_get_current_conditions",
return_value=current,
) as mock_current, patch(
"homeassistant.components.accuweather.AccuWeather.async_get_forecast",
return_value=forecast,
) as mock_forecast:
await hass.services.async_call(
"homeassistant",
"update_entity",
{ATTR_ENTITY_ID: ["weather.home"]},
blocking=True,
)
assert mock_current.call_count == 1
assert mock_forecast.call_count == 1
async def test_unsupported_condition_icon_data(hass):
"""Test with unsupported condition icon data."""
await init_integration(hass, forecast=True, unsupported_icon=True)
state = hass.states.get("weather.home")
assert state.attributes.get(ATTR_FORECAST_CONDITION) is None

View file

@ -0,0 +1,981 @@
[
{
"Date": "2020-07-26T07:00:00+02:00",
"EpochDate": 1595739600,
"HoursOfSun": 7.2,
"DegreeDaySummary": {
"Heating": {
"Value": 0.0,
"Unit": "C",
"UnitType": 17
},
"Cooling": {
"Value": 4.0,
"Unit": "C",
"UnitType": 17
}
},
"Ozone": {
"Value": 32,
"Category": "Good",
"CategoryValue": 1
},
"Grass": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Mold": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Ragweed": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Tree": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"UVIndex": {
"Value": 5,
"Category": "Moderate",
"CategoryValue": 2
},
"TemperatureMin": {
"Value": 15.4,
"Unit": "C",
"UnitType": 17
},
"TemperatureMax": {
"Value": 29.5,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureMin": {
"Value": 15.1,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureMax": {
"Value": 29.8,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureShadeMin": {
"Value": 15.1,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureShadeMax": {
"Value": 28.0,
"Unit": "C",
"UnitType": 17
},
"IconDay": 17,
"IconPhraseDay": "Partly sunny w/ t-storms",
"HasPrecipitationDay": true,
"PrecipitationTypeDay": "Rain",
"PrecipitationIntensityDay": "Moderate",
"ShortPhraseDay": "A shower and t-storm around",
"LongPhraseDay": "Clouds and sunshine with a couple of showers and a thunderstorm around late this afternoon",
"PrecipitationProbabilityDay": 60,
"ThunderstormProbabilityDay": 40,
"RainProbabilityDay": 60,
"SnowProbabilityDay": 0,
"IceProbabilityDay": 0,
"WindDay": {
"Speed": {
"Value": 13.0,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 166,
"Localized": "SSE",
"English": "SSE"
}
},
"WindGustDay": {
"Speed": {
"Value": 29.6,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 178,
"Localized": "S",
"English": "S"
}
},
"TotalLiquidDay": {
"Value": 2.5,
"Unit": "mm",
"UnitType": 3
},
"RainDay": {
"Value": 2.5,
"Unit": "mm",
"UnitType": 3
},
"SnowDay": {
"Value": 0.0,
"Unit": "cm",
"UnitType": 4
},
"IceDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"HoursOfPrecipitationDay": 1.0,
"HoursOfRainDay": 1.0,
"HoursOfSnowDay": 0.0,
"HoursOfIceDay": 0.0,
"CloudCoverDay": 58,
"IconNight": 41,
"IconPhraseNight": "Partly cloudy w/ t-storms",
"HasPrecipitationNight": true,
"PrecipitationTypeNight": "Rain",
"PrecipitationIntensityNight": "Moderate",
"ShortPhraseNight": "Partly cloudy",
"LongPhraseNight": "Partly cloudy",
"PrecipitationProbabilityNight": 57,
"ThunderstormProbabilityNight": 40,
"RainProbabilityNight": 57,
"SnowProbabilityNight": 0,
"IceProbabilityNight": 0,
"WindNight": {
"Speed": {
"Value": 7.4,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 289,
"Localized": "WNW",
"English": "WNW"
}
},
"WindGustNight": {
"Speed": {
"Value": 18.5,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 256,
"Localized": "WSW",
"English": "WSW"
}
},
"TotalLiquidNight": {
"Value": 2.3,
"Unit": "mm",
"UnitType": 3
},
"RainNight": {
"Value": 2.3,
"Unit": "mm",
"UnitType": 3
},
"SnowNight": {
"Value": 0.0,
"Unit": "cm",
"UnitType": 4
},
"IceNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"HoursOfPrecipitationNight": 1.0,
"HoursOfRainNight": 1.0,
"HoursOfSnowNight": 0.0,
"HoursOfIceNight": 0.0,
"CloudCoverNight": 65
},
{
"Date": "2020-07-27T07:00:00+02:00",
"EpochDate": 1595826000,
"HoursOfSun": 7.4,
"DegreeDaySummary": {
"Heating": {
"Value": 0.0,
"Unit": "C",
"UnitType": 17
},
"Cooling": {
"Value": 3.0,
"Unit": "C",
"UnitType": 17
}
},
"Ozone": {
"Value": 39,
"Category": "Good",
"CategoryValue": 1
},
"Grass": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Mold": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Ragweed": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Tree": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"UVIndex": {
"Value": 7,
"Category": "High",
"CategoryValue": 3
},
"TemperatureMin": {
"Value": 15.9,
"Unit": "C",
"UnitType": 17
},
"TemperatureMax": {
"Value": 26.2,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureMin": {
"Value": 15.8,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureMax": {
"Value": 28.9,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureShadeMin": {
"Value": 15.8,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureShadeMax": {
"Value": 25.0,
"Unit": "C",
"UnitType": 17
},
"IconDay": 4,
"IconPhraseDay": "Intermittent clouds",
"HasPrecipitationDay": false,
"ShortPhraseDay": "Clouds and sun",
"LongPhraseDay": "Clouds and sun",
"PrecipitationProbabilityDay": 25,
"ThunderstormProbabilityDay": 24,
"RainProbabilityDay": 25,
"SnowProbabilityDay": 0,
"IceProbabilityDay": 0,
"WindDay": {
"Speed": {
"Value": 9.3,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 297,
"Localized": "WNW",
"English": "WNW"
}
},
"WindGustDay": {
"Speed": {
"Value": 14.8,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 317,
"Localized": "NW",
"English": "NW"
}
},
"TotalLiquidDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"RainDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"SnowDay": {
"Value": 0.0,
"Unit": "cm",
"UnitType": 4
},
"IceDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"HoursOfPrecipitationDay": 0.0,
"HoursOfRainDay": 0.0,
"HoursOfSnowDay": 0.0,
"HoursOfIceDay": 0.0,
"CloudCoverDay": 52,
"IconNight": 36,
"IconPhraseNight": "Intermittent clouds",
"HasPrecipitationNight": false,
"ShortPhraseNight": "Partly cloudy",
"LongPhraseNight": "Partly cloudy",
"PrecipitationProbabilityNight": 6,
"ThunderstormProbabilityNight": 0,
"RainProbabilityNight": 6,
"SnowProbabilityNight": 0,
"IceProbabilityNight": 0,
"WindNight": {
"Speed": {
"Value": 7.4,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 162,
"Localized": "SSE",
"English": "SSE"
}
},
"WindGustNight": {
"Speed": {
"Value": 14.8,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 175,
"Localized": "S",
"English": "S"
}
},
"TotalLiquidNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"RainNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"SnowNight": {
"Value": 0.0,
"Unit": "cm",
"UnitType": 4
},
"IceNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"HoursOfPrecipitationNight": 0.0,
"HoursOfRainNight": 0.0,
"HoursOfSnowNight": 0.0,
"HoursOfIceNight": 0.0,
"CloudCoverNight": 63
},
{
"Date": "2020-07-28T07:00:00+02:00",
"EpochDate": 1595912400,
"HoursOfSun": 5.7,
"DegreeDaySummary": {
"Heating": {
"Value": 0.0,
"Unit": "C",
"UnitType": 17
},
"Cooling": {
"Value": 6.0,
"Unit": "C",
"UnitType": 17
}
},
"Ozone": {
"Value": 29,
"Category": "Good",
"CategoryValue": 1
},
"Grass": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Mold": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Ragweed": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Tree": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"UVIndex": {
"Value": 7,
"Category": "High",
"CategoryValue": 3
},
"TemperatureMin": {
"Value": 16.8,
"Unit": "C",
"UnitType": 17
},
"TemperatureMax": {
"Value": 31.7,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureMin": {
"Value": 16.7,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureMax": {
"Value": 31.6,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureShadeMin": {
"Value": 16.7,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureShadeMax": {
"Value": 30.0,
"Unit": "C",
"UnitType": 17
},
"IconDay": 4,
"IconPhraseDay": "Intermittent clouds",
"HasPrecipitationDay": false,
"ShortPhraseDay": "Partly sunny and very warm",
"LongPhraseDay": "Very warm with a blend of sun and clouds",
"PrecipitationProbabilityDay": 10,
"ThunderstormProbabilityDay": 4,
"RainProbabilityDay": 10,
"SnowProbabilityDay": 0,
"IceProbabilityDay": 0,
"WindDay": {
"Speed": {
"Value": 16.7,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 198,
"Localized": "SSW",
"English": "SSW"
}
},
"WindGustDay": {
"Speed": {
"Value": 24.1,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 198,
"Localized": "SSW",
"English": "SSW"
}
},
"TotalLiquidDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"RainDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"SnowDay": {
"Value": 0.0,
"Unit": "cm",
"UnitType": 4
},
"IceDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"HoursOfPrecipitationDay": 0.0,
"HoursOfRainDay": 0.0,
"HoursOfSnowDay": 0.0,
"HoursOfIceDay": 0.0,
"CloudCoverDay": 65,
"IconNight": 36,
"IconPhraseNight": "Intermittent clouds",
"HasPrecipitationNight": false,
"ShortPhraseNight": "Partly cloudy",
"LongPhraseNight": "Partly cloudy",
"PrecipitationProbabilityNight": 25,
"ThunderstormProbabilityNight": 24,
"RainProbabilityNight": 25,
"SnowProbabilityNight": 0,
"IceProbabilityNight": 0,
"WindNight": {
"Speed": {
"Value": 9.3,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 265,
"Localized": "W",
"English": "W"
}
},
"WindGustNight": {
"Speed": {
"Value": 22.2,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 271,
"Localized": "W",
"English": "W"
}
},
"TotalLiquidNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"RainNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"SnowNight": {
"Value": 0.0,
"Unit": "cm",
"UnitType": 4
},
"IceNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"HoursOfPrecipitationNight": 0.0,
"HoursOfRainNight": 0.0,
"HoursOfSnowNight": 0.0,
"HoursOfIceNight": 0.0,
"CloudCoverNight": 53
},
{
"Date": "2020-07-29T07:00:00+02:00",
"EpochDate": 1595998800,
"HoursOfSun": 9.4,
"DegreeDaySummary": {
"Heating": {
"Value": 0.0,
"Unit": "C",
"UnitType": 17
},
"Cooling": {
"Value": 0.0,
"Unit": "C",
"UnitType": 17
}
},
"Ozone": {
"Value": 18,
"Category": "Good",
"CategoryValue": 1
},
"Grass": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Mold": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Ragweed": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Tree": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"UVIndex": {
"Value": 6,
"Category": "High",
"CategoryValue": 3
},
"TemperatureMin": {
"Value": 11.7,
"Unit": "C",
"UnitType": 17
},
"TemperatureMax": {
"Value": 24.0,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureMin": {
"Value": 10.1,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureMax": {
"Value": 26.5,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureShadeMin": {
"Value": 10.1,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureShadeMax": {
"Value": 22.5,
"Unit": "C",
"UnitType": 17
},
"IconDay": 3,
"IconPhraseDay": "Partly sunny",
"HasPrecipitationDay": false,
"ShortPhraseDay": "Cooler with partial sunshine",
"LongPhraseDay": "Cooler with partial sunshine",
"PrecipitationProbabilityDay": 9,
"ThunderstormProbabilityDay": 0,
"RainProbabilityDay": 9,
"SnowProbabilityDay": 0,
"IceProbabilityDay": 0,
"WindDay": {
"Speed": {
"Value": 13.0,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 293,
"Localized": "WNW",
"English": "WNW"
}
},
"WindGustDay": {
"Speed": {
"Value": 24.1,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 271,
"Localized": "W",
"English": "W"
}
},
"TotalLiquidDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"RainDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"SnowDay": {
"Value": 0.0,
"Unit": "cm",
"UnitType": 4
},
"IceDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"HoursOfPrecipitationDay": 0.0,
"HoursOfRainDay": 0.0,
"HoursOfSnowDay": 0.0,
"HoursOfIceDay": 0.0,
"CloudCoverDay": 45,
"IconNight": 34,
"IconPhraseNight": "Mostly clear",
"HasPrecipitationNight": false,
"ShortPhraseNight": "Mainly clear",
"LongPhraseNight": "Mainly clear",
"PrecipitationProbabilityNight": 1,
"ThunderstormProbabilityNight": 0,
"RainProbabilityNight": 1,
"SnowProbabilityNight": 0,
"IceProbabilityNight": 0,
"WindNight": {
"Speed": {
"Value": 11.1,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 264,
"Localized": "W",
"English": "W"
}
},
"WindGustNight": {
"Speed": {
"Value": 18.5,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 266,
"Localized": "W",
"English": "W"
}
},
"TotalLiquidNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"RainNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"SnowNight": {
"Value": 0.0,
"Unit": "cm",
"UnitType": 4
},
"IceNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"HoursOfPrecipitationNight": 0.0,
"HoursOfRainNight": 0.0,
"HoursOfSnowNight": 0.0,
"HoursOfIceNight": 0.0,
"CloudCoverNight": 27
},
{
"Date": "2020-07-30T07:00:00+02:00",
"EpochDate": 1596085200,
"HoursOfSun": 9.2,
"DegreeDaySummary": {
"Heating": {
"Value": 1.0,
"Unit": "C",
"UnitType": 17
},
"Cooling": {
"Value": 0.0,
"Unit": "C",
"UnitType": 17
}
},
"Ozone": {
"Value": 14,
"Category": "Good",
"CategoryValue": 1
},
"Grass": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Mold": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Ragweed": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"Tree": {
"Value": 0,
"Category": "Low",
"CategoryValue": 1
},
"UVIndex": {
"Value": 7,
"Category": "High",
"CategoryValue": 3
},
"TemperatureMin": {
"Value": 12.2,
"Unit": "C",
"UnitType": 17
},
"TemperatureMax": {
"Value": 21.4,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureMin": {
"Value": 11.3,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureMax": {
"Value": 22.2,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureShadeMin": {
"Value": 11.3,
"Unit": "C",
"UnitType": 17
},
"RealFeelTemperatureShadeMax": {
"Value": 19.5,
"Unit": "C",
"UnitType": 17
},
"IconDay": 4,
"IconPhraseDay": "Intermittent clouds",
"HasPrecipitationDay": false,
"ShortPhraseDay": "Clouds and sun",
"LongPhraseDay": "Intervals of clouds and sunshine",
"PrecipitationProbabilityDay": 1,
"ThunderstormProbabilityDay": 0,
"RainProbabilityDay": 1,
"SnowProbabilityDay": 0,
"IceProbabilityDay": 0,
"WindDay": {
"Speed": {
"Value": 18.5,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 280,
"Localized": "W",
"English": "W"
}
},
"WindGustDay": {
"Speed": {
"Value": 27.8,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 273,
"Localized": "W",
"English": "W"
}
},
"TotalLiquidDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"RainDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"SnowDay": {
"Value": 0.0,
"Unit": "cm",
"UnitType": 4
},
"IceDay": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"HoursOfPrecipitationDay": 0.0,
"HoursOfRainDay": 0.0,
"HoursOfSnowDay": 0.0,
"HoursOfIceDay": 0.0,
"CloudCoverDay": 50,
"IconNight": 34,
"IconPhraseNight": "Mostly clear",
"HasPrecipitationNight": false,
"ShortPhraseNight": "Mostly clear",
"LongPhraseNight": "Mostly clear",
"PrecipitationProbabilityNight": 3,
"ThunderstormProbabilityNight": 0,
"RainProbabilityNight": 3,
"SnowProbabilityNight": 0,
"IceProbabilityNight": 0,
"WindNight": {
"Speed": {
"Value": 9.3,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 272,
"Localized": "W",
"English": "W"
}
},
"WindGustNight": {
"Speed": {
"Value": 18.5,
"Unit": "km/h",
"UnitType": 7
},
"Direction": {
"Degrees": 274,
"Localized": "W",
"English": "W"
}
},
"TotalLiquidNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"RainNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"SnowNight": {
"Value": 0.0,
"Unit": "cm",
"UnitType": 4
},
"IceNight": {
"Value": 0.0,
"Unit": "mm",
"UnitType": 3
},
"HoursOfPrecipitationNight": 0.0,
"HoursOfRainNight": 0.0,
"HoursOfSnowNight": 0.0,
"HoursOfIceNight": 0.0,
"CloudCoverNight": 13
}
]