zwave-js / zwave-js-ui

Full featured Z-Wave Control Panel UI and MQTT gateway. Built using Nodejs, and Vue/Vuetify
https://zwave-js.github.io/zwave-js-ui
MIT License
970 stars 204 forks source link

[question] MQTT topics for Configuration of devices, trouble matching values to topics #196

Closed LordMike closed 3 years ago

LordMike commented 3 years ago

Hi,

Note: Json views are from zwave2mqtt, not zwavejs2mqtt.

I'm trying to make sense of the topics available for configurations of devices. I sort of expected the same property/value setup in the 112 CC, as with other values. Below, I've looked at one specific node to match up its configuration from the getNodes json, and the topics it presents.

Config 22, some kind of integer

From GetNodes: image

From MQTT: image

In this one, we can't find the value 1107296257 anywhere in the shown topics. In fact, the only place 1107296257 appears on my MQTT server, is with the old Z2M topics. Contrary, I can't find the value 33 in the json.

I think these keys, 2130706432 etc., are "Value Ids".. Right?.. How do I map that? :) I half expected those to be present in the json document.

Setting 32, a list of sorts

From getNodes: image

In MQTT: image

In this, the value is noted as being 3 in the MQTT topics, which for some reason isn't as detailed as the 22-setting. There's just one topic here. From the JSON, the value is a string - which is odd, as I read somewhere that list values would now be indices - which I'd put as index 2 (0-indexed).

Are these list values 1-indexed ?

LordMike commented 3 years ago

I may also have misunderstood something, as the topics indicate endpoint 0, while the json indicates endpoint 1..

Did I mess up?

robertsLando commented 3 years ago

@LordMike I think that config should be splitteed using partial parameters: https://zwave-js.github.io/node-zwave-js/#/development/config-files?id=partial-parameters

Also most screenshots seems about the old Z2M right? the format is not from zwavejs2mqtt. Now values are mapped as an array of object {text: ..., value: ...}

In this one, we can't find the value 1107296257 anywhere in the shown topics. In fact, the only place 1107296257 appears on my MQTT server, is with the old Z2M topics. Contrary, I can't find the value 33 in the json.

The things are different now, it depends on configuration file of that device. Could you show it's deviceId?

cc @AlCalzone

AlCalzone commented 3 years ago

The property in the first two screenshots is an example of partial parameters. It is cumbersome for users to calculate the value whenever they need to change parts of it. Hell, there are even tools out there which shouldn't need to exist: https://nathanfiscus.github.io/inovelli-notification-calc/

So what you're seeing in zwave-js is 4 values instead of a single one, each targeting a single byte of the combined param: 255 = 0x000000ff 65280 = 0x0000ff00 and so on ==> https://github.com/zwave-js/node-zwave-js/blob/9fa9a67cd52321de801efdb4d324dfe023759e86/packages/config/config/devices/0x0371/zw164.json#L1590-L1633 They get combined behind the scenes to the original value the device expects.

The params 32 and following look like they should also be split into partial parameters: https://github.com/zwave-js/node-zwave-js/blob/9fa9a67cd52321de801efdb4d324dfe023759e86/packages/config/config/devices/0x0371/zw164.json#L36-L299 This will leave you with a ton of params, but at least they are easier to understand than "Option 1, 2, 3...".

LordMike commented 3 years ago

Also most screenshots seems about the old Z2M right? the format is not from zwavejs2mqtt. Now values are mapped as an array of object {text: ..., value: ...}

Nope. This is zwavejs2mqtt. The zwave2mqtt topics are collapsed and not shown. I have not sent Z2M topics to the zwavejs2mqtt prefix, so what we're seeing should be the current layout.

EDIT: You are correct @robertsLando. I went back and checked my command. I dumped getNodes from zwave2mqtt. Disregard the JSON stuff.

LordMike commented 3 years ago

So what you're seeing in zwave-js is 4 values instead of a single one, each targeting a single byte of the combined param: 255 = 0x000000ff 65280 = 0x0000ff00 and so on ==> https://github.com/zwave-js/node-zwave-js/blob/9fa9a67cd52321de801efdb4d324dfe023759e86/packages/config/config/devices/0x0371/zw164.json#L1590-L1633

In these instances, zwavejs2mqtt could push both the partial values, and the actual value. And then handle the subsequent set's.

Is it possible to set the whole value in one go, in zwavejs?

robertsLando commented 3 years ago

From GetNodes:

If you check the valueId object it has node_id and some other props in snake case. Now all props are in camel case

LordMike commented 3 years ago

From GetNodes:

If you check the valueId object it has node_id and some other props in snake case. Now all props are in camel case

Yeap. I found that the getNodes dump actually was from Z2M.

robertsLando commented 3 years ago

Yeap. I found that the getNodes dump actually was from Z2M.

Could you update your question by checking the dumps coming from zwavejs2mqtt so?

AlCalzone commented 3 years ago

In these instances, zwavejs2mqtt could push both the partial values, and the actual value

I don't follow. What do you mean?

Is it possible to set the whole value in one go, in zwavejs?

Yes, but not by setting a value. You'd have to go through the commandClasses API and provide the valueSize yourself. I don't think zwavejs2mqtt has a way to do that yet?

await node.commandClasses.Configuration.set(32 /* param # */, 1234567 /* value */, 4 /* value size */);

We can think about changing this, but I need to understand the use case first. What's the reason you want to go through the original value instead of the partial ones?

LordMike commented 3 years ago

It's my impression that a value in Z-wave, like the configurations, actually represent one value. So for what we've seen, it's an integer (4 bytes) with 4 distinct meanings for each byte. So you decide to split up the integer to make it easier for users like me and zwavejs2mqtt - cool.

But. It's always my goal to have as little chatter as possible over a low-bandwith channel like z-wave (I aim for minimalism in many projects to avoid issues in the future), which always means sending as little data as possible.

From what I gather, setting these 4 values will send 4 messages over z-wave, each with ... one byte, or all four bytes in them?.. If it's all four bytes at a time, with just the newly set byte changed, then you have to wait for an ack before sending the next value, in order to include the previously set one - right?.. If you didn't you'd risk concurrency issues, if messages are out of order.. and so on.. :|

In any case, if I'm configuring a device to some template I have, I will be configuring each parameter to some value.. In these cases, that would then be up to 4x the amount of messages.

Finally. If these "partial" values are the way to go, everyone does it, it's always been the way to do it .. etc, then I'm not here to change anything.. :) But I don't think that a gateway library like zwavejs should encourage users into sending more messages than needed. (Other issues I've created also hint to this effect, like RGB in one message, or removing associations from the lifeline group).

AlCalzone commented 3 years ago

Okay that is clear to me. Bulk-setting configuration params in general isn't really compatible with the setValue API since that is aimed at simple/primitive values. I guess this needs to be split into two issues:

  1. UI/MQTT: Provide API to perform bulk-setting config params
  2. node-zwave-js: Handle partial params when bulk-setting config params.
LordMike commented 3 years ago

I'm not familiar enough with the z-wave protocol to know how setting values work.. Do these partial values come from z-wave (ie. "set param 22[0xff]" or your zwavejs?

While doing log captures for another issue, I'm seeing a breakdown of the configuration CC's:

20:15:49.526 DRIVER « [Node 021] [REQ] [ApplicationCommand]
                      └─[ConfigurationCCReport]
                          parameter #: 252
                          value size:  1
                          value:       0

So I'm guessing the abstraction to "partial values" occurs in zwavejs?

AlCalzone commented 3 years ago

So I'm guessing the abstraction to "partial values" occurs in zwavejs?

Correct. The necessity comes from device manufacturers creating these human-incompatible compound values that don't make sense. zwave-js splits and combines partial params behind the scenes.

LordMike commented 3 years ago

I would argue they really do make sense. At this level, this is exactly what they can do to cram as much functionality into an embedded device as they can. :)

All the parts make sense to me now, so I'm covered. This issue is also off-topic, and I found that the original question was because I used old configs to match up with. Newer configs fit the topics I see.

So I'm closing this now. The idea of introducing "bulk" sets (which are actually "set"'s, where the current are "user-friendly set"'s) is another topic :)