feat: Poll manuSpecificPhilips2 for Hue lights#32078
Conversation
|
Cool! Can you explain the logic behind polling a little bit, to make sure I understand it? Is it like this? |
|
@andrei-lazarov Correct. Same thing for device-to-device bindings. 😊 |
@Koenkk I was about to do that, but wouldn't it be better to confirm before polling that the |
Updated type assertions for readCluster and readAttrs.
|
I've been thinking: Why not use the state of the Hue Native Control device option to dynamically override the poll target? @Nerivec Would that be doable with existing APIs and also actually be testable? |
|
Not sure how this was implemented. I assume there's a zigbee2mqtt/lib/extension/configure.ts Line 70 in cfc7ab8 |
|
@Nerivec Would you mind sanity checking my test harness? 😊 I think the issue was that |
|
@andrei-lazarov Would you be able to test this PR on your end? |
|
Actually, looking at the philips branch in the context of the whole |
|
@Nerivec Edit: Actually, triggering the Hue branch for every poll is correct. We're simply swapping out the cluster/attribute used during polling to provide more accurate/efficient state updates for supported Hue lights with |
|
I think we're switching to the Hue-specific cluster as soon as possible without having to refactor the entire Also, lots of typos in my commit messages today, huh? 😅 |
|
I thought the intent was to make one request instead of many? This ends up same as before, just a different cluster used, doesn't it? Technically less attributes (bit smaller payload), but same number of requests. @Koenkk isn't there a way to keep this custom stuff in ZHC? Poll logic override like custom time read or something? |
Yes, just a different cluster (for now). See above. 😅
AFAIK no... But would be a much clearer approach tho. |
|
@Nerivec Let's put this PR on hold until we have a more maintainable way of implementing such overrides from ZHC. Cramming manufacturer-specific code into ZH/Z2M isn't the way to go. 😊 |
|
About the revert, that wasn't strictly related to this PR, just a way to avoid executing the logic if we're not going to enter the About moving this to ZHC, I think we can just introduce something on the definition, since this used by Z2M, not ZH, we don't have to introduce anything at ZH level. zigbee2mqtt/lib/extension/onEvent.ts Line 85 in cfc7ab8 onBindPoll?: (device: Zh.Device, endpoint: Zh.Endpoint) => Promise<void>Note: just a quick overview, need to dig into the requirements from Z2M, and the possible needs from ZHC. |
Thanks for clarifying!
Sounds like an elegant solution to me! 💅
I assume the proposed |
Then I would propose to add a "whatToPoll" function in index.ts which returns the attributes to read for a given command. |
|
@Nerivec Ok, so we now got a rough idea of how to implement this.
But how do we go from here? |
You mean moving the whole POLL_ON_MESSAGE? I was thinking having it as a possible override mechanism that definitions can declare. We need a way to declare, "this is the default" (current), and "this is what this device should do" (intent of this PR). |
Leaving it up to individual definitions doesn't make much sense, IMHO, because that |
|
Just would need to add the entry in the same modern extend as the |
Good point. |
|
Depends if we want something a bit more flexible (possible future ZHC uses). A function that takes device+endpoint and does what it needs to do instead of the default in Z2M is more future-proof (avoids refactoring 😁). |
A more general purpose override function sounds quite useful, but implementation will be a bit more tricky. 😅 |
|
I had an idea that I want to share, a bit off-topic from the Hue cluster.
Sorry, will do! |
@andrei-lazarov Oh, that's an interesting idea! Having less hardcoded stuff around is always good.
No need to rush. 😊 A general purpose override function that allows ZHC to alter device-specific behavior in Z2M would be the most flexible solution. However, it's not yet clear how exactly such overrides would be called from Z2M extensions. I'm in favor of a compromise that moves the override into ZHC but is limited in scope, i.e. not general purpose. |
The same as onEvent, like I mentioned above. Can just call anything from the definition, with whatever args are needed. // in ZHC definition type
onBindPoll?: (device: Zh.Device, toPoll: Set<Zh.Endpoint>: existingPollers: Map<string, () => void>) => Promise<void>
// example use in ZHC definition
...
onBindPoll: (device, toPoll, existingPollers) => {
for (const endpoint of toPoll) {
const key = ...;
let poller = existingPollers.get(key);
if (!poller) {
poller = debounce(async () => {
try {
await endpoint.read<"manuSpecificPhilips2", ManuSpecificPhilips2>("manuSpecificPhilips2", ["state"]);
} catch (error) {
logger.error(`Failed to poll ${readAttrs} from ${device.ieeeAddr} (${(error as Error).message})`);
}
}, 1000);
existingPollers.set(key, poller);
}
poller();
}
}
...// in Z2M
#bindPollers = new Map<string, () => void>(); // replaces `bindDebouncers`
if (data.device.definition?.onBindPoll) {
const toPoll = this.#getEndpointsToPoll(data.device.zh.endpoints, data.groupID);
await data.device.definition.onBindPoll(device, toPoll, this.#bindPollers);
} else {
// default Z2M logic
}For the real thing, need to pass some of |
|
Quite involved for such a "simple" enhancement. 😅 I'm a little bit concerned about the potential overhead caused by the back and forth (ZHC/Z2M) when compared to a static But if everything checks out on that end, I can certainly give it a shot. |
|
It's only a function call on the definition, if defined, barely any impact at all. @Koenkk thoughts on #32078 (comment) ? Seems a lot of stuff in POLL_ON_MESSAGE is manuf-spe/custom clusters, might be worth moving some of that to ZHC as well, better typing & co (can do it over time, like we did custom clusters). |
As mentioned in Koenkk/zigbee-herdsman-converters#12256 and #31960, Z2M automatically reads (i.e. polls) specific attributes (brightness, state, etc.) when a device is being controlled via Zigbee Bindings.
Instead of reading only a limited amount of standard attributes, the Philips Hue-exclusive
manuSpecificPhilips2cluster can be used to reduce airtime and improve responsiveness by fetching the complete device state with a single command.To my knowledge, the only Hue device that doesn't feature this cluster is the Hue Smart Plug, but it is capable of reporting anyways.
cc. @andrei-lazarov