Skip to content

feat(ha): treat notificationComplete as stateless event like action#31686

Open
rohankapoorcom wants to merge 3 commits intoKoenkk:devfrom
rohankapoorcom:feat/stateless-notification-complete
Open

feat(ha): treat notificationComplete as stateless event like action#31686
rohankapoorcom wants to merge 3 commits intoKoenkk:devfrom
rohankapoorcom:feat/stateless-notification-complete

Conversation

@rohankapoorcom
Copy link
Copy Markdown
Contributor

@rohankapoorcom rohankapoorcom commented Apr 11, 2026

Summary

Extend the Home Assistant extension so notificationComplete is handled like action: clear from cached state after publish, publish to a dedicated MQTT topic for device triggers, and run device trigger discovery.

Behavior

  • action: unchanged — clear only when legacyActionSensor is enabled.
  • notificationComplete: always cleared after publish so the last LED effect completion does not linger in state.
  • Both: with JSON output, values are republished to zigbee2mqtt/<device>/<key> and device trigger discovery runs.

Motivation

Supports Inovelli ledEffectComplete (from zigbee-herdsman-converters) as a one-off event without overloading the action property.

Related context:

I assumed—possibly incorrectly—that the switch was doing the same thing, broadcasting an event. Is the switch actually changing state? Does Zigbee (or Z2M) not have an event concept?

The switch is effectively broadcasting an event. I don't think Z2M has the concept of arbitrary event, only Actions are treated like events. We use the Actions concept already to send the multi tap scenes so I wouldn't want to overload that to send this over as well. Let me look at how it's implemented and see if we can extend that logic to send this as an event instead.

Implementation

  • Introduces STATELESS_EVENT_PROPERTIES (action, notificationComplete).
  • Skips undefined or empty string values to avoid re-entrant clears.

Made with Cursor

Extend Home Assistant extension handling so notificationComplete follows the
same pattern as action: clear from cached state after publish (always, unlike
action which clears only with legacyActionSensor), publish the value to a
dedicated MQTT topic for device triggers, and run device trigger discovery.

Adds STATELESS_EVENT_PROPERTIES to list event-like state keys; skip empty
values to avoid re-entrant clears.

Supports Inovelli ledEffectComplete (zigbee-herdsman-converters) without
overloading the action property.

Made-with: Cursor
@rohankapoorcom rohankapoorcom force-pushed the feat/stateless-notification-complete branch from 04ade77 to d68f93f Compare April 11, 2026 22:58
@rohankapoorcom rohankapoorcom changed the base branch from master to dev April 11, 2026 22:58
Add integration tests for STATELESS_EVENT_PROPERTIES: MQTT device trigger
discovery, dedicated topic, state clear on json output, and no device_automation
when output is attribute.

Made-with: Cursor
@Koenkk
Copy link
Copy Markdown
Owner

Koenkk commented Apr 13, 2026

I would propose to rename notificationComplete to action to keep it in line with all the other events.

@rohankapoorcom
Copy link
Copy Markdown
Contributor Author

The switches already send an action command. We've differentiated notificationComplete because it's the switch itself acknowledging that the notification is done vs the action being something that was performed on a switch (tapping or multi tapping on a button). I don't think it makes sense to try to conflate the two into a single action.

@Koenkk
Copy link
Copy Markdown
Owner

Koenkk commented Apr 13, 2026

What about action: notification_done? I really don't want to introduce more action like properties (because then more will come)

@rohankapoorcom
Copy link
Copy Markdown
Contributor Author

There's a bunch of different values though, not just one and we need to know which one is returned:

const LED_NOTIFICATION_TYPES: {[key: number]: string} = {
    0: "LED_1",
    1: "LED_2",
    2: "LED_3",
    3: "LED_4",
    4: "LED_5",
    5: "LED_6",
    6: "LED_7",
    16: "ALL_LEDS",
    "-1": "CONFIG_BUTTON_DOUBLE_PRESS",
};

See: https://github.com/Koenkk/zigbee-herdsman-converters/blob/c2ffd92daad72db1a8020391fd7f564de76824f9/src/lib/inovelli.ts#L815

@Nerivec
Copy link
Copy Markdown
Collaborator

Nerivec commented Apr 13, 2026

Agreed with the no-more-action-like props decision. It would too quickly become a nightmare for both dev maintenance and user usage patterns.
I haven't looked at the upstream code, but is publishing a "completion" event even necessary?

@wbyoung
Copy link
Copy Markdown

wbyoung commented Apr 14, 2026

I haven't looked at the upstream code, but is publishing a "completion" event even necessary?

I'm not 100% familiar with Z2M (I use ZHA), but yes, the switch in question broadcasts that the notification is dismissed through this event. And there are many possible values it passes along with it for combination(s) of LEDs that are no longer being used for the notification.

My understanding is that it'll be much easier to code this if the notificationComplete isn't "stuck" in a truthy state, and that's what the main issue is with how it's currently being delivered via Z2M.

Hopefully this helps and/or @rohankapoorcom or @MrDaGree could better clarify.

@rohankapoorcom
Copy link
Copy Markdown
Contributor Author

I haven't looked at the upstream code, but is publishing a "completion" event even necessary?

If your question is do we need to know whether the notification is complete, yes. @wbyoung made a notification manager for Inovelli switches. It needs to know which notifications that were triggered are still running and the only way to know that is to get the completion event.

If the question is do we need to clear the notification completion event, I believe so. The problem otherwise is that the state becomes "sticky" and the notification manager has no idea what it is referring to when the notification completion doesn't change. Here's an example workflow:

  • I set a notification for 10 seconds on LED 7.
  • After 10 seconds, the notification completion event triggers and now notificationComplete = "LED_7".
  • The notification manager detects the change and knows the notification has completed
  • I set another notification for 10 seconds on LED 7.
  • After 10 seconds, the notification completion event changes, but notificationComplete doesn't change. It's still set to notificationComplete = "LED_7"
  • The notification manager has no way to know the second notification has completed.

Please let me know if you can think of another way to handle this.

@Koenkk
Copy link
Copy Markdown
Owner

Koenkk commented Apr 14, 2026

Could this maybe be exposed as a binary which goes to true when running and false when getting a notificationComplete?

@wbyoung
Copy link
Copy Markdown

wbyoung commented Apr 15, 2026

Could this maybe be exposed as a binary which goes to true when running and false when getting a notificationComplete?

Probably not. The notification complete contains several possible payloads (for ALL_LEDS or LED_1-LED_7 getting completed).

@Koenkk
Copy link
Copy Markdown
Owner

Koenkk commented Apr 17, 2026

I don't see why that would expose blocking each led as a binary, in case notificationComplete: ALL_LEDS is send, all led binary exposes should go to false.

@rohankapoorcom
Copy link
Copy Markdown
Contributor Author

rohankapoorcom commented Apr 17, 2026

How would a binary help here? How do they get "reset" and set back to false? Don't we still have the same problem?

  • I set a notification for 10 seconds on LED 7.
  • After 10 seconds, the notification completion event triggers and now notificationCompleteLed7 = true.
  • The notification manager detects the change and knows the notification has completed
  • I set another notification for 10 seconds on LED 7.
  • After 10 seconds, the notification completion event changes, but notificationComplete doesn't change. It's still set to notificationCompleteLed7 = true
  • The notification manager has no way to know the second notification has completed.

@Koenkk
Copy link
Copy Markdown
Owner

Koenkk commented Apr 21, 2026

If I understand correctly, this will give the following behaviour:

Start situation: led_7 = OFF

I set a notification for 10 seconds on LED 7.

State change: led_7 = ON

After 10 seconds, the notification completion event triggers and now notificationCompleteLed7 = true.

State change: led_7 = OFF

The notification manager detects the change and knows the notification has completed

Can detect the change because led_7 goes from ON to OFF

I set another notification for 10 seconds on LED 7.

State change: led_7 = ON

After 10 seconds, the notification completion event changes, but notificationComplete doesn't change. It's still set to notificationCompleteLed7 = true
The notification manager has no way to know the second notification has completed.

State change: led_7 = ON

Would that solve the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants