Skip to content

Commit 0a9509e

Browse files
authored
Merge pull request #18 from wbyoung/fix-notification-with-led-override-dismissal
Fix dismissal of notifications with customizations
2 parents dd0c18f + 7a90dbc commit 0a9509e

File tree

7 files changed

+69
-21
lines changed

7 files changed

+69
-21
lines changed

custom_components/lampie/orchestrator.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ async def override_switch(
403403
switch_id,
404404
led_config_source=led_config_source,
405405
led_config=led_config,
406-
exclude={LEDConfigSourceType.SERVICE} if is_reset else set(),
406+
exclude={LEDConfigSourceType.OVERRIDE} if is_reset else set(),
407407
log_context="override-switch",
408408
)
409409

@@ -462,8 +462,8 @@ async def _switch_apply_notification_or_override(
462462

463463
if (
464464
from_state.led_config_source
465-
and from_state.led_config_source.type == LEDConfigSourceType.SERVICE
466-
and LEDConfigSourceType.SERVICE not in exclude
465+
and from_state.led_config_source.type == LEDConfigSourceType.OVERRIDE
466+
and LEDConfigSourceType.OVERRIDE not in exclude
467467
):
468468
led_config_source = from_state.led_config_source
469469
led_config = from_state.led_config
@@ -869,7 +869,7 @@ async def _handle_zha_event(self, event: Event[ZHAEventData]) -> None:
869869
elif all_clear:
870870
await self._switch_apply_notification_or_override(
871871
switch_id,
872-
exclude={LEDConfigSourceType.SERVICE},
872+
exclude={LEDConfigSourceType.OVERRIDE},
873873
dismissal_command=command,
874874
via_switch_firmware=via_switch_firmware,
875875
log_context=f"dismissed via {switch_id}",
@@ -966,7 +966,7 @@ async def _async_handle_switch_override_expired(
966966
dismiss=partial(
967967
self._switch_apply_notification_or_override,
968968
switch_id,
969-
exclude={LEDConfigSourceType.SERVICE},
969+
exclude={LEDConfigSourceType.OVERRIDE},
970970
log_context=f"override expired for {switch_id}",
971971
),
972972
handle_expired=partial(

custom_components/lampie/services.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ async def _activate(
7272
slugs: list[str] = call.data[ATTR_NOTIFICATION]
7373
led_config: tuple[LEDConfig, ...] | None = call.data.get(ATTR_LED_CONFIG)
7474
led_config_source = (
75-
LEDConfigSource(f"{','.join(slugs)}[custom]", LEDConfigSourceType.SERVICE)
75+
LEDConfigSource(f"{','.join(slugs)}[custom]", LEDConfigSourceType.NOTIFICATION)
7676
if led_config is not None
7777
else None
7878
)
@@ -105,7 +105,7 @@ async def _override(
105105
name: str = call.data.get(ATTR_NAME) or f"{DOMAIN}.{SERVICE_NAME_OVERRIDE}"
106106
switch_ids: list[str] = call.data[ATTR_ENTITY_ID]
107107
led_config: tuple[LEDConfig, ...] | None = call.data[ATTR_LED_CONFIG]
108-
led_config_source = LEDConfigSource(name, LEDConfigSourceType.SERVICE)
108+
led_config_source = LEDConfigSource(name, LEDConfigSourceType.OVERRIDE)
109109

110110
if led_config is None: # none indicates a reset
111111
led_config_source = LEDConfigSource(None)

custom_components/lampie/types.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from dataclasses import dataclass, field
88
import datetime as dt
99
from enum import Enum, IntEnum, StrEnum, auto
10+
import re
1011
from typing import TYPE_CHECKING, Any, NotRequired, Self, TypedDict
1112

1213
from homeassistant.config_entries import ConfigEntry
@@ -30,6 +31,8 @@
3031
from .coordinator import LampieUpdateCoordinator
3132
from .orchestrator import LampieOrchestrator
3233

34+
_SLUG_TAG_SUFFIX = re.compile(r"\[[^\]]+\]$")
35+
3336
type Slug = str
3437
type DeviceId = str
3538
type EntityId = str
@@ -182,7 +185,7 @@ class LEDConfigSourceType(StrEnum):
182185
"""LED configuration source type."""
183186

184187
NOTIFICATION = auto()
185-
SERVICE = auto()
188+
OVERRIDE = auto()
186189

187190

188191
@dataclass(frozen=True)
@@ -196,7 +199,25 @@ def __str__(self) -> str:
196199
return self.type.name.lower() + (f":{self.value}" if self.value else "")
197200

198201
def is_for_notification(self, slug: str) -> bool:
199-
return self.type == LEDConfigSourceType.NOTIFICATION and self.value == slug
202+
"""Checks if a source is for a notification slug.
203+
204+
The following would result in `True` for `doors_open`:
205+
206+
LEDConfigSource("doors_open")
207+
LEDConfigSource("doors_open,windows_open[custom]")
208+
209+
While these would be `False`:
210+
211+
LEDConfigSource("lampie.override", LEDConfigSourceType.OVERRIDE)
212+
LEDConfigSource("doors_open", LEDConfigSourceType.OVERRIDE)
213+
214+
Returns:
215+
True when this is for the given slug.
216+
"""
217+
return (
218+
self.type == LEDConfigSourceType.NOTIFICATION
219+
and slug in _SLUG_TAG_SUFFIX.sub("", self.value or "").split(",")
220+
)
200221

201222
def to_dict(self) -> dict[str, Any]:
202223
return {
@@ -206,9 +227,12 @@ def to_dict(self) -> dict[str, Any]:
206227

207228
@classmethod
208229
def from_dict(cls, data: dict[str, Any]) -> Self:
230+
type_name_migration_mapping = {"service": "override"}
231+
type_name = type_name_migration_mapping.get(data[ATTR_TYPE], data[ATTR_TYPE])
232+
209233
return cls(
210234
value=data[ATTR_VALUE],
211-
type=getattr(LEDConfigSourceType, data[ATTR_TYPE].upper()),
235+
type=getattr(LEDConfigSourceType, type_name.upper()),
212236
)
213237

214238

tests/snapshots/test_scenarios.ambr

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@
6565
),
6666
])
6767
# ---
68+
# name: test_dismissal_from_switch[aux_double_press_with_notification_activation_customizing_leds][service_calls]
69+
list([
70+
])
71+
# ---
6872
# name: test_dismissal_from_switch[aux_double_press_with_service_override][service_calls]
6973
list([
7074
])
@@ -183,6 +187,10 @@
183187
),
184188
])
185189
# ---
190+
# name: test_dismissal_from_switch[config_double_press_with_notification_activation_customizing_leds][service_calls]
191+
list([
192+
])
193+
# ---
186194
# name: test_dismissal_from_switch[config_double_press_with_service_override][service_calls]
187195
list([
188196
])
@@ -994,7 +1002,7 @@
9941002
}),
9951003
),
9961004
'led_config_source': dict({
997-
'type': <LEDConfigSourceType.SERVICE: 'service'>,
1005+
'type': <LEDConfigSourceType.OVERRIDE: 'override'>,
9981006
'value': 'lampie.override',
9991007
}),
10001008
'local_protection_id': 'switch.kitchen_local_protection',
@@ -3912,7 +3920,7 @@
39123920
}),
39133921
),
39143922
'led_config_source': dict({
3915-
'type': <LEDConfigSourceType.SERVICE: 'service'>,
3923+
'type': <LEDConfigSourceType.OVERRIDE: 'override'>,
39163924
'value': 'lampie.override',
39173925
}),
39183926
'local_protection_id': 'switch.kitchen_local_protection',
@@ -4067,7 +4075,7 @@
40674075
}),
40684076
),
40694077
'led_config_source': dict({
4070-
'type': <LEDConfigSourceType.SERVICE: 'service'>,
4078+
'type': <LEDConfigSourceType.OVERRIDE: 'override'>,
40714079
'value': 'lampie.override',
40724080
}),
40734081
'local_protection_id': 'switch.kitchen_local_protection',
@@ -4408,7 +4416,7 @@
44084416
}),
44094417
),
44104418
'led_config_source': dict({
4411-
'type': <LEDConfigSourceType.SERVICE: 'service'>,
4419+
'type': <LEDConfigSourceType.OVERRIDE: 'override'>,
44124420
'value': 'customized_name',
44134421
}),
44144422
'local_protection_id': 'switch.kitchen_local_protection',
@@ -4880,7 +4888,7 @@
48804888
}),
48814889
),
48824890
'led_config_source': dict({
4883-
'type': <LEDConfigSourceType.SERVICE: 'service'>,
4891+
'type': <LEDConfigSourceType.OVERRIDE: 'override'>,
48844892
'value': 'lampie.override',
48854893
}),
48864894
'local_protection_id': 'switch.entryway_local_protection',
@@ -5941,7 +5949,7 @@
59415949
}),
59425950
),
59435951
'led_config_source': dict({
5944-
'type': <LEDConfigSourceType.SERVICE: 'service'>,
5952+
'type': <LEDConfigSourceType.OVERRIDE: 'override'>,
59455953
'value': 'lampie.override',
59465954
}),
59475955
'local_protection_id': 'switch.kitchen_local_protection',

tests/snapshots/test_sensor.ambr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
}),
6262
]),
6363
'source': dict({
64-
'type': 'service',
64+
'type': 'override',
6565
'value': 'lampie.override',
6666
}),
6767
}),
@@ -228,7 +228,7 @@
228228
}),
229229
),
230230
'led_config_source': dict({
231-
'type': <LEDConfigSourceType.SERVICE: 'service'>,
231+
'type': <LEDConfigSourceType.OVERRIDE: 'override'>,
232232
'value': 'lampie.override',
233233
}),
234234
'local_protection_id': 'switch.kitchen_local_protection',

tests/test_scenarios.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1899,13 +1899,29 @@ async def test_toggle_notification_with_actions(
18991899
"expected_zha_calls": 0,
19001900
},
19011901
),
1902+
Scenario(
1903+
f"{prefix}_double_press_with_notification_activation_customizing_leds",
1904+
{
1905+
**_DISMISSAL_FROM_SWITCH_BASE,
1906+
"initial_leds_on": [True],
1907+
"initial_led_config_source": LEDConfigSource(
1908+
"doors_open,second_slug[custom]",
1909+
LEDConfigSourceType.NOTIFICATION,
1910+
),
1911+
"steps": [{"event": {"command": command}}],
1912+
"expected_notification_state": "off",
1913+
"expected_leds_on": [],
1914+
"expected_zha_calls": 0,
1915+
},
1916+
),
19021917
Scenario(
19031918
f"{prefix}_double_press_with_service_override",
19041919
{
19051920
**_DISMISSAL_FROM_SWITCH_BASE,
19061921
"initial_leds_on": [True],
19071922
"initial_led_config_source": LEDConfigSource(
1908-
f"{DOMAIN}.{SERVICE_NAME_OVERRIDE}", LEDConfigSourceType.SERVICE
1923+
f"{DOMAIN}.{SERVICE_NAME_OVERRIDE}",
1924+
LEDConfigSourceType.OVERRIDE,
19091925
),
19101926
"steps": [{"event": {"command": command}}],
19111927
"expected_notification_state": "on",

tests/test_sensor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ async def test_missing_switch_device(
242242
"switch_info": LampieSwitchInfo(
243243
led_config=(LEDConfig(Color.BLUE, effect=Effect.SOLID),),
244244
led_config_source=LEDConfigSource(
245-
"lampie.override", LEDConfigSourceType.SERVICE
245+
"lampie.override", LEDConfigSourceType.OVERRIDE
246246
),
247247
local_protection_id="unstored:entity_id",
248248
disable_clear_notification_id="unstored:entity_id",
@@ -258,7 +258,7 @@ async def test_missing_switch_device(
258258
}
259259
],
260260
"source": {
261-
"type": "service",
261+
"type": "override",
262262
"value": "lampie.override",
263263
},
264264
},

0 commit comments

Comments
 (0)