/** * * Enerwave RSM2 Dual Relay Switch Device Type * * Author: Eric Maycock (erocm123) * Date: 2016-03-25 * * Device Type supports all the feautres of the Enerwave RSM2 device including both switches, * and the AllOn/AllOff functionality. */ metadata { definition (name: "Enerwave RSM2 Dual Relay Switch", namespace: "erocm123", author: "Eric Maycock", vid:"generic-switch") { capability "Switch" capability "Polling" capability "Configuration" capability "Refresh" capability "Zw Multichannel" capability "Health Check" attribute "switch1", "string" attribute "switch2", "string" command "on1" command "off1" command "on2" command "off2" fingerprint mfr: "011A", prod: "0101", model: "5606" fingerprint deviceId: "0x1001", inClusters:"0x86, 0x72, 0x85, 0x60, 0x8E, 0x25, 0x20, 0x70, 0x27" } simulator { status "on": "command: 2003, payload: FF" status "off": "command: 2003, payload: 00" // reply messages reply "2001FF,delay 100,2502": "command: 2503, payload: FF" reply "200100,delay 100,2502": "command: 2503, payload: 00" } tiles(scale: 2){ multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc" attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } } standardTile("switch1", "device.switch1",canChangeIcon: true, width: 2, height: 2) { state "on", label: "switch1", action: "off1", icon: "st.switches.switch.on", backgroundColor: "#00a0dc" state "off", label: "switch1", action: "on1", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } standardTile("switch2", "device.switch2",canChangeIcon: true, width: 2, height: 2) { state "on", label: "switch2", action: "off2", icon: "st.switches.switch.on", backgroundColor: "#00a0dc" state "off", label: "switch2", action: "on2", icon: "st.switches.switch.off", backgroundColor: "#ffffff" } standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" } standardTile("configure", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { state "default", label:"", action:"configure", icon:"st.secondary.configure" } main(["switch","switch1", "switch2"]) details(["switch","switch1","switch2","refresh","configure"]) } } def parse(String description) { def result = [] def cmd = zwave.parse(description) if (cmd) { result += zwaveEvent(cmd) log.debug "Parsed ${cmd} to ${result.inspect()}" } else { log.debug "Non-parsed event: ${description}" } return result } def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) { // Not used } def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) { sendEvent(name: "switch", value: cmd.value ? "on" : "off", type: "digital") def result = [] result << zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format() result << zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format() response(delayBetween(result, 1000)) // returns the result of reponse() } def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) { sendEvent(name: "switch", value: cmd.value ? "on" : "off", type: "digital") def result = [] result << zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format() result << zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format() response(delayBetween(result, 1000)) // returns the result of reponse() } def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) { def result if (cmd.scale == 0) { result = createEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kWh") } else if (cmd.scale == 1) { result = createEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kVAh") } else { result = createEvent(name: "power", value: cmd.scaledMeterValue, unit: "W") } return result } def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCapabilityReport cmd) { log.debug "multichannelv3.MultiChannelCapabilityReport $cmd" if (cmd.endPoint == 2 ) { def currstate = device.currentState("switch2").getValue() if (currstate == "on") sendEvent(name: "switch2", value: "off", isStateChange: true, display: false) else if (currstate == "off") sendEvent(name: "switch2", value: "on", isStateChange: true, display: false) } else if (cmd.endPoint == 1 ) { def currstate = device.currentState("switch1").getValue() if (currstate == "on") sendEvent(name: "switch1", value: "off", isStateChange: true, display: false) else if (currstate == "off") sendEvent(name: "switch1", value: "on", isStateChange: true, display: false) } } def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) { def map = [ name: "switch$cmd.sourceEndPoint" ] switch(cmd.commandClass) { case 32: if (cmd.parameter == [0]) { map.value = "off" } if (cmd.parameter == [255]) { map.value = "on" } createEvent(map) break case 37: if (cmd.parameter == [0]) { map.value = "off" } if (cmd.parameter == [255]) { map.value = "on" } break } def events = [createEvent(map)] if (map.value == "on") { events += [createEvent([name: "switch", value: "on"])] } else { def allOff = true (1..2).each { n -> if (n != cmd.sourceEndPoint) { if (device.currentState("switch${n}").value != "off") allOff = false } } if (allOff) { events += [createEvent([name: "switch", value: "off"])] } } events } def zwaveEvent(physicalgraph.zwave.Command cmd) { // This will capture any commands not handled by other instances of zwaveEvent // and is recommended for development so you can see every command the device sends return createEvent(descriptionText: "${device.displayName}: ${cmd}") } def zwaveEvent(physicalgraph.zwave.commands.switchallv1.SwitchAllReport cmd) { log.debug "SwitchAllReport $cmd" } def refresh() { def cmds = [] cmds << zwave.manufacturerSpecificV2.manufacturerSpecificGet().format() cmds << zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format() cmds << zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format() delayBetween(cmds, 1000) } def ping() { log.debug "ping()" refresh() } def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) { def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId) log.debug "msr: $msr" updateDataValue("MSR", msr) } def poll() { def cmds = [] cmds << zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format() cmds << zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format() delayBetween(cmds, 1000) } def configure() { log.debug "configure() called" sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID]) def cmds = [] cmds << zwave.configurationV1.configurationSet(parameterNumber: 3, configurationValue: [1]).format() cmds << zwave.configurationV1.configurationGet(parameterNumber: 3).format() return delayBetween(cmds, 2000) } /** * Triggered when Done button is pushed on Preference Pane */ def updated() { log.debug "Preferences have been changed. Attempting configure()" def cmds = configure() response(cmds) } def on() { delayBetween([ zwave.switchAllV1.switchAllOn().format(), zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(), zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format() ], 1000) } def off() { delayBetween([ zwave.switchAllV1.switchAllOff().format(), zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(), zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:2, commandClass:37, command:2).format() ], 1000) } 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() ], 1000) } 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() ], 1000) } def on2() { delayBetween([ zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:1, parameter:[255]).format(), zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format() ], 1000) } def off2() { delayBetween([ zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:1, parameter:[0]).format(), zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format() ], 1000) }