Is there an easy way of getting the Z-Wave command class version? I know I can get it by issuing a Z-Wave versionCommandClassGet, but it seems this is something that the Z-Wave stack should have learned when the device was paired (like it learns the classes themselves), so I'm wondering if there is a simple function -- e.g., one where you just pass the command class number and it returns the maximum supported version number.
It seems this should exist and would be straightforward to implement in the platform (particularly as command classes can only change if the device firmware changed, so it would only be necessary to check after a firmware update and maybe through a repair function), but I don't know if there is a function to get at this within a driver.
In the same vein though, you would also only have to do the command class report one time (in configure?) and then store the results in a state for future use.
If the existing drivers store the version information, I'm not aware of that. I've certainly never seen any evidence that it is stored in the system anywhere.
Check out the "Basic Z-Wave Tool" provided by the Hubitat team.
If you switch your driver over to it and run the getCommandClassReport command you will get a list off all the command classes and their version in the logs. I guess you can also look at the code and see how they pull the information if needed.
I could see where this would be helpful.. Might need to add this functionality..
Thanks - Yes, I"m aware of that.
To clarify: I'm looking for an easy way to get the command class during the execution of a driver so that the driver can adapt and use more advanced features where available. I know I can issue asynchronous calls to the device to find that out; it seems it should be much easier than this - I was assuming that the platform / Z-wave stack would find this out when it initially adds a device (or updates device firmware as the classes can change on a firmware update) and it would be much easier if there were a call to get the class version information from the platform. This seems like an area where this information could be easily gathered at the platform level and available to the driver by a simple call (e.g., a "getZwaveClassVersion(class#)) call. That is, this seems to be a function that is common enough that it should be abstracted by the platform and since the information doesn't change it can be gathered at startup / pairing / firmware update so there is less driver-execution-time work / management (and less network traffic while the system is in-use).
Maybe this just doesn't exist yet.
That would be awesome. I think it would make it much easier to use this information without coding errors.
I also have a proposal for better management of Z-wave Parameters on a platform level. I'd like to send that to you too. I'll write that up today. I have some ideas that I think would greatly simplify driver writing and be easy to implement.
As long as it is done on the platform level, and not the driver level, that would be fine. I don't think it's reasonable to have every user go back and modify their drivers to add this functionality.
Needing to know the version of command class is simply not something that is needed very often. It is only useful for generic drivers that support a wide range of devices, where needing a higher level command class version is actually value added - which it usually is not.
Note that I didn't say never. Jvm may have a perfectly valid use case. Although even then I don't see why it can't just be polled once in configure and stored in a state variable.
Exactly. What I was envisioning is that all the existing functionality would stay. The one change is that, on pairing and after a firmware update, the platform would query the command class version for every supported command class. There would be a new function getCommandClassVersion that is passed the command class number and immediately returns the value of the highest supported class (it was pre-gathered, so this is not asynchronous). The existing ZWave functions remain -- so someone could still "manually" query for the command class -- but they wouldn't have to. There could also be a boolean version ( supportsCommandClassVersiont(class#, version#) which returns true or false)
That seems like a lot of platform work for something that you can do today in the driver one time, and store the results in a state variable.
But whatever. That's Hubitat's call, not mine.
I was seeing this as a little platform work which saves much more driver work. The point is that if you do it in the driver, every driver writer has to write the code to do the queries and, given the responses are asynchronous, has to deal with it on a asynchronous basis with data arriving at unpredictable times. Repeat this for dozens if not hundreds of drivers, and that is huge. If its in the platform at pairing, its a simple loop (for every device, for every command class, get the version and store it in a groovy Map of class / version) and this occurs at a time when network traffic and processing isn't critical (so what if there is extra data gathered that doesn't get used or some extra network traffic during startup - it won't amount to much time or storage and reduces later traffic). The results are then available the moment the driver starts - no querying at initialization and waiting to figure out what to do - instead, class version can just be treated as any other static data. Seems far easier and less error prone from a driver development point.
Also, the state variable storage can be a problem (yes, manageable, but still easier if the programmer doesn't have to) - firmware updates can change the class version (though that's rare - I've only seen it when I updated some old dimmers one time) and that would be missed by the driver. Moving it to the platform allows this to be error proofed since the firmware updater can "know" to check.
Except dynamically polling the command class version is almost never actually needed. So "every driver writer" doesn't have to do this... Only ones that write multi-function, multi-device drivers. which is not very many by definition. If they are generic/multifunction then there should be very few of them - otherwise they are device specific...
The fact that people aren't doing this in drivers today manually (at least not in any wide spread use cases) backs up my statement that this is not needed for the majority of drivers, and is OK to do ad hoc...
But again - whatever. There is a way to do it today that is not very cumbersome. If Hubitat adds it at the platform level, that's great - it certainly doesn't hurt me any.
Sorry, one more thought occurred to me. Since you indicated you were giving this idea of pre-gathering some z-wave reports some thought, it occurs to me that there are many types of reports / data items that are simply harder to use than they need to be due to the asynchronous nature of Z-wave interaction and could be made much easier if the data was gathered at install / startup time. This is particularly true in the case of sleeping devices where you can't effectively gather information during the sleep, but which could have been gathered at install.
With this in mind, I'd like to see Hubitat expand its "device" information to include all of the common "report" information that doesn't change during the lifetime of the device (or, at least, doesn't change unless the firmware changes) and which can be gathered on startup. This really seems like a "platform" feature (rather than something to replicate in drivers). I think that this and some simple calls to access the data would avoid programming errors (particularly race-conditions and timing ones) and make development easier
This seems pretty easy to implement at the platform level - i.e., by a installation sequence that does something like . . .
On Pairing, Or if previously Paired and data not gathered,
or if (check firmware version and if firmware has changed from prior startup), then
For each Z-Wave device:
IF sleeping, On Next Wakeup OR If awake then
For each command class, get version #
Set up default ZWave.Parse to not exceed the retrieved class version # and Hubitat supported maximum version #
Get Central Scene Supported Report info
Get Central Scene Configuration Get (for V3)
Get Version Report
Get Association Group Information Report
* Get Configuration Get if supported
Get Firmware Info (versions, etc.)
get Manufacturer Specific Info.
And store all this information in a device.zwave structure so it can be accessed in a driver or app.
This could be done on an evolutionary basis - start with the command class and firmware versions, and using these to set the default zwave.parse versions, then build up. . .
Of course, the existing Z-Wave classes would remain so developers could still use the "traditional" methods.
It may also be helpful to store the data with all the fields / information you would get from the original payload - i.e., store the payload and then have functions like "getCachedDeviceReport("Firmware") " which would return the same cmd structure as you would have gotten from the report. Perhaps augmenting the cmd structure to always include a cmd.reportVersion which would also tell you which command class version was used for the original report.
Any further thought on this? As mentioned, I think it would be extremely helpful for developers if the platform could, at pairing time, collect "fixed" device information so it was always available to a driver without doing a asynchronous call. The 3 that that I would find most useful
- Firmware version (stored as individual parameters, perhaps in the Version V2 format),
- Command classes and versions -- including that of each endpoint if the device is multi-endpoint. Currently, one gets the classes by inclusters, but not versions, and doesn't get endpoint data. I'd envision this to be a simple Map by endpoint like [[ep:0, [Map of class:version]][ep:1, [Map of class:version], [ep:2, [Map of class:version]]], etc. For endpoints other than the parent (0), I understand that the version would be the same as the parent version, but I put version in the structure for consistency.
- Meter Supported Report information
#1 and #2 would be particularly useful to me, especially for some work I'm doing on a driver so that I can better handle devices that sleep (as the driver might not be able to get this information so easily during Initialization), and for several other reasons.
The implementation might be as simple as gathering and storing report payloads for the various reports at boot time so that, when needed, the driver can just do a "getDataValue" call to retrieve the already stored payload and pass it to zwave.parse thus providing the information synchronously rather than requiring an asynchronous call . And if you already have the class versions, you know exactly which version map to pass to parse.
Over time, this could be built out so that the platform would gather all the "fixed" report information at pairing, but the "standard" commands that now exist could remain in case they are needed.