Merge pull request #51595 from home-assistant/rc

This commit is contained in:
Paulus Schoutsen 2021-06-07 14:47:50 -07:00 committed by GitHub
commit e5028d285c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 353 additions and 63 deletions

View File

@ -115,7 +115,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build base image
uses: home-assistant/builder@2021.05.0
uses: home-assistant/builder@2021.06.2
with:
args: |
$BUILD_ARGS \
@ -167,7 +167,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build base image
uses: home-assistant/builder@2021.05.0
uses: home-assistant/builder@2021.06.2
with:
args: |
$BUILD_ARGS \

View File

@ -228,10 +228,10 @@ class AsusWrtRouter:
# System
model = await _get_nvram_info(self._api, "MODEL")
if model:
if model and "model" in model:
self._model = model["model"]
firmware = await _get_nvram_info(self._api, "FIRMWARE")
if firmware:
if firmware and "firmver" in firmware and "buildno" in firmware:
self._sw_v = f"{firmware['firmver']} (build {firmware['buildno']})"
# Load tracked entities from registry

View File

@ -44,11 +44,15 @@ class BroadlinkHeartbeat:
"""Send packets to feed watchdog timers."""
hass = self._hass
config_entries = hass.config_entries.async_entries(DOMAIN)
hosts = {entry.data[CONF_HOST] for entry in config_entries}
await hass.async_add_executor_job(self.heartbeat, hosts)
for entry in config_entries:
host = entry.data[CONF_HOST]
@staticmethod
def heartbeat(hosts):
"""Send packets to feed watchdog timers."""
for host in hosts:
try:
await hass.async_add_executor_job(blk.ping, host)
blk.ping(host)
except OSError as err:
_LOGGER.debug("Failed to send heartbeat to %s: %s", host, err)
else:

View File

@ -3,6 +3,6 @@
"name": "Deutscher Wetterdienst (DWD) Weather Warnings",
"documentation": "https://www.home-assistant.io/integrations/dwd_weather_warnings",
"codeowners": ["@runningman84", "@stephan192", "@Hummel95"],
"requirements": ["dwdwfsapi==1.0.3"],
"requirements": ["dwdwfsapi==1.0.4"],
"iot_class": "cloud_polling"
}

View File

@ -39,14 +39,14 @@ class GarminConnectConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
return await self._show_setup_form()
websession = async_get_clientsession(self.hass)
username = user_input[CONF_USERNAME]
password = user_input[CONF_PASSWORD]
garmin_client = Garmin(
websession, user_input[CONF_USERNAME], user_input[CONF_PASSWORD]
)
garmin_client = Garmin(websession, username, password)
errors = {}
try:
username = await garmin_client.login()
await garmin_client.login()
except GarminConnectConnectionError:
errors["base"] = "cannot_connect"
return await self._show_setup_form(errors)
@ -68,7 +68,7 @@ class GarminConnectConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
title=username,
data={
CONF_ID: username,
CONF_USERNAME: user_input[CONF_USERNAME],
CONF_PASSWORD: user_input[CONF_PASSWORD],
CONF_USERNAME: username,
CONF_PASSWORD: password,
},
)

View File

@ -2,7 +2,7 @@
"domain": "garmin_connect",
"name": "Garmin Connect",
"documentation": "https://www.home-assistant.io/integrations/garmin_connect",
"requirements": ["garminconnect_aio==0.1.1"],
"requirements": ["garminconnect_aio==0.1.4"],
"codeowners": ["@cyberjunky"],
"config_flow": true,
"iot_class": "cloud_polling"

View File

@ -1,4 +1,6 @@
"""Offer geolocation automation rules."""
import logging
import voluptuous as vol
from homeassistant.components.geo_location import DOMAIN
@ -10,6 +12,8 @@ from homeassistant.helpers.event import TrackStates, async_track_state_change_fi
# mypy: allow-untyped-defs, no-check-untyped-defs
_LOGGER = logging.getLogger(__name__)
EVENT_ENTER = "enter"
EVENT_LEAVE = "leave"
DEFAULT_EVENT = EVENT_ENTER
@ -49,6 +53,13 @@ async def async_attach_trigger(hass, config, action, automation_info):
return
zone_state = hass.states.get(zone_entity_id)
if zone_state is None:
_LOGGER.warning(
"Unable to execute automation %s: Zone %s not found",
automation_info["name"],
zone_entity_id,
)
return
from_match = (
condition.zone(hass, zone_state, from_state) if from_state else False

View File

@ -2,7 +2,7 @@
"domain": "ialarm",
"name": "Antifurto365 iAlarm",
"documentation": "https://www.home-assistant.io/integrations/ialarm",
"requirements": ["pyialarm==1.7"],
"requirements": ["pyialarm==1.8.1"],
"codeowners": ["@RyuzakiKK"],
"config_flow": true,
"iot_class": "local_polling"

View File

@ -172,14 +172,12 @@ async def async_setup_entry(
)
try:
async with async_timeout.timeout(30):
async with async_timeout.timeout(60):
await isy.initialize()
except asyncio.TimeoutError as err:
_LOGGER.error(
"Timed out initializing the ISY; device may be busy, trying again later: %s",
err,
)
raise ConfigEntryNotReady from err
raise ConfigEntryNotReady(
f"Timed out initializing the ISY; device may be busy, trying again later: {err}"
) from err
except ISYInvalidAuthError as err:
_LOGGER.error(
"Invalid credentials for the ISY, please adjust settings and try again: %s",
@ -187,16 +185,13 @@ async def async_setup_entry(
)
return False
except ISYConnectionError as err:
_LOGGER.error(
"Failed to connect to the ISY, please adjust settings and try again: %s",
err,
)
raise ConfigEntryNotReady from err
raise ConfigEntryNotReady(
f"Failed to connect to the ISY, please adjust settings and try again: {err}"
) from err
except ISYResponseParseError as err:
_LOGGER.warning(
"Error processing responses from the ISY; device may be busy, trying again later"
)
raise ConfigEntryNotReady from err
raise ConfigEntryNotReady(
f"Invalid XML response from ISY; Ensure the ISY is running the latest firmware: {err}"
) from err
_categorize_nodes(hass_isy_data, isy.nodes, ignore_identifier, sensor_identifier)
_categorize_programs(hass_isy_data, isy.programs)

View File

@ -186,9 +186,6 @@ async def async_setup_entity_basic(
hass, config, async_add_entities, config_entry, discovery_data=None
):
"""Set up a MQTT Light."""
if CONF_STATE_VALUE_TEMPLATE not in config and CONF_VALUE_TEMPLATE in config:
config[CONF_STATE_VALUE_TEMPLATE] = config[CONF_VALUE_TEMPLATE]
async_add_entities([MqttLight(hass, config, config_entry, discovery_data)])
@ -236,6 +233,9 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity):
def _setup_from_config(self, config):
"""(Re)Setup the entity."""
if CONF_STATE_VALUE_TEMPLATE not in config and CONF_VALUE_TEMPLATE in config:
config[CONF_STATE_VALUE_TEMPLATE] = config[CONF_VALUE_TEMPLATE]
topic = {
key: config.get(key)
for key in (

View File

@ -3,7 +3,7 @@
"name": "ReCollect Waste",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/recollect_waste",
"requirements": ["aiorecollect==1.0.4"],
"requirements": ["aiorecollect==1.0.5"],
"codeowners": ["@bachya"],
"iot_class": "cloud_polling"
}

View File

@ -280,10 +280,10 @@ def _update_states_table_with_foreign_key_options(connection, engine):
for foreign_key in inspector.get_foreign_keys(TABLE_STATES):
if foreign_key["name"] and (
# MySQL/MariaDB will have empty options
not foreign_key["options"]
not foreign_key.get("options")
or
# Postgres will have ondelete set to None
foreign_key["options"].get("ondelete") is None
foreign_key.get("options", {}).get("ondelete") is None
):
alters.append(
{
@ -319,7 +319,7 @@ def _drop_foreign_key_constraints(connection, engine, table, columns):
for foreign_key in inspector.get_foreign_keys(table):
if (
foreign_key["name"]
and foreign_key["options"].get("ondelete")
and foreign_key.get("options", {}).get("ondelete")
and foreign_key["constrained_columns"] == columns
):
drops.append(ForeignKeyConstraint((), (), name=foreign_key["name"]))

View File

@ -112,6 +112,7 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
async def _async_set_unique_id_from_udn(self, raise_on_progress=True):
"""Set the unique id from the udn."""
assert self._host is not None
await self.async_set_unique_id(self._udn, raise_on_progress=raise_on_progress)
self._async_update_existing_host_entry(self._host)
updates = {CONF_HOST: self._host}
@ -206,30 +207,28 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
return entry
return None
async def _async_start_discovery_for_host(self, host):
"""Start discovery for a host."""
if entry := self._async_update_existing_host_entry(host):
async def _async_start_discovery(self):
"""Start discovery."""
assert self._host is not None
if entry := self._async_update_existing_host_entry(self._host):
if entry.unique_id:
# Let the flow continue to fill the missing
# unique id as we may be able to obtain it
# in the next step
raise data_entry_flow.AbortFlow("already_configured")
self.context[CONF_HOST] = host
self.context[CONF_HOST] = self._host
for progress in self._async_in_progress():
if progress.get("context", {}).get(CONF_HOST) == host:
if progress.get("context", {}).get(CONF_HOST) == self._host:
raise data_entry_flow.AbortFlow("already_in_progress")
self._host = host
async def async_step_ssdp(self, discovery_info: DiscoveryInfoType):
"""Handle a flow initialized by ssdp discovery."""
LOGGER.debug("Samsung device found via SSDP: %s", discovery_info)
self._udn = _strip_uuid(discovery_info[ATTR_UPNP_UDN])
self._host = urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname
await self._async_set_unique_id_from_udn()
await self._async_start_discovery_for_host(
urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname
)
await self._async_start_discovery()
self._manufacturer = discovery_info[ATTR_UPNP_MANUFACTURER]
if not self._manufacturer or not self._manufacturer.lower().startswith(
"samsung"
@ -245,7 +244,8 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a flow initialized by dhcp discovery."""
LOGGER.debug("Samsung device found via DHCP: %s", discovery_info)
self._mac = discovery_info[MAC_ADDRESS]
await self._async_start_discovery_for_host(discovery_info[IP_ADDRESS])
self._host = discovery_info[IP_ADDRESS]
await self._async_start_discovery()
await self._async_set_device_unique_id()
self.context["title_placeholders"] = {"device": self._title}
return await self.async_step_confirm()
@ -254,7 +254,8 @@ class SamsungTVConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a flow initialized by zeroconf discovery."""
LOGGER.debug("Samsung device found via ZEROCONF: %s", discovery_info)
self._mac = format_mac(discovery_info[ATTR_PROPERTIES]["deviceid"])
await self._async_start_discovery_for_host(discovery_info[CONF_HOST])
self._host = discovery_info[CONF_HOST]
await self._async_start_discovery()
await self._async_set_device_unique_id()
self.context["title_placeholders"] = {"device": self._title}
return await self.async_step_confirm()

View File

@ -764,7 +764,7 @@ class SonosSpeaker:
"""Pause all current coordinators and restore groups."""
for speaker in (s for s in speakers if s.is_coordinator):
if speaker.media.playback_status == SONOS_STATE_PLAYING:
hass.async_create_task(speaker.soco.pause())
speaker.soco.pause()
groups = []

View File

@ -45,6 +45,7 @@ SIGNAL_UPDATE_ENTITY = "tibber_rt_update_{}"
RT_SENSOR_MAP = {
"averagePower": ["average power", DEVICE_CLASS_POWER, POWER_WATT, None],
"power": ["power", DEVICE_CLASS_POWER, POWER_WATT, None],
"powerProduction": ["power production", DEVICE_CLASS_POWER, POWER_WATT, None],
"minPower": ["min power", DEVICE_CLASS_POWER, POWER_WATT, None],
"maxPower": ["max power", DEVICE_CLASS_POWER, POWER_WATT, None],
"accumulatedConsumption": [

View File

@ -156,6 +156,26 @@ class TodSensor(BinarySensorEntity):
self._time_after += self._after_offset
self._time_before += self._before_offset
def _turn_to_next_day(self):
"""Turn to to the next day."""
if is_sun_event(self._after):
self._time_after = get_astral_event_next(
self.hass, self._after, self._time_after - self._after_offset
)
self._time_after += self._after_offset
else:
# Offset is already there
self._time_after += timedelta(days=1)
if is_sun_event(self._before):
self._time_before = get_astral_event_next(
self.hass, self._before, self._time_before - self._before_offset
)
self._time_before += self._before_offset
else:
# Offset is already there
self._time_before += timedelta(days=1)
async def async_added_to_hass(self):
"""Call when entity about to be added to Home Assistant."""
self._calculate_boudary_time()
@ -182,7 +202,7 @@ class TodSensor(BinarySensorEntity):
if now < self._time_before:
self._next_update = self._time_before
return
self._calculate_boudary_time()
self._turn_to_next_day()
self._next_update = self._time_after
@callback

View File

@ -5,7 +5,7 @@ from typing import Final
MAJOR_VERSION: Final = 2021
MINOR_VERSION: Final = 6
PATCH_VERSION: Final = "2"
PATCH_VERSION: Final = "3"
__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

@ -224,7 +224,7 @@ aiopvpc==2.1.2
aiopylgtv==0.4.0
# homeassistant.components.recollect_waste
aiorecollect==1.0.4
aiorecollect==1.0.5
# homeassistant.components.shelly
aioshelly==0.6.4
@ -515,7 +515,7 @@ dovado==0.4.1
dsmr_parser==0.29
# homeassistant.components.dwd_weather_warnings
dwdwfsapi==1.0.3
dwdwfsapi==1.0.4
# homeassistant.components.dweet
dweepy==0.3.0
@ -635,7 +635,7 @@ gTTS==2.2.2
garages-amsterdam==2.1.1
# homeassistant.components.garmin_connect
garminconnect_aio==0.1.1
garminconnect_aio==0.1.4
# homeassistant.components.geniushub
geniushub-client==0.6.30
@ -1464,7 +1464,7 @@ pyhomematic==0.1.72
pyhomeworks==0.0.6
# homeassistant.components.ialarm
pyialarm==1.7
pyialarm==1.8.1
# homeassistant.components.icloud
pyicloud==0.10.2

View File

@ -146,7 +146,7 @@ aiopvpc==2.1.2
aiopylgtv==0.4.0
# homeassistant.components.recollect_waste
aiorecollect==1.0.4
aiorecollect==1.0.5
# homeassistant.components.shelly
aioshelly==0.6.4
@ -341,7 +341,7 @@ gTTS==2.2.2
garages-amsterdam==2.1.1
# homeassistant.components.garmin_connect
garminconnect_aio==0.1.1
garminconnect_aio==0.1.4
# homeassistant.components.geo_json_events
# homeassistant.components.usgs_earthquakes_feed
@ -808,7 +808,7 @@ pyhiveapi==0.4.2
pyhomematic==0.1.72
# homeassistant.components.ialarm
pyialarm==1.7
pyialarm==1.8.1
# homeassistant.components.icloud
pyicloud==0.10.2

View File

@ -1,4 +1,6 @@
"""The tests for the geolocation trigger."""
import logging
import pytest
from homeassistant.components import automation, zone
@ -318,3 +320,46 @@ async def test_if_fires_on_zone_disappear(hass, calls):
assert (
calls[0].data["some"] == "geo_location - geo_location.entity - hello - - test"
)
async def test_zone_undefined(hass, calls, caplog):
"""Test for undefined zone."""
hass.states.async_set(
"geo_location.entity",
"hello",
{"latitude": 32.880586, "longitude": -117.237564, "source": "test_source"},
)
await hass.async_block_till_done()
caplog.set_level(logging.WARNING)
zone_does_not_exist = "zone.does_not_exist"
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "geo_location",
"source": "test_source",
"zone": zone_does_not_exist,
"event": "leave",
},
"action": {"service": "test.automation"},
}
},
)
hass.states.async_set(
"geo_location.entity",
"hello",
{"latitude": 32.881011, "longitude": -117.234758, "source": "test_source"},
)
await hass.async_block_till_done()
assert len(calls) == 0
assert (
f"Unable to execute automation automation 0: Zone {zone_does_not_exist} not found"
in caplog.text
)

View File

@ -12,6 +12,8 @@ import homeassistant.util.dt as dt_util
from tests.common import assert_setup_component
ORIG_TIMEZONE = dt_util.DEFAULT_TIME_ZONE
@pytest.fixture(autouse=True)
def mock_legacy_time(legacy_patchable_time):
@ -26,6 +28,13 @@ def setup_fixture(hass):
hass.config.longitude = 18.98583
@pytest.fixture(autouse=True)
def restore_timezone(hass):
"""Make sure we change timezone."""
yield
dt_util.set_default_time_zone(ORIG_TIMEZONE)
async def test_setup(hass):
"""Test the setup."""
config = {
@ -863,6 +872,7 @@ async def test_sun_offset(hass):
async def test_dst(hass):
"""Test sun event with offset."""
hass.config.time_zone = "CET"
dt_util.set_default_time_zone(dt_util.get_time_zone("CET"))
test_time = datetime(2019, 3, 30, 3, 0, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
@ -882,7 +892,210 @@ async def test_dst(hass):
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state.attributes["after"] == "2019-03-30T03:30:00+01:00"
assert state.attributes["before"] == "2019-03-30T03:40:00+01:00"
assert state.attributes["next_update"] == "2019-03-30T03:30:00+01:00"
assert state.attributes["after"] == "2019-03-31T03:30:00+02:00"
assert state.attributes["before"] == "2019-03-31T03:40:00+02:00"
assert state.attributes["next_update"] == "2019-03-31T03:30:00+02:00"
assert state.state == STATE_OFF
async def test_simple_before_after_does_not_loop_utc_not_in_range(hass):
"""Test simple before after."""
hass.config.time_zone = "UTC"
dt_util.set_default_time_zone(dt_util.UTC)
test_time = datetime(2019, 1, 10, 18, 43, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{
"platform": "tod",
"name": "Night",
"before": "06:00",
"after": "22:00",
}
]
}
with patch(
"homeassistant.components.tod.binary_sensor.dt_util.utcnow",
return_value=test_time,
):
await async_setup_component(hass, "binary_sensor", config)
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.night")
assert state.state == STATE_OFF
assert state.attributes["after"] == "2019-01-10T22:00:00+00:00"
assert state.attributes["before"] == "2019-01-11T06:00:00+00:00"
assert state.attributes["next_update"] == "2019-01-10T22:00:00+00:00"
async def test_simple_before_after_does_not_loop_utc_in_range(hass):
"""Test simple before after."""
hass.config.time_zone = "UTC"
dt_util.set_default_time_zone(dt_util.UTC)
test_time = datetime(2019, 1, 10, 22, 43, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{
"platform": "tod",
"name": "Night",
"before": "06:00",
"after": "22:00",
}
]
}
with patch(
"homeassistant.components.tod.binary_sensor.dt_util.utcnow",
return_value=test_time,
):
await async_setup_component(hass, "binary_sensor", config)
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.night")
assert state.state == STATE_ON
assert state.attributes["after"] == "2019-01-10T22:00:00+00:00"
assert state.attributes["before"] == "2019-01-11T06:00:00+00:00"
assert state.attributes["next_update"] == "2019-01-11T06:00:00+00:00"
async def test_simple_before_after_does_not_loop_utc_fire_at_before(hass):
"""Test simple before after."""
hass.config.time_zone = "UTC"
dt_util.set_default_time_zone(dt_util.UTC)
test_time = datetime(2019, 1, 11, 6, 0, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{
"platform": "tod",
"name": "Night",
"before": "06:00",
"after": "22:00",
}
]
}
with patch(
"homeassistant.components.tod.binary_sensor.dt_util.utcnow",
return_value=test_time,
):
await async_setup_component(hass, "binary_sensor", config)
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.night")
assert state.state == STATE_OFF
assert state.attributes["after"] == "2019-01-11T22:00:00+00:00"
assert state.attributes["before"] == "2019-01-12T06:00:00+00:00"
assert state.attributes["next_update"] == "2019-01-11T22:00:00+00:00"
async def test_simple_before_after_does_not_loop_utc_fire_at_after(hass):
"""Test simple before after."""
hass.config.time_zone = "UTC"
dt_util.set_default_time_zone(dt_util.UTC)
test_time = datetime(2019, 1, 10, 22, 0, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{
"platform": "tod",
"name": "Night",
"before": "06:00",
"after": "22:00",
}
]
}
with patch(
"homeassistant.components.tod.binary_sensor.dt_util.utcnow",
return_value=test_time,
):
await async_setup_component(hass, "binary_sensor", config)
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.night")
assert state.state == STATE_ON
assert state.attributes["after"] == "2019-01-10T22:00:00+00:00"
assert state.attributes["before"] == "2019-01-11T06:00:00+00:00"
assert state.attributes["next_update"] == "2019-01-11T06:00:00+00:00"
async def test_simple_before_after_does_not_loop_utc_both_before_now(hass):
"""Test simple before after."""
hass.config.time_zone = "UTC"
dt_util.set_default_time_zone(dt_util.UTC)
test_time = datetime(2019, 1, 10, 22, 0, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{
"platform": "tod",
"name": "Morning",
"before": "08:00",
"after": "00:00",
}
]
}
with patch(
"homeassistant.components.tod.binary_sensor.dt_util.utcnow",
return_value=test_time,
):
await async_setup_component(hass, "binary_sensor", config)
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.morning")
assert state.state == STATE_OFF
assert state.attributes["after"] == "2019-01-11T00:00:00+00:00"
assert state.attributes["before"] == "2019-01-11T08:00:00+00:00"
assert state.attributes["next_update"] == "2019-01-11T00:00:00+00:00"
async def test_simple_before_after_does_not_loop_berlin_not_in_range(hass):
"""Test simple before after."""
hass.config.time_zone = "Europe/Berlin"
dt_util.set_default_time_zone(dt_util.get_time_zone("Europe/Berlin"))
test_time = datetime(2019, 1, 10, 18, 43, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{
"platform": "tod",
"name": "Dark",
"before": "06:00",
"after": "00:00",
}
]
}
with patch(
"homeassistant.components.tod.binary_sensor.dt_util.utcnow",
return_value=test_time,
):
await async_setup_component(hass, "binary_sensor", config)
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.dark")
assert state.state == STATE_OFF
assert state.attributes["after"] == "2019-01-11T00:00:00+01:00"
assert state.attributes["before"] == "2019-01-11T06:00:00+01:00"
assert state.attributes["next_update"] == "2019-01-11T00:00:00+01:00"
async def test_simple_before_after_does_not_loop_berlin_in_range(hass):
"""Test simple before after."""
hass.config.time_zone = "Europe/Berlin"
dt_util.set_default_time_zone(dt_util.get_time_zone("Europe/Berlin"))
test_time = datetime(2019, 1, 10, 23, 43, 0, tzinfo=dt_util.UTC)
config = {
"binary_sensor": [
{
"platform": "tod",
"name": "Dark",
"before": "06:00",
"after": "00:00",
}
]
}
with patch(
"homeassistant.components.tod.binary_sensor.dt_util.utcnow",
return_value=test_time,
):
await async_setup_component(hass, "binary_sensor", config)
await hass.async_block_till_done()
state = hass.states.get("binary_sensor.dark")
assert state.state == STATE_ON
assert state.attributes["after"] == "2019-01-11T00:00:00+01:00"
assert state.attributes["before"] == "2019-01-11T06:00:00+01:00"
assert state.attributes["next_update"] == "2019-01-11T06:00:00+01:00"