Creating a double-tap rule for switches that don't support it

I've been slowly building out my z-wave network for about a year and only recently started to try some more advanced stuff with Rule Machine.

I'd like to have a double-tap of the on or off switch of one of my dimmers perform some additional actions (i.e. one tap turns it on, a second tap turns some other lights nearby on).

All of my dimmers are Leviton DZ6HDs - anf upon doing some reading, I see they do not natively support double-tap functionality. Looking back on it now, maybe I should have picked a different brand, but I'm seversl hundred bucks into them now so I'd rather not have to replace with a different brand if it can be avoided.

There are some helpful posts here that show roughly how to do this with a sort of "tap status" variable and a delayed reset on the variable to basically simulate double tap logic.

I haven't been able to get anything like that to work though.

The problem seems to be that my event is triggered by the switch being switched "on" and then runs the various rules - but pressing the "on" paddle a second time, when the switch is already on doesn't seem to trigger anything else.

Am i missing something obvious here? Should I be choosing a different trigger event other than "switch" turning to on?

Appreciate any insight anyone has - thank you!

Your device would set least needed to send some "button" event (e.g., button 1 pushed) for this to work. In Z-Wave terms, this feature is normally called Central Scenes. What makes multi-tap devices special is that they send different events (scenes) for different numbers of taps. If yours only send a single event regardless of multiple taps, that's likely where the workarounds you saw come into play (though a link to any of them so someone could see what you're really talking about is better than vague allusion to them).

Most Z-Wave devices also won't send a report back in response to a "Set" command if nothing really changed, which is what's happening if tjr light is already on and you tap the paddle up/on again. I don't really see any way to make this work without a different device, either one meant for this feature (whether single or multiple taps, but "native" multiple taps is certainly easier) or supplementing it with a button/remote device you could use for just this purpose.

3 Likes

As @bertabcd1234 said, that works as long as your switch sends some kind of button event, which your dimmers don't.

If you revisit this idea, I would recommend Zooz dimmers and switches.

2 Likes

Use my custom driver: [DRIVER] Leviton Dimmers (DZPD3 / DZ6HD)

Turn on debug logging and then press On multiple times when already on. Do you see debug logs indicating the driver got more "on" messages from the device?

If so, the driver could be modified to create button events for every on/off tap, which you could then use to make your virtual double tap rules.

3 Likes

Thanks all for the quick replies, and jtp10181 for that suggestion - I will give it a shot. The device I have been testing this on is actually the basic Leviton on/off switch but I'll try one of the dimmers now. I had already noticed in the log for the device that additional "on" taps are recognized, i.e.

2024-01-04 09:07:14.099 PM
Back Door Light is on [physical]

2024-01-04 09:07:08.159 PM
Back Door Light is on [physical]

2024-01-04 09:07:04.410 PM
Back Door Light was turned on [physical]

The "was turned on" is when the switch first goes from off to on, then the more recent "is on" lines were logged when I press the "on" toggle again.

So, there is at least some recognition in HE that the switch is being pressed again.

Will report back - thanks!

Ok that is normal so I suspected the device would send an event for every tap.

I can modify the driver tomorrow if you want, unless you are going to try it? It will be a pretty trivial change, adding just a few lines in the correct place to create the event.

Sure, I'd love to give that a shot if you don't mind making the change! Let me know if there's any more info I can provide.

I see your note about firmware - would you recommend being at the latest version before trying your driver? I haven't checked the version for any of them (not totally sure how, to be honest, but I can figure it out) - will do that if you think it's necessary.

Thanks so much!

It's almost impossible to get this to work at the app level, I have done it and it just slows everything down and is unreliable.

Best is built into the device the next option is at the driver level as @jtp10181 suggests. Still not great but it works.

2 Likes

I think a lot of people had issues with older Leviton firmware, devices locking up possibly. That was why it became a big deal to update them. Driver should work fine on any firmware I think. I personally only have the one Leviton plug in dimmer module that someone sent me to make the driver with. Otherwise all my stuff is Zooz.

Depends how you do it... Most people want it NOT to send the single press event to the hub if they are trying to do only double press, for instance. In that case you have to hold sending the single press event in the driver until the timeout window expires to make sure it isn't actually a double press event.

Thus, every single press by definition has to be slowed down to wait for the multi press time window to expire.

If you send the single press, and then just all presses after that, sure, then it wouldn't slow anything down (and is super easy to code, obviously... isStateChange: false). But every other time I tried to be nice and add this feature on switches that didn't support it in hardware I immediately got complaints that "I don't want it to send the single tap if I'm trying to double tap", etc.

So I am just 100% out of the soft multi-tap coding business now. :slight_smile:

Anyway, your driver - your choice. I'm just sharing MY experiences in this arena.

4 Likes

I didn't think of that. I have used a soft double tap with a Caseta switch. It worked well enough that I used it for a few months before adding a Pico next to the switch.

I never attempted this with a dimmer, and have difficulty understanding how it can be made to work with a dimmer.

2 Likes

I think a quick tap ON when already on will still send another event to the hub. It might just be the level though, so you are right it could be trickier with a dimmer.

@isolecki I think some debug logs using my dimmer driver would be helpful. I do not have a wall switch to try it out, only the plug module which has a single button on/off toggle button.

1 Like

Especially if the dimmer is already ā€œonā€ at some dim level.

1 Like

Thanks @jtp10181!

I tried updating the firmware through HE with a method I found on this forum, but ran into an "insufficient memory" issue which it seems a few others have encountered. So, I will probably need to do it with a USB stick, which I don't presently have.

I'll give your driver a shot without updating - both on dimmer and switch - and see how it goes. Thanks for the help - I'll report back!

Its only made for the dimmer, I dont think it works right on a switch.

@jtp10181 I tried it just for fun and it does run the switch too, FYI! I haven't touched any of the dimmer-specific features, but on/off works just fine.

Anyway, here is a debug log from me turning it on while running on your driver, and pressing the on switch again several times before turning it off. Hope this is what you need and I've done it right - let me know! Thanks again!

dev:8 2024-01-05 06:21:31.955 PM
info Back Door Light: switch is turned off (digital)
dev:8 2024-01-05 06:21:31.674 PM
debug Back Door Light: getSetLevelCmds output [level:0, duration:255, endPoint:0]
dev:8 2024-01-05 06:21:31.671 PM
debug Back Door Light: off...
dev:8 2024-01-05 06:21:30.791 PM
debug Back Door Light: level is set to 10% (digital) [NOT CHANGED]
dev:8 2024-01-05 06:21:30.788 PM
debug Back Door Light: switch is turned on (digital) [NOT CHANGED]
dev:8 2024-01-05 06:21:30.496 PM
debug Back Door Light: getSetLevelCmds output [level:255, duration:255, endPoint:0]
dev:8 2024-01-05 06:21:30.494 PM
debug Back Door Light: on...
dev:8 2024-01-05 06:21:24.780 PM
debug Back Door Light: level is set to 10% (digital) [NOT CHANGED]
dev:8 2024-01-05 06:21:24.778 PM
debug Back Door Light: switch is turned on (digital) [NOT CHANGED]
dev:8 2024-01-05 06:21:24.519 PM
debug Back Door Light: getSetLevelCmds output [level:255, duration:255, endPoint:0]
dev:8 2024-01-05 06:21:24.517 PM
debug Back Door Light: on...
dev:8 2024-01-05 06:21:23.314 PM
debug Back Door Light: level is set to 10% (digital) [NOT CHANGED]
dev:8 2024-01-05 06:21:23.311 PM
debug Back Door Light: switch is turned on (digital) [NOT CHANGED]
dev:8 2024-01-05 06:21:23.007 PM
debug Back Door Light: getSetLevelCmds output [level:255, duration:255, endPoint:0]
dev:8 2024-01-05 06:21:23.005 PM
debug Back Door Light: on...
dev:8 2024-01-05 06:21:21.700 PM
debug Back Door Light: level is set to 10% (digital) [NOT CHANGED]
dev:8 2024-01-05 06:21:21.698 PM
info Back Door Light: switch is turned on (digital)

Looks like your pressed the on command from the device page?
Need to press the actual switch, to see what commands come back from the device when tapping on the paddle when it is already one.

I think you will actually need go into the driver code and at the very bottom uncomment the trace logging so I can see the exact messages sent back by the device.

//For Extreme Code Debugging - tracing commands
void logTrace(String msg) {
	//Uncomment to Enable
	log.trace "${device.displayName}: ${msg}"
}

Ah, gotcha. Here you go - I hope this is fairly legible, I'm pasting it from mobile.

dev:8 2024-01-05 08:40:02.589 PM
info Back Door Light: switch is turned off (physical)
dev:8 2024-01-05 08:40:02.586 PM
trace Back Door Light: SwitchMultilevelReport(value:0) (ep 0)
dev:8 2024-01-05 08:40:02.585 PM
trace Back Door Light: parse: zw device: 10, command: 2603, payload: 00 00 00 , isMulticast: false --PARSED-- SwitchMultilevelReport(value:0)
dev:8 2024-01-05 08:40:02.423 PM
trace Back Door Light: Hail() (ep 0)
dev:8 2024-01-05 08:40:02.421 PM
trace Back Door Light: parse: zw device: 10, command: 8201, payload: , isMulticast: false --PARSED-- Hail()
dev:8 2024-01-05 08:40:00.640 PM
debug Back Door Light: level is set to 100% (physical) [NOT CHANGED]
dev:8 2024-01-05 08:40:00.637 PM
debug Back Door Light: switch is turned on (physical) [NOT CHANGED]
dev:8 2024-01-05 08:40:00.635 PM
trace Back Door Light: SwitchMultilevelReport(value:99) (ep 0)
dev:8 2024-01-05 08:40:00.630 PM
trace Back Door Light: parse: zw device: 10, command: 2603, payload: 63 63 00 , isMulticast: false --PARSED-- SwitchMultilevelReport(value:99)
dev:8 2024-01-05 08:40:00.447 PM
trace Back Door Light: Hail() (ep 0)
dev:8 2024-01-05 08:40:00.445 PM
trace Back Door Light: parse: zw device: 10, command: 8201, payload: , isMulticast: false --PARSED-- Hail()
dev:8 2024-01-05 08:39:55.108 PM
debug Back Door Light: level is set to 100% (physical) [NOT CHANGED]
dev:8 2024-01-05 08:39:55.106 PM
debug Back Door Light: switch is turned on (physical) [NOT CHANGED]
dev:8 2024-01-05 08:39:55.103 PM
trace Back Door Light: SwitchMultilevelReport(value:99) (ep 0)
dev:8 2024-01-05 08:39:55.102 PM
trace Back Door Light: parse: zw device: 10, command: 2603, payload: 63 63 00 , isMulticast: false --PARSED-- SwitchMultilevelReport(value:99)
dev:8 2024-01-05 08:39:54.965 PM
trace Back Door Light: Hail() (ep 0)
dev:8 2024-01-05 08:39:54.963 PM
trace Back Door Light: parse: zw device: 10, command: 8201, payload: , isMulticast: false --PARSED-- Hail()
dev:8 2024-01-05 08:39:52.751 PM
debug Back Door Light: level is set to 100% (physical) [NOT CHANGED]
dev:8 2024-01-05 08:39:52.748 PM
debug Back Door Light: switch is turned on (physical) [NOT CHANGED]
dev:8 2024-01-05 08:39:52.745 PM
trace Back Door Light: SwitchMultilevelReport(value:99) (ep 0)
dev:8 2024-01-05 08:39:52.743 PM
trace Back Door Light: parse: zw device: 10, command: 2603, payload: 63 63 00 , isMulticast: false --PARSED-- SwitchMultilevelReport(value:99)
dev:8 2024-01-05 08:39:52.608 PM
trace Back Door Light: Hail() (ep 0)
dev:8 2024-01-05 08:39:52.607 PM
trace Back Door Light: parse: zw device: 10, command: 8201, payload: , isMulticast: false --PARSED-- Hail()
dev:8 2024-01-05 08:39:49.600 PM
info Back Door Light: level is set to 100% (physical)
dev:8 2024-01-05 08:39:49.584 PM
info Back Door Light: switch is turned on (physical)
dev:8 2024-01-05 08:39:49.571 PM
trace Back Door Light: SwitchMultilevelReport(value:99) (ep 0)
dev:8 2024-01-05 08:39:49.566 PM
trace Back Door Light: parse: zw device: 10, command: 2603, payload: 63 63 00 , isMulticast: false --PARSED-- SwitchMultilevelReport(value:99)
dev:8 2024-01-05 08:39:49.344 PM
trace Back Door Light: Hail() (ep 0)
dev:8 2024-01-05 08:39:49.339 PM
trace Back Door Light: parse: zw device: 10, command: 8201, payload: , isMulticast: false --PARSED-- Hail()
dev:8 2024-01-05 08:39:27.193 PM
debug Back Door Light: executeConfigureCmds...
dev:8 2024-01-05 08:39:25.981 PM
debug Back Door Light: Description logging is: true
dev:8 2024-01-05 08:39:25.979 PM
debug Back Door Light: Debug logging is: true
dev:8 2024-01-05 08:39:25.977 PM
debug Back Door Light: updated...

(Editing/Removing previous post as I've made further progress)

I've been looking through your code and reading some other posts over the weekend, curious to see if I can figure it out... I do a little bit of very basic JS scripting for work so I can sort of read this, but don't really know exactly what's going on.

I've managed to cobble together the functionality I was looking for by adding just a bit to your driver! Here's what I did, for any interested readers. I can't say that this is the "right" way to go about this, as I don't really know what I'm doing, but it works :slight_smile: feedback & criticism welcome!

First, I donā€™t care about the timing between taps - I just want the second "on" tap to trigger something else, and the second "off" tap to do something similar.

So, I added two new attributes at the top:

attribute "onSwitchCounter", "string"
attribute "offSwitchCounter", "string"

And a new function to modify their values when the switch is pressed. Pressing the "on" paddle increments the "on" counter by one, and resets the other counter to 0. Pressing the "off" counter does the opposite:

void toggleSwitchCounter(String value) {
if (value == "on") {
sendEvent(name:"offSwitchCounter", value:0)
String currentOnSwitchCount = (device.currentValue("onSwitchCounter") as Integer) + 1
sendEvent(name:"onSwitchCounter", value:currentOnSwitchCount)
//logDebug "onSwitchCount: ${device.currentValue("onSwitchCounter")}"
} else if (value == "off") {
sendEvent(name:"onSwitchCounter", value:0)
String currentOffSwitchCount = (device.currentValue("offSwitchCounter") as Integer) + 1
sendEvent(name:"offSwitchCounter", value:currentOffSwitchCount)
//logDebug "offSwitchCount: ${device.currentValue("offSwitchCounter")}"
}
}

That function gets called in sendSwitchEvents:

toggleSwitchCounter(value)

With that, I can build a rule around these two custom attributes to process actions when the counter hits a certain number (could do triple, quad, etc taps too, I think).

One thing I couldn't figure out was how to make the attributes integers rather than strings. I would declare them as integers and pass integers to sendEvent, but device.currentValue would always return a string anyway. I'm sure it's something really obvious, but I'm new here :slight_smile:

Anyway, thanks everyone for the help and @jtp10181 especially for your great driver! (all of this works fine with my DZ15S switch as well, by the way).

1 Like

Sorry for not getting back to you earlier, I got busy with other things and knew I didn't have the time to work on the code right now. Glad you got it figured out on your own. If you need help tweaking it any further let me know.