Conversation
bddfb48 to
7171b26
Compare
2a2f3af to
3f9bd9f
Compare
533bd75 to
41c3994
Compare
|
@rohankapoorcom @jncasey this is as far as I can take this without being able to test it against a system that's using Zigbee2MQTT. If/when either of you have time to review it and/or take it to the point of being usable, I think it would be much appreciated by anyone using Zigbee2MQTT. 🥂 |
bd4f127 to
a0cc274
Compare
0ce1d5c to
2a81862
Compare
This is currently untested.
|
There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. |
|
There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. |
|
There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. |
|
Quick testing, getting the following error in MQTT for a mmwave blue switch. There were a few issues I noticed right away:
Quick POC that worked for me, happy to make another PR to the z2m branch for it, is below: # types.py
class Effect(IntEnum):
_ignore_ = ("_Z2M_BY_EFFECT",)
OFF = 0
SOLID = 1
FAST_BLINK = 2
SLOW_BLINK = 3
PULSE = 4
CHASE = 5
OPEN_CLOSE = 6
SMALL_TO_BIG = 7
AURORA = 8
SLOW_FALLING = 9
MEDIUM_FALLING = 10
FAST_FALLING = 11
SLOW_RISING = 12
MEDIUM_RISING = 13
FAST_RISING = 14
MEDIUM_BLINK = 15
SLOW_CHASE = 16
FAST_CHASE = 17
FAST_SIREN = 18
SLOW_SIREN = 19
CLEAR = 255
_Z2M_BY_EFFECT: ClassVar[dict["Effect", str]]
@property
def zha(self) -> int:
return int(self)
@property
def z2m(self) -> str:
return type(self)._Z2M_BY_EFFECT[self]
Effect._Z2M_BY_EFFECT = {
Effect.OFF: "off",
Effect.SOLID: "solid",
Effect.FAST_BLINK: "fast_blink",
Effect.SLOW_BLINK: "slow_blink",
Effect.PULSE: "pulse",
Effect.CHASE: "chase",
Effect.OPEN_CLOSE: "open_close",
Effect.SMALL_TO_BIG: "small_to_big",
Effect.AURORA: "aurora",
Effect.SLOW_FALLING: "slow_falling",
Effect.MEDIUM_FALLING: "medium_falling",
Effect.FAST_FALLING: "fast_falling",
Effect.SLOW_RISING: "slow_rising",
Effect.MEDIUM_RISING: "medium_rising",
Effect.FAST_RISING: "fast_rising",
Effect.MEDIUM_BLINK: "medium_blink",
Effect.SLOW_CHASE: "slow_chase",
Effect.FAST_CHASE: "fast_chase",
Effect.FAST_SIREN: "fast_siren",
Effect.SLOW_SIREN: "slow_siren",
Effect.CLEAR: "clear_effect",
}# orchestration.py
def _switch_command_led_params(self, led: LEDConfig, switch_id: SwitchId) -> dict[str, Any]:
firmware_duration = (
self._firmware_duration(led.duration)
if self._any_has_expiration_messaging([switch_id])
else None
)
duration = (
255
if led.duration is None
or led.duration == ALREADY_EXPIRED
or firmware_duration is None
else firmware_duration
)
switch_info = self.switch_info(switch_id)
is_z2m = switch_info.integration == Integration.Z2M
base = {
("color" if is_z2m else "led_color"): int(led.color),
("effect" if is_z2m else "led_effect"): (led.effect.z2m if is_z2m else led.effect.zha),
("level" if is_z2m else "led_level"): int(led.brightness),
}
return base | {("duration" if is_z2m else "led_duration"): duration} |
|
Wow, thanks for getting and the great info. If you're up for putting in the work to open a PR against my branch, that would be most welcome! There's good test coverage in there, so if you get it working with tests covering the changes, we should be able to refactor/change things as needed to fit with how this will work for Z-Wave and Matter which I've already started on as well. If you're just up for testing, I'd welcome that as well. Let me know what your interest/availability is. |
|
I have some time tonight and this weekend where I can get it refactored into a PR and updating tests! |
|
@MrDaGree wonderful! Let me know if I can answer any questions. I'm really helpful excited to get this merge and allow more people to use it. |
|
@wbyoung - Im running into a weird issue I've noticed with the if (
(notification_complete := payload.get("notificationComplete"))
and (command := f"led_effect_complete_{notification_complete}")
and command in DISMISSAL_COMMANDS
):
await self._handle_generic_event(
command=command,
switch_id=switch_id,
integration=Integration.Z2M,
)Once
|
I'm guessing that ZHA works differently here, but there's really no payload to speak of—just the event being triggered. That event doesn't really come with the full state of things. It sounds like what you're saying is that Z2M keeps track of the state of the switch and sends the whole state in the event/update that we're registered for. Does that sound right? If so, we'll likely need to store the state of |
|
I can confirm that what you've described is how notificationComplete is processed in Z2M. |
This is helpful to know! I appreciate, though it seems a bit of an issue that it doesnt "clear" the next time you apply an LED effect |
We can maintain our own state, though. As long as we only react to the changes we see, it should function about the same. |
|
The issue revolves around notifications with a specific duration. If I have a 30s duration notification, at the end of that "ALL_LEDS" is set in the payload. If I set another 30s duration notification, the payload already has "ALL_LEDS" set so it doesnt change to then be able to react on and immediately "clears" on the lampie side of things despite the notification still running. This isnt an issue if I alternate between dismissing via the switch and then have a timed duration one. Scenario to help ensure I'm explaining well:
EDIT: I guess we could store the "state" of the switch when we start a notification like you previously said in Lampie itself, but it'd be nice if the |
I guess we could handle that in the Z2M converter, but it's a little bit weird since we'd basically be guessing at what point to reset the attribute since the device doesn't tell us that information. |
@rohankapoorcom would it be okay to clear it on any next change? It's a momentarily fired event, not something that's a persistent state. I'm guessing this just doesn't map well to the Z2M representation of things. @MrDaGree are we also saying that (outside of Lampie) we have a notification that clears with |
Do you know how the momentary clearing is handled on the ZHA side? We could try to implement it exactly the same way there. I assumed that the device would publish a "clearing" of it after some period of time but it does not. |
I don't know that I've dug far enough into it to know the exact answer, but can look more if need be. I know that ZHA publishes certain events to the HASS event bus with key |
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. |
Correct. I also wonder if it would make more sense for Lampie to send back clear, but clearing the LEDS also would run into the same as above as it wouldnt change the notificationComplete |
Another way—and this is what I was planning before @rohankapoorcom added support in the Z2M converters—is to just manage the notification durations entirely in the integration and not send them to the switch at all. But hopefully @rohankapoorcom has a solution in mind and can turn something around quickly enough to allow you to continue to move this forward, @MrDaGree. |
There's still some work to do on this:
Device Names and Identifiers
I got some great explanations on naming, topics, and identifiers.
Before this, in c2e9c1f, switches could be looked up by MQTT device ID or name (in case that's ever a useful idea to apply again).
Original problem description:
Obtaining Parameter Values
In c2e9c1f, I used the same strategy of locating related entities from the device. It turns out, though, that the 2x tap to dismiss notifications entity is disabled by default in the entity registry. The approach being implemented now is to request an update from MQTT when switches are added and process state updates for them.
Original problem description:
Prior Art & Documentation Resources
The following were suggested as reference points for implementation:
mqtt.publishmqtt.async_subscribeNotes
ZHA has some events that it can receive from the switches, namely
0x24which is forled_effect_complete. When this PR was first openened, that wasn't present in the Z2M docs nor the herdsman converters, but @rohankapoorcom added support for this in Koenkk/zigbee-herdsman-converters#9735.