Fix loop in tod binary sensor (#51491)

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
pull/51593/head
J. Nick Koston 2021-06-07 08:21:10 -10:00 committed by GitHub
parent a383198c0c
commit a3146ad150
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 237 additions and 4 deletions

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

@ -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"