Merge pull request #52745 from home-assistant/rc

2021.7.1
This commit is contained in:
Franck Nijhof 2021-07-08 16:40:16 +02:00 committed by GitHub
commit 27c6fe4376
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 198 additions and 148 deletions

View File

@ -634,6 +634,7 @@ omit =
homeassistant/components/mjpeg/camera.py
homeassistant/components/mochad/*
homeassistant/components/modbus/climate.py
homeassistant/components/modbus/modbus.py
homeassistant/components/modem_callerid/sensor.py
homeassistant/components/motion_blinds/__init__.py
homeassistant/components/motion_blinds/const.py

View File

@ -59,8 +59,8 @@ def setup(hass, config):
for device in devices:
_LOGGER.info(
"Discovered Ecovacs device on account: %s with nickname %s",
device["did"],
device["nick"],
device.get("did"),
device.get("nick"),
)
vacbot = VacBot(
ecovacs_api.uid,
@ -77,7 +77,8 @@ def setup(hass, config):
"""Shut down open connections to Ecovacs XMPP server."""
for device in hass.data[ECOVACS_DEVICES]:
_LOGGER.info(
"Shutting down connection to Ecovacs device %s", device.vacuum["did"]
"Shutting down connection to Ecovacs device %s",
device.vacuum.get("did"),
)
device.disconnect()

View File

@ -77,7 +77,7 @@ class EsphomeCamera(Camera, EsphomeBaseEntity):
await self._image_cond.wait()
if not self.available:
return None
return self._state.image[:]
return self._state.data[:]
async def _async_camera_stream_image(self) -> bytes | None:
"""Return a single camera image in a stream."""
@ -88,7 +88,7 @@ class EsphomeCamera(Camera, EsphomeBaseEntity):
await self._image_cond.wait()
if not self.available:
return None
return self._state.image[:]
return self._state.data[:]
async def handle_async_mjpeg_stream(self, request):
"""Serve an HTTP MJPEG stream from the camera."""

View File

@ -3,7 +3,7 @@
"name": "ESPHome",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/esphome",
"requirements": ["aioesphomeapi==4.0.1"],
"requirements": ["aioesphomeapi==5.0.0"],
"zeroconf": ["_esphomelib._tcp.local."],
"codeowners": ["@OttoWinter", "@jesserockz"],
"after_dependencies": ["zeroconf", "tag"],

View File

@ -1,6 +1,8 @@
"""Support for the Forecast.Solar sensor service."""
from __future__ import annotations
from datetime import datetime
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN, SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_IDENTIFIERS, ATTR_MANUFACTURER, ATTR_NAME
@ -64,5 +66,7 @@ class ForecastSolarSensorEntity(CoordinatorEntity, SensorEntity):
@property
def state(self) -> StateType:
"""Return the state of the sensor."""
state: StateType = getattr(self.coordinator.data, self._sensor.key)
state: StateType | datetime = getattr(self.coordinator.data, self._sensor.key)
if isinstance(state, datetime):
return state.isoformat()
return state

View File

@ -195,12 +195,13 @@ class FritzBoxTools:
"""Scan for new devices and return a list of found device ids."""
_LOGGER.debug("Checking devices for FRITZ!Box router %s", self.host)
_default_consider_home = DEFAULT_CONSIDER_HOME.total_seconds()
if self._options:
consider_home = self._options.get(
CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME.total_seconds()
CONF_CONSIDER_HOME, _default_consider_home
)
else:
consider_home = DEFAULT_CONSIDER_HOME
consider_home = _default_consider_home
new_device = False
for known_host in self._update_info():

View File

@ -66,9 +66,6 @@ class KNXFan(KnxEntity, FanEntity):
# FanSpeedMode.STEP if max_step is set
self._step_range: tuple[int, int] | None = (1, max_step) if max_step else None
self._attr_supported_features = SUPPORT_SET_SPEED
if self._device.supports_oscillation:
self._attr_supported_features |= SUPPORT_OSCILLATE
self._attr_unique_id = str(self._device.speed.group_address)
async def async_set_percentage(self, percentage: int) -> None:
@ -79,6 +76,16 @@ class KNXFan(KnxEntity, FanEntity):
else:
await self._device.set_speed(percentage)
@property
def supported_features(self) -> int:
"""Flag supported features."""
flags = SUPPORT_SET_SPEED
if self._device.supports_oscillation:
flags |= SUPPORT_OSCILLATE
return flags
@property
def percentage(self) -> int | None:
"""Return the current speed as a percentage."""

View File

@ -2,7 +2,7 @@
"domain": "lutron",
"name": "Lutron",
"documentation": "https://www.home-assistant.io/integrations/lutron",
"requirements": ["pylutron==0.2.7"],
"requirements": ["pylutron==0.2.8"],
"codeowners": ["@JonGilmore"],
"iot_class": "local_polling"
}

View File

@ -47,7 +47,7 @@ async def async_setup_entry(
def _build_forecast_data(timestep):
data = {}
data[ATTR_FORECAST_TIME] = timestep.date
data[ATTR_FORECAST_TIME] = timestep.date.isoformat()
if timestep.weather:
data[ATTR_FORECAST_CONDITION] = _get_weather_condition(timestep.weather.value)
if timestep.precipitation:

View File

@ -310,6 +310,8 @@ class ModbusHub:
"""Convert async to sync pymodbus call."""
if self._config_delay:
return None
if not self._client:
return None
if not self._client.is_socket_open():
return None
async with self._lock:

View File

@ -59,6 +59,9 @@ async def async_setup_entry(hass, entry, async_add_entities):
vol.Optional(ATTR_UNLATCH, default=False): cv.boolean,
},
"lock_n_go",
)
platform.async_register_entity_service(
"set_continuous_mode",
{
vol.Required(ATTR_ENABLE): cv.boolean,

View File

@ -191,6 +191,8 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
"""Get rain data from weather data."""
if "all" in rain:
return round(rain["all"], 2)
if "3h" in rain:
return round(rain["3h"], 2)
if "1h" in rain:
return round(rain["1h"], 2)
return 0
@ -201,6 +203,8 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
if snow:
if "all" in snow:
return round(snow["all"], 2)
if "3h" in snow:
return round(snow["3h"], 2)
if "1h" in snow:
return round(snow["1h"], 2)
return 0

View File

@ -3,7 +3,7 @@
"name": "SimpliSafe",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/simplisafe",
"requirements": ["simplisafe-python==11.0.0"],
"requirements": ["simplisafe-python==11.0.1"],
"codeowners": ["@bachya"],
"iot_class": "cloud_polling"
}

View File

@ -52,14 +52,17 @@ CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
MP_DOMAIN: vol.Schema(
{
vol.Optional(CONF_ADVERTISE_ADDR): cv.string,
vol.Optional(CONF_INTERFACE_ADDR): cv.string,
vol.Optional(CONF_HOSTS): vol.All(
cv.ensure_list_csv, [cv.string]
),
}
MP_DOMAIN: vol.All(
cv.deprecated(CONF_INTERFACE_ADDR),
vol.Schema(
{
vol.Optional(CONF_ADVERTISE_ADDR): cv.string,
vol.Optional(CONF_INTERFACE_ADDR): cv.string,
vol.Optional(CONF_HOSTS): vol.All(
cv.ensure_list_csv, [cv.string]
),
}
),
)
}
)
@ -126,6 +129,13 @@ async def async_setup_entry( # noqa: C901
if advertise_addr:
pysonos.config.EVENT_ADVERTISE_IP = advertise_addr
if deprecated_address := config.get(CONF_INTERFACE_ADDR):
_LOGGER.warning(
"'%s' is deprecated, enable %s in the Network integration (https://www.home-assistant.io/integrations/network/)",
CONF_INTERFACE_ADDR,
deprecated_address,
)
async def _async_stop_event_listener(event: Event) -> None:
await asyncio.gather(
*[speaker.async_unsubscribe() for speaker in data.discovered.values()],

View File

@ -71,6 +71,7 @@ SUBSCRIPTION_SERVICES = [
"zoneGroupTopology",
]
UNAVAILABLE_VALUES = {"", "NOT_IMPLEMENTED", None}
UNUSED_DEVICE_KEYS = ["SPID", "TargetRoomName"]
_LOGGER = logging.getLogger(__name__)
@ -407,6 +408,10 @@ class SonosSpeaker:
"""Update device properties from an event."""
if more_info := event.variables.get("more_info"):
battery_dict = dict(x.split(":") for x in more_info.split(","))
for unused in UNUSED_DEVICE_KEYS:
battery_dict.pop(unused, None)
if not battery_dict:
return
if "BattChg" not in battery_dict:
_LOGGER.debug(
"Unknown device properties update for %s (%s), please report an issue: '%s'",

View File

@ -43,7 +43,6 @@ from .const import (
)
from .core import PROVIDERS, IdleTimer, StreamOutput
from .hls import async_setup_hls
from .recorder import RecorderOutput
_LOGGER = logging.getLogger(__name__)
@ -265,6 +264,10 @@ class Stream:
) -> None:
"""Make a .mp4 recording from a provided stream."""
# Keep import here so that we can import stream integration without installing reqs
# pylint: disable=import-outside-toplevel
from .recorder import RecorderOutput
# Check for file access
if not self.hass.config.is_allowed_path(video_path):
raise HomeAssistantError(f"Can't write {video_path}, no access to path!")

View File

@ -3,7 +3,7 @@
"name": "Belkin WeMo",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/wemo",
"requirements": ["pywemo==0.6.3"],
"requirements": ["pywemo==0.6.5"],
"ssdp": [
{
"manufacturer": "Belkin International Inc."

View File

@ -5,7 +5,7 @@ from typing import Final
MAJOR_VERSION: Final = 2021
MINOR_VERSION: Final = 7
PATCH_VERSION: Final = "0"
PATCH_VERSION: Final = "1"
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 8, 0)

View File

@ -160,7 +160,7 @@ aioeafm==0.1.2
aioemonitor==1.0.5
# homeassistant.components.esphome
aioesphomeapi==4.0.1
aioesphomeapi==5.0.0
# homeassistant.components.flo
aioflo==0.4.1
@ -1562,7 +1562,7 @@ pyloopenergy==0.2.1
pylutron-caseta==0.10.0
# homeassistant.components.lutron
pylutron==0.2.7
pylutron==0.2.8
# homeassistant.components.mailgun
pymailgunner==1.4
@ -1966,7 +1966,7 @@ pyvolumio==0.1.3
pywebpush==1.9.2
# homeassistant.components.wemo
pywemo==0.6.3
pywemo==0.6.5
# homeassistant.components.wilight
pywilight==0.0.70
@ -2102,7 +2102,7 @@ simplehound==0.3
simplepush==1.1.4
# homeassistant.components.simplisafe
simplisafe-python==11.0.0
simplisafe-python==11.0.1
# homeassistant.components.sisyphus
sisyphus-control==3.0

View File

@ -100,7 +100,7 @@ aioeafm==0.1.2
aioemonitor==1.0.5
# homeassistant.components.esphome
aioesphomeapi==4.0.1
aioesphomeapi==5.0.0
# homeassistant.components.flo
aioflo==0.4.1
@ -1084,7 +1084,7 @@ pyvolumio==0.1.3
pywebpush==1.9.2
# homeassistant.components.wemo
pywemo==0.6.3
pywemo==0.6.5
# homeassistant.components.wilight
pywilight==0.0.70
@ -1148,7 +1148,7 @@ sharkiqpy==0.1.8
simplehound==0.3
# homeassistant.components.simplisafe
simplisafe-python==11.0.0
simplisafe-python==11.0.1
# homeassistant.components.slack
slackclient==2.5.0

View File

@ -70,7 +70,7 @@ async def test_sensors(
assert entry
assert state
assert entry.unique_id == f"{entry_id}_power_highest_peak_time_today"
assert state.state == "2021-06-27 13:00:00+00:00"
assert state.state == "2021-06-27T13:00:00+00:00"
assert state.attributes.get(ATTR_FRIENDLY_NAME) == "Highest Power Peak Time - Today"
assert state.attributes.get(ATTR_STATE_CLASS) is None
assert state.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_TIMESTAMP
@ -82,7 +82,7 @@ async def test_sensors(
assert entry
assert state
assert entry.unique_id == f"{entry_id}_power_highest_peak_time_tomorrow"
assert state.state == "2021-06-27 14:00:00+00:00"
assert state.state == "2021-06-27T14:00:00+00:00"
assert (
state.attributes.get(ATTR_FRIENDLY_NAME) == "Highest Power Peak Time - Tomorrow"
)

View File

@ -2,8 +2,7 @@
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S%z"
TEST_DATETIME_STRING = "2020-04-25 12:00:00+0000"
TEST_DATETIME_STRING = "2020-04-25T12:00:00+00:00"
TEST_API_KEY = "test-metoffice-api-key"

View File

@ -6,7 +6,6 @@ from homeassistant.components.metoffice.const import ATTRIBUTION, DOMAIN
from . import NewDateTime
from .const import (
DATETIME_FORMAT,
KINGSLYNN_SENSOR_RESULTS,
METOFFICE_CONFIG_KINGSLYNN,
METOFFICE_CONFIG_WAVERTREE,
@ -54,13 +53,10 @@ async def test_one_sensor_site_running(hass, requests_mock, legacy_patchable_tim
for running_id in running_sensor_ids:
sensor = hass.states.get(running_id)
sensor_id = sensor.attributes.get("sensor_id")
sensor_name, sensor_value = WAVERTREE_SENSOR_RESULTS[sensor_id]
_, sensor_value = WAVERTREE_SENSOR_RESULTS[sensor_id]
assert sensor.state == sensor_value
assert (
sensor.attributes.get("last_update").strftime(DATETIME_FORMAT)
== TEST_DATETIME_STRING
)
assert sensor.attributes.get("last_update").isoformat() == TEST_DATETIME_STRING
assert sensor.attributes.get("site_id") == "354107"
assert sensor.attributes.get("site_name") == TEST_SITE_NAME_WAVERTREE
assert sensor.attributes.get("attribution") == ATTRIBUTION
@ -115,11 +111,10 @@ async def test_two_sensor_sites_running(hass, requests_mock, legacy_patchable_ti
sensor = hass.states.get(running_id)
sensor_id = sensor.attributes.get("sensor_id")
if sensor.attributes.get("site_id") == "354107":
sensor_name, sensor_value = WAVERTREE_SENSOR_RESULTS[sensor_id]
_, sensor_value = WAVERTREE_SENSOR_RESULTS[sensor_id]
assert sensor.state == sensor_value
assert (
sensor.attributes.get("last_update").strftime(DATETIME_FORMAT)
== TEST_DATETIME_STRING
sensor.attributes.get("last_update").isoformat() == TEST_DATETIME_STRING
)
assert sensor.attributes.get("sensor_id") == sensor_id
assert sensor.attributes.get("site_id") == "354107"
@ -127,11 +122,10 @@ async def test_two_sensor_sites_running(hass, requests_mock, legacy_patchable_ti
assert sensor.attributes.get("attribution") == ATTRIBUTION
else:
sensor_name, sensor_value = KINGSLYNN_SENSOR_RESULTS[sensor_id]
_, sensor_value = KINGSLYNN_SENSOR_RESULTS[sensor_id]
assert sensor.state == sensor_value
assert (
sensor.attributes.get("last_update").strftime(DATETIME_FORMAT)
== TEST_DATETIME_STRING
sensor.attributes.get("last_update").isoformat() == TEST_DATETIME_STRING
)
assert sensor.attributes.get("sensor_id") == sensor_id
assert sensor.attributes.get("site_id") == "322380"

View File

@ -9,7 +9,6 @@ from homeassistant.util import utcnow
from . import NewDateTime
from .const import (
DATETIME_FORMAT,
METOFFICE_CONFIG_KINGSLYNN,
METOFFICE_CONFIG_WAVERTREE,
WAVERTREE_SENSOR_RESULTS,
@ -74,11 +73,11 @@ async def test_site_cannot_update(hass, requests_mock, legacy_patchable_time):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
entity = hass.states.get("weather.met_office_wavertree_3_hourly")
assert entity
weather = hass.states.get("weather.met_office_wavertree_3_hourly")
assert weather
entity = hass.states.get("weather.met_office_wavertree_daily")
assert entity
weather = hass.states.get("weather.met_office_wavertree_daily")
assert weather
requests_mock.get("/public/data/val/wxfcs/all/json/354107?res=3hourly", text="")
requests_mock.get("/public/data/val/wxfcs/all/json/354107?res=daily", text="")
@ -87,11 +86,11 @@ async def test_site_cannot_update(hass, requests_mock, legacy_patchable_time):
async_fire_time_changed(hass, future_time)
await hass.async_block_till_done()
entity = hass.states.get("weather.met_office_wavertree_3_hourly")
assert entity.state == STATE_UNAVAILABLE
weather = hass.states.get("weather.met_office_wavertree_3_hourly")
assert weather.state == STATE_UNAVAILABLE
entity = hass.states.get("weather.met_office_wavertree_daily")
assert entity.state == STATE_UNAVAILABLE
weather = hass.states.get("weather.met_office_wavertree_daily")
assert weather.state == STATE_UNAVAILABLE
@patch(
@ -126,50 +125,49 @@ async def test_one_weather_site_running(hass, requests_mock, legacy_patchable_ti
await hass.async_block_till_done()
# Wavertree 3-hourly weather platform expected results
entity = hass.states.get("weather.met_office_wavertree_3_hourly")
assert entity
weather = hass.states.get("weather.met_office_wavertree_3_hourly")
assert weather
assert entity.state == "sunny"
assert entity.attributes.get("temperature") == 17
assert entity.attributes.get("wind_speed") == 9
assert entity.attributes.get("wind_bearing") == "SSE"
assert entity.attributes.get("visibility") == "Good - 10-20"
assert entity.attributes.get("humidity") == 50
assert weather.state == "sunny"
assert weather.attributes.get("temperature") == 17
assert weather.attributes.get("wind_speed") == 9
assert weather.attributes.get("wind_bearing") == "SSE"
assert weather.attributes.get("visibility") == "Good - 10-20"
assert weather.attributes.get("humidity") == 50
# Forecasts added - just pick out 1 entry to check
assert len(entity.attributes.get("forecast")) == 35
assert len(weather.attributes.get("forecast")) == 35
assert (
entity.attributes.get("forecast")[26]["datetime"].strftime(DATETIME_FORMAT)
== "2020-04-28 21:00:00+0000"
weather.attributes.get("forecast")[26]["datetime"]
== "2020-04-28T21:00:00+00:00"
)
assert entity.attributes.get("forecast")[26]["condition"] == "cloudy"
assert entity.attributes.get("forecast")[26]["temperature"] == 10
assert entity.attributes.get("forecast")[26]["wind_speed"] == 4
assert entity.attributes.get("forecast")[26]["wind_bearing"] == "NNE"
assert weather.attributes.get("forecast")[26]["condition"] == "cloudy"
assert weather.attributes.get("forecast")[26]["temperature"] == 10
assert weather.attributes.get("forecast")[26]["wind_speed"] == 4
assert weather.attributes.get("forecast")[26]["wind_bearing"] == "NNE"
# Wavertree daily weather platform expected results
entity = hass.states.get("weather.met_office_wavertree_daily")
assert entity
weather = hass.states.get("weather.met_office_wavertree_daily")
assert weather
assert entity.state == "sunny"
assert entity.attributes.get("temperature") == 19
assert entity.attributes.get("wind_speed") == 9
assert entity.attributes.get("wind_bearing") == "SSE"
assert entity.attributes.get("visibility") == "Good - 10-20"
assert entity.attributes.get("humidity") == 50
assert weather.state == "sunny"
assert weather.attributes.get("temperature") == 19
assert weather.attributes.get("wind_speed") == 9
assert weather.attributes.get("wind_bearing") == "SSE"
assert weather.attributes.get("visibility") == "Good - 10-20"
assert weather.attributes.get("humidity") == 50
# Also has Forecasts added - again, just pick out 1 entry to check
assert len(entity.attributes.get("forecast")) == 8
assert len(weather.attributes.get("forecast")) == 8
assert (
entity.attributes.get("forecast")[7]["datetime"].strftime(DATETIME_FORMAT)
== "2020-04-29 12:00:00+0000"
weather.attributes.get("forecast")[7]["datetime"] == "2020-04-29T12:00:00+00:00"
)
assert entity.attributes.get("forecast")[7]["condition"] == "rainy"
assert entity.attributes.get("forecast")[7]["temperature"] == 13
assert entity.attributes.get("forecast")[7]["wind_speed"] == 13
assert entity.attributes.get("forecast")[7]["wind_bearing"] == "SE"
assert weather.attributes.get("forecast")[7]["condition"] == "rainy"
assert weather.attributes.get("forecast")[7]["temperature"] == 13
assert weather.attributes.get("forecast")[7]["wind_speed"] == 13
assert weather.attributes.get("forecast")[7]["wind_bearing"] == "SE"
@patch(
@ -216,93 +214,91 @@ async def test_two_weather_sites_running(hass, requests_mock, legacy_patchable_t
await hass.async_block_till_done()
# Wavertree 3-hourly weather platform expected results
entity = hass.states.get("weather.met_office_wavertree_3_hourly")
assert entity
weather = hass.states.get("weather.met_office_wavertree_3_hourly")
assert weather
assert entity.state == "sunny"
assert entity.attributes.get("temperature") == 17
assert entity.attributes.get("wind_speed") == 9
assert entity.attributes.get("wind_bearing") == "SSE"
assert entity.attributes.get("visibility") == "Good - 10-20"
assert entity.attributes.get("humidity") == 50
assert weather.state == "sunny"
assert weather.attributes.get("temperature") == 17
assert weather.attributes.get("wind_speed") == 9
assert weather.attributes.get("wind_bearing") == "SSE"
assert weather.attributes.get("visibility") == "Good - 10-20"
assert weather.attributes.get("humidity") == 50
# Forecasts added - just pick out 1 entry to check
assert len(entity.attributes.get("forecast")) == 35
assert len(weather.attributes.get("forecast")) == 35
assert (
entity.attributes.get("forecast")[18]["datetime"].strftime(DATETIME_FORMAT)
== "2020-04-27 21:00:00+0000"
weather.attributes.get("forecast")[18]["datetime"]
== "2020-04-27T21:00:00+00:00"
)
assert entity.attributes.get("forecast")[18]["condition"] == "sunny"
assert entity.attributes.get("forecast")[18]["temperature"] == 9
assert entity.attributes.get("forecast")[18]["wind_speed"] == 4
assert entity.attributes.get("forecast")[18]["wind_bearing"] == "NW"
assert weather.attributes.get("forecast")[18]["condition"] == "sunny"
assert weather.attributes.get("forecast")[18]["temperature"] == 9
assert weather.attributes.get("forecast")[18]["wind_speed"] == 4
assert weather.attributes.get("forecast")[18]["wind_bearing"] == "NW"
# Wavertree daily weather platform expected results
entity = hass.states.get("weather.met_office_wavertree_daily")
assert entity
weather = hass.states.get("weather.met_office_wavertree_daily")
assert weather
assert entity.state == "sunny"
assert entity.attributes.get("temperature") == 19
assert entity.attributes.get("wind_speed") == 9
assert entity.attributes.get("wind_bearing") == "SSE"
assert entity.attributes.get("visibility") == "Good - 10-20"
assert entity.attributes.get("humidity") == 50
assert weather.state == "sunny"
assert weather.attributes.get("temperature") == 19
assert weather.attributes.get("wind_speed") == 9
assert weather.attributes.get("wind_bearing") == "SSE"
assert weather.attributes.get("visibility") == "Good - 10-20"
assert weather.attributes.get("humidity") == 50
# Also has Forecasts added - again, just pick out 1 entry to check
assert len(entity.attributes.get("forecast")) == 8
assert len(weather.attributes.get("forecast")) == 8
assert (
entity.attributes.get("forecast")[7]["datetime"].strftime(DATETIME_FORMAT)
== "2020-04-29 12:00:00+0000"
weather.attributes.get("forecast")[7]["datetime"] == "2020-04-29T12:00:00+00:00"
)
assert entity.attributes.get("forecast")[7]["condition"] == "rainy"
assert entity.attributes.get("forecast")[7]["temperature"] == 13
assert entity.attributes.get("forecast")[7]["wind_speed"] == 13
assert entity.attributes.get("forecast")[7]["wind_bearing"] == "SE"
assert weather.attributes.get("forecast")[7]["condition"] == "rainy"
assert weather.attributes.get("forecast")[7]["temperature"] == 13
assert weather.attributes.get("forecast")[7]["wind_speed"] == 13
assert weather.attributes.get("forecast")[7]["wind_bearing"] == "SE"
# King's Lynn 3-hourly weather platform expected results
entity = hass.states.get("weather.met_office_king_s_lynn_3_hourly")
assert entity
weather = hass.states.get("weather.met_office_king_s_lynn_3_hourly")
assert weather
assert entity.state == "sunny"
assert entity.attributes.get("temperature") == 14
assert entity.attributes.get("wind_speed") == 2
assert entity.attributes.get("wind_bearing") == "E"
assert entity.attributes.get("visibility") == "Very Good - 20-40"
assert entity.attributes.get("humidity") == 60
assert weather.state == "sunny"
assert weather.attributes.get("temperature") == 14
assert weather.attributes.get("wind_speed") == 2
assert weather.attributes.get("wind_bearing") == "E"
assert weather.attributes.get("visibility") == "Very Good - 20-40"
assert weather.attributes.get("humidity") == 60
# Also has Forecast added - just pick out 1 entry to check
assert len(entity.attributes.get("forecast")) == 35
assert len(weather.attributes.get("forecast")) == 35
assert (
entity.attributes.get("forecast")[18]["datetime"].strftime(DATETIME_FORMAT)
== "2020-04-27 21:00:00+0000"
weather.attributes.get("forecast")[18]["datetime"]
== "2020-04-27T21:00:00+00:00"
)
assert entity.attributes.get("forecast")[18]["condition"] == "cloudy"
assert entity.attributes.get("forecast")[18]["temperature"] == 10
assert entity.attributes.get("forecast")[18]["wind_speed"] == 7
assert entity.attributes.get("forecast")[18]["wind_bearing"] == "SE"
assert weather.attributes.get("forecast")[18]["condition"] == "cloudy"
assert weather.attributes.get("forecast")[18]["temperature"] == 10
assert weather.attributes.get("forecast")[18]["wind_speed"] == 7
assert weather.attributes.get("forecast")[18]["wind_bearing"] == "SE"
# King's Lynn daily weather platform expected results
entity = hass.states.get("weather.met_office_king_s_lynn_daily")
assert entity
weather = hass.states.get("weather.met_office_king_s_lynn_daily")
assert weather
assert entity.state == "cloudy"
assert entity.attributes.get("temperature") == 9
assert entity.attributes.get("wind_speed") == 4
assert entity.attributes.get("wind_bearing") == "ESE"
assert entity.attributes.get("visibility") == "Very Good - 20-40"
assert entity.attributes.get("humidity") == 75
assert weather.state == "cloudy"
assert weather.attributes.get("temperature") == 9
assert weather.attributes.get("wind_speed") == 4
assert weather.attributes.get("wind_bearing") == "ESE"
assert weather.attributes.get("visibility") == "Very Good - 20-40"
assert weather.attributes.get("humidity") == 75
# All should have Forecast added - again, just picking out 1 entry to check
assert len(entity.attributes.get("forecast")) == 8
assert len(weather.attributes.get("forecast")) == 8
assert (
entity.attributes.get("forecast")[5]["datetime"].strftime(DATETIME_FORMAT)
== "2020-04-28 12:00:00+0000"
weather.attributes.get("forecast")[5]["datetime"] == "2020-04-28T12:00:00+00:00"
)
assert entity.attributes.get("forecast")[5]["condition"] == "cloudy"
assert entity.attributes.get("forecast")[5]["temperature"] == 11
assert entity.attributes.get("forecast")[5]["wind_speed"] == 7
assert entity.attributes.get("forecast")[5]["wind_bearing"] == "ESE"
assert weather.attributes.get("forecast")[5]["condition"] == "cloudy"
assert weather.attributes.get("forecast")[5]["temperature"] == 11
assert weather.attributes.get("forecast")[5]["wind_speed"] == 7
assert weather.attributes.get("forecast")[5]["wind_bearing"] == "ESE"

View File

@ -103,3 +103,23 @@ async def test_device_payload_without_battery(
await hass.async_block_till_done()
assert bad_payload in caplog.text
async def test_device_payload_without_battery_and_ignored_keys(
hass, config_entry, config, soco, battery_event, caplog
):
"""Test device properties event update without battery info and ignored keys."""
soco.get_battery_info.return_value = None
await setup_platform(hass, config_entry, config)
subscription = soco.deviceProperties.subscribe.return_value
sub_callback = subscription.callback
ignored_payload = "SPID:InCeiling,TargetRoomName:Bouncy House"
battery_event.variables["more_info"] = ignored_payload
sub_callback(battery_event)
await hass.async_block_till_done()
assert ignored_payload not in caplog.text