Device Polling

So here is one for you. I have a few of the Enerwave Dual Relay Modules and I use the in some rooms that do not have dual wall switches for the fan and light.
What I do is basically power the switch but connect it so the relay in the fan is always powered and when I toggle the switch I have a rule that turns the relays on or off depending on what I want. This works because the switches get polled and when they get polled and report their on or off status it controls the light in the room. How can I setup polling for these in RM?

https://www.amazon.com/Enerwave-Z-Wave-Switch-Module-Convert/dp/B01CPO2D3K

You can use Periodic in a trigger for a polling loop if you need one. Then, as @bamarayne says, you can send a refresh command to the device by setting that up in Custom Commands. I’m not familiar with what you’re doing, but this sounds like what you need.

How often do you poll the device?

1 Like

I dont have to have a poll currently. the switch is a GE ZWave wall switch and in ST I just have a rule that when switch is on turn on light when off turn off. It works with about a 3 second delay. I, in the past, had a poll every 2 seconds going to them but have not needed it for a while.

Oh, ok. Depending on the switch, you should get pretty fast responsiveness. You just use a trigger with “physical”.

1 Like

You would need one for off as well. Can't use "physical switch" in a rule, because it's only an event, not a state.

2 Likes

Man I missed you in ST lol

1 Like

Just an fyi, none of the devices we support with our built in drivers require polling to report physical state changes.

2 Likes

do you have a drive for the Enerwave Dual Relay?

1 Like

We do not, we didn’t actually have any staff using it.
Drivers are a little more work to migrate than apps, not much though. I’m sure we’ll publish something shortly on the steps involved.

It works with Generic ZWave Switch to control one of the relays but not the other just as an FYI

Do you have the driver for ST? If so, it’s pretty easy to change it.

I do but unfortunately I’m not a coder just a breaker.

1 Like

if anyone wants to help
/**

  • Enerwave RSM2
  • Borrowed from Matt Frank via smartthings community forums. Minor edits by Joel Tamkin
  • Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except
  • in compliance with the License. You may obtain a copy of the License at:
  •  http://www.apache.org/licenses/LICENSE-2.0
    
  • Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
  • on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
  • for the specific language governing permissions and limitations under the License.

/
/
*

  • Enerwave Dual Load ZWN-RSM2
    */
    // for the UI
    metadata {
    definition (name: “Enerwave Dual Load ZWN-RSM2”, author: “matt”) {
    capability "Switch"
    capability "Polling"
    capability "Configuration"
    capability “Refresh”

    attribute "switch1", "string"
    attribute "switch2", "string"
    
    
    command "on1"
    command "off1"
    command "on2"
    command "off2"
    

    }

    simulator {
    // TODO: define status and reply messages here
    }

    tiles {

    standardTile("switch1", "device.switch1",canChangeIcon: true) {
                    state "on", label: "switch1", action: "off1", icon: "st.switches.switch.on", backgroundColor: "#79b821"
                    state "off", label: "switch1", action: "on1", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
            }
    standardTile("switch2", "device.switch2",canChangeIcon: true) {
                    state "on", label: "switch2", action: "off2", icon: "st.switches.switch.on", backgroundColor: "#79b821"
                    state "off", label: "switch2", action: "on2", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
            }
    standardTile("refresh", "device.switch1", inactiveLabel: false, decoration: "flat") {
                    state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
            }
    
    standardTile("configure", "device.switch1", inactiveLabel: false, decoration: "flat") {
    				state "default", label:"", action:"configure", icon:"st.secondary.configure"
            }
    
    
    main(["switch1", "switch2"])
    details(["switch1","switch2","refresh","configure"])
    

    }
    }

// 0x25 0x32 0x27 0x70 0x85 0x72 0x86 0x60 0xEF 0x82

// 0x25: switch binary
// 0x32: meter
// 0x27: switch all
// 0x70: configuration
// 0x85: association
// 0x86: version
// 0x60: multi-channel
// 0xEF: mark
// 0x82: hail

// parse events into attributes
def parse(String description) {
log.debug “Parsing desc => ‘${description}’”

def result = null
def cmd = zwave.parse(description, [0x60:3, 0x25:1, 0x70:1, 0x72:1])
if (cmd) {
    result = createEvent(zwaveEvent(cmd))
}

return result

}

//Reports

def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: “${device.displayName}: ${cmd}”)
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
log.debug "BasicReport $cmd.value"
def map = [name: “switch1”, type: “physical”]
if (cmd.value == 0) {
map.value = “off”
}
else if (cmd.value == 255) {
map.value = “on”
}
//refresh()
return map

}

def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
//[name: “switch”, value: cmd.value ? “on” : “off”, type: “digital”]
log.debug “SwitchBinaryReport $cmd.value”
}

def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
//log.debug “MultiChannelCmdEncap $cmd”

def map = [ name: "switch$cmd.sourceEndPoint" ]
if (cmd.commandClass == 37){
	if (cmd.parameter == [0]) {
    	map.value = "off"
    }
    if (cmd.parameter == [255]) {
        map.value = "on"
    }
    log.debug "Processed zwave message: $map"
    map
}

}

// handle commands

def refresh() {
delayBetween([
log.debug(“refreshing s1”),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
log.debug(“refreshing s2”),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
//zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format()
])
}

def poll() {
delayBetween([
zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
])

}

def configure() {
log.debug "Executing ‘configure’"
delayBetween([
zwave.configurationV1.configurationSet(parameterNumber:4, configurationValue: [0]).format() // Report reguarly
])
}

def on1() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:1, parameter:[255]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
])

}

def off1() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:1, parameter:[0]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
])

}

def on2() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:1, parameter:[255]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
])

}

def off2() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:1, parameter:[0]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
])
}

/*

Enerwave Dual Load ZWN-RSM2
*/
// for the UI
metadata {
definition (name: "Enerwave Dual Load ZWN-RSM2", namespace: "hubitat", author: "matt") {
capability "Switch"
capability "Polling"
capability "Configuration"
capability "Refresh"

attribute "switch1", "string"
attribute "switch2", "string"


command "on1"
command "off1"
command "on2"
command "off2"
}


}

// 0x25 0x32 0x27 0x70 0x85 0x72 0x86 0x60 0xEF 0x82

// 0x25: switch binary
// 0x32: meter
// 0x27: switch all
// 0x70: configuration
// 0x85: association
// 0x86: version
// 0x60: multi-channel
// 0xEF: mark
// 0x82: hail

// parse events into attributes
def parse(String description) {
log.debug "Parsing desc => ‘${description}’"

def result = null
def cmd = zwave.parse(description, [0x60:3, 0x25:1, 0x70:1, 0x72:1])
if (cmd) {
    result = createEvent(zwaveEvent(cmd))
}

return result
}

//Reports

def zwaveEvent(hubitat.zwave.Command cmd) {
createEvent(descriptionText: "${device.displayName}: ${cmd}")
}

def zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd) {
log.debug "BasicReport $cmd.value"
def map = [name: "switch1", type: "physical"]
if (cmd.value == 0) {
map.value = "off"
}
else if (cmd.value == 255) {
map.value = "on"
}
//refresh()
return map

}

def zwaveEvent(hubitat.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
//[name: "switch", value: cmd.value ? "on" : "off", type: "digital"]
log.debug "SwitchBinaryReport $cmd.value"
}

def zwaveEvent(hubitat.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
//log.debug "MultiChannelCmdEncap $cmd"

def map = [ name: "switch$cmd.sourceEndPoint" ]
if (cmd.commandClass == 37){
	if (cmd.parameter == [0]) {
    	map.value = "off"
    }
    if (cmd.parameter == [255]) {
        map.value = "on"
    }
    log.debug "Processed zwave message: $map"
    map
}
}

// handle commands

def refresh() {
delayBetween([
log.debug("refreshing s1"),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
log.debug("refreshing s2"),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
//zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format()
])
}

def poll() {
delayBetween([
zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
])

}

def configure() {
log.debug "Executing ‘configure’"
delayBetween([
zwave.configurationV1.configurationSet(parameterNumber:4, configurationValue: [0]).format()	// Report reguarly
])
}

def on1() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:1, parameter:[255]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
])

}

def off1() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:1, parameter:[0]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
])

}

def on2() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:1, parameter:[255]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
])

}

def off2() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:1, parameter:[0]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
])
}

Give that a try, might work, can’t test it.

You open Drivers Code, click on New Driver (upper right), then copy and paste that code in. Click Save. Then in the device itself, change the Type to this driver (bottom of list of types), and click Save.

2 Likes

Driver works great… Now i gotta figure out how to make a virtual device that points to one of the relays rather than the whole thing because it shows up as one switch in apps.
thanks Bruce!

2 Likes

You can use a custom command in RM. With that you can directly control each switch. So you may not need a virtual device at all.

2 Likes

well that worked thank you

1 Like

This is fantastic, got lots of duel relays using that ST driver. Was a bit worried how they’d work when my hub shows…

2 Likes

Bruce is the man.

2 Likes