fix: retain terminal zero during interception

This commit is contained in:
Bas Nijholt 2026-09-06 09:44:44 -07:00
commit cfe778cef8
3 changed files with 81 additions and 0 deletions

View file

@ -295,6 +295,9 @@ def prepare_adaptation_data(
for key in (ATTR_ENTITY_ID, ATTR_BRIGHTNESS, ATTR_TRANSITION)
if key in service_data
}
# The current state can retain brightness zero while the light is off.
# Keep this command available to intercept a new bare turn-on.
filter_by_state = False
service_datas = _split_service_call_data(service_data) if split else [service_data]
service_datas_length = len(service_datas)

View file

@ -484,6 +484,30 @@ async def test_prepare_zero_after_shared_brightness_was_applied(hass_states_mock
assert data.attributes is LightControlAttributes.NONE
async def test_prepare_zero_is_not_filtered_for_off_light(hass_states_mock):
"""A retained zero remains available to intercept a bare turn-on."""
hass_states_mock.states.get.return_value = Mock(attributes={ATTR_BRIGHTNESS: 0})
data = prepare_adaptation_data(
hass_states_mock,
"light.test",
Context(id="test-id"),
1,
0.2,
{
ATTR_ENTITY_ID: "light.test",
ATTR_BRIGHTNESS: 0,
ATTR_COLOR_TEMP_KELVIN: 4000,
},
split=True,
filter_by_state=True,
force=False,
)
assert [item async for item in data.service_call_datas] == [
{ATTR_ENTITY_ID: "light.test", ATTR_BRIGHTNESS: 0},
]
@pytest.fixture(name="hass_states_mock")
def fixture_hass_states_mock():
"""Mocks a HA state machine which returns a mock state."""

View file

@ -5213,3 +5213,57 @@ async def test_zero_sleep_multi_light_intercept_has_no_follow_up(hass):
]
assert payloads == [{ATTR_ENTITY_ID: managed}]
assert all(hass.states.get(entity_id).state == STATE_OFF for entity_id in managed)
@pytest.mark.parametrize("split", [False, True])
@pytest.mark.parametrize("skip_redundant", [False, True])
async def test_zero_sleep_intercepts_off_light_reporting_zero(
hass,
split,
skip_redundant,
):
"""A retained zero remains an off command during intercepted turn-on."""
switch, (light, *_) = await setup_lights_and_switch(
hass,
{
CONF_INTERCEPT: True,
CONF_SEPARATE_TURN_ON_COMMANDS: split,
CONF_SKIP_REDUNDANT_COMMANDS: skip_redundant,
CONF_SLEEP_BRIGHTNESS: 0,
},
)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: light.entity_id},
blocking=True,
)
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: switch.sleep_mode_switch.entity_id},
blocking=True,
)
await _finish_zero_sleep_adaptations(hass, switch)
attributes = dict(hass.states.get(light.entity_id).attributes)
attributes[ATTR_BRIGHTNESS] = 0
set_light_brightness(light, 0)
hass.states.async_set(light.entity_id, STATE_OFF, attributes)
await hass.async_block_till_done()
events = []
remove_listener = hass.bus.async_listen(EVENT_CALL_SERVICE, events.append)
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: light.entity_id},
blocking=True,
)
await _finish_zero_sleep_adaptations(hass, switch)
remove_listener()
assert _light_turn_on_payloads(events, light.entity_id) == [
{ATTR_ENTITY_ID: light.entity_id},
]
assert hass.states.get(light.entity_id).state == STATE_OFF