Leviton DZMX1 dimmer needs a delay before automagic refresh after being manually tapped
See original GitHub issueDescribe the bug
When the physical button on the Levition DZMX1 dimmer switch is tapped, the device emits an ApplicationUpdateRequest. zwave-js correctly interprets this as a state-change notification (logging “Node does not send unsolicited updates, refreshing actuator and sensor values...
”) and immediately performs a refreshValues()
on the node, sending a MultilevelSwitchCCGet
command. But, the device immediately responds with an “Application Status” command indicating “busy, try again later”, which is dropped as unimplemented by zwave-js. Ten seconds later, the outstanding Get command times out.
The consequences of all this is:
- The state of the device is not automatically updated after a physical button tap.
- Attempts to communicate with the device after a physical button tap (e.g., to manually poll the value, or change the value via zwave) will be delayed for 10 seconds, waiting for the automatic Get command to timeout.
I figure the “busy, try again later” response from the device was a technique to avoid violating the old Lutron patent. A refreshValues()
on the node does succeed if it is delayed at least 950ms after receiving the ApplicationUpdateRequest. So, it looks like Leviton implemented “Well, let’s just require a 1 second delay, so that no one can possibly call this an ‘instant update’.”
To handle this, I propose inserting a device-specific delay before refreshValues()
is called in this block https://github.com/zwave-js/node-zwave-js/blob/6cc6466e2ce050b95364b1740cc6d123af3cdba1/packages/zwave-js/src/lib/node/Node.ts#L1505-L1512 The delay is trivial, but what about the device-specific aspect? Would it be reasonable to just add a new parameter to the schema for device configuration files?
(Another possibility would be to implement handling the “Application Status, busy, try again later” message, and automatically retrying the request. But… even that would require knowing how long to wait before the retry, hence a device-specific parameter.)
Device information
Which device(s) is/are affected (make/model)? Leviton DZMX1 What are the node IDs? Node 2
Last Known Working Configuration
- New device
- Previously working device (node-zwave-js)
- Previously working device (other platform)
Installation information
How did you install node-zwave-js
?
-
zwavejs2mqtt
(latest) docker image -
zwavejs2mqtt
(dev) docker image - ioBroker.zwave2 adapter
- Pkg (
npm install @zwave-js/server
) - Manual Docker build
node-zwave-js
branch:zwavejs2mqtt
branch:
- Manually built (to experiment with delays before
refreshValues()
) - Other:
To Reproduce Steps to reproduce the behavior:
- Have DZMX1 in network.
- Tap its button.
- Within the next 10 seconds, try to do something with it over RF.
- Look at logs.
Additional context none
Logfile:
This logfile is from stock zwave-js (without any delays hacked in). The timeline is:
- Light is off, zwave-js-server started up.
- Human taps physical button.
- Device calls for help, zwave-js responds, device says “Naw, I am busy”, zwave-js ignores that.
- 3-4 seconds later, human runs script asking zwave-js to poll the current level value and then set the value to zero.
- 10 seconds after the button tap, when zwave-js’s original automatic Get request times out, the requested poll/set finally occur.
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (5 by maintainers)
Top GitHub Comments
There are a few parts to this.
maintenance\schemas\device-config.json
, somewhere in the properties key, line 223 1.2 parsing:packages\config\src\CompatConfig.ts
, classCompatConfig
1.3 Documentation:docs\development\config-files.md
this.deviceConfig.compat?.manualValueRefreshDelay
.I can take a stab at adding this.
Any hints/clues as to where to start (a filename, a keyword — some crate or barrel to form the basis of my cargo cult) would be appreciated.