Here is my virtual device handler based on standard simulated switch:
/**
* Copyright 2015 SmartThings
*
* 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.
*
*/
metadata {
definition (name: "Orvibo Simulated Switch", namespace: "WilliePrinsloo", author: "willie@prinsloo.com") {
capability "Switch"
capability "Relay Switch"
capability "Actuator"
}
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: '${currentValue}', action: "switch:on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState:"on"
state "on", label: '${currentValue}', action: "switch:off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
}
main "switch"
details(["switch","on","off"])
}
}
def parse(description) {
}
def on() {
log.debug "$version on()"
sendEvent(name: "switch", value: "on")
}
def off() {
log.debug "$version off()"
sendEvent(name: "switch", value: "off")
}
private getVersion() {
"PUBLISHED"
}
and here is the smart app added to the physical relay device to sync or bind the virtual and physical switch states:
/**
* Virtual / Physical Switch Sync (i.e. Enerwave ZWN-RSM2 Adapter, Monoprice Dual Relay, Philio PAN04, Aeon SmartStrip)
*
* Copyright 2016 Eric Maycock (erocm123)
*
* Note: Use a "Simulated Switch" from the IDE for best results
*
* 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.
*
*/
definition(
name: "Virtual / Physical Switch Sync",
namespace: "erocm123",
author: "Eric Maycock",
description: "Keeps multi switch devices like the Aeon Smartstrip, Monoprice Dual Relay, and Philio PAN04 in sync with their virtual switches",
category: "My Apps",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
preferences {
page(name: "numberPage", nextPage: "setupPage")
page(name: "setupPage")
}
def numberPage() {
dynamicPage(name: "numberPage", install: false, uninstall: true) {
section {
input "vNumber", "number", title:"Number of virtual switches", description: 2, defaultValue: 2 , required: true
}
section([title:"Available Options", mobileOnly:true]) {
label title:"Assign a name for your app (optional)", required:false
}
}
}
def setupPage() {
dynamicPage(name: "setupPage", install: true, uninstall: true) {
section {
input "physical", "capability.switch", title: "Which Physical Switch?", multiple: false, required: true
for (int i = 1; i <= vNumber; i++){
input "virtual${i}", "capability.switch", title: "Virtual Switch to link to Switch ${i}?", multiple: false, required: true
}
}
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
log.debug "Initializing Virtual / Physical Switch Sync v 1.0"
for (int i = 1; i <= vNumber; i++){
subscribe(physical, "switch${i}", physicalHandler)
subscribeToCommand(settings["virtual${i}"], "on", virtualHandler)
subscribeToCommand(settings["virtual${i}"], "off", virtualHandler)
}
}
def virtualHandler(evt) {
log.debug "virtualHandler called with event: deviceId ${evt.deviceId} name:${evt.name} source:${evt.source} value:${evt.value} isStateChange: ${evt.isStateChange()} isPhysical: ${evt.isPhysical()} isDigital: ${evt.isDigital()} data: ${evt.data} device: ${evt.device}"
for (int i = 1; i <= vNumber; i++){
if (evt.deviceId == settings["virtual${i}"].id) {
physical."${evt.value}${i}"()
}
}
}
def physicalHandler(evt) {
log.debug "physicalHandler called with event: name:${evt.name} source:${evt.source} value:${evt.value} isStateChange: ${evt.isStateChange()} isPhysical: ${evt.isPhysical()} isDigital: ${evt.isDigital()} data: ${evt.data} device: ${evt.device}"
for (int i = 1; i <= vNumber; i++){
if (evt.name == "switch${i}") {
try {
sendEvent(settings["virtual${i}"], [name:"switch", value:"$evt.value", type:"physical"])
} catch (e) {
log.trace "Caught error: Likely caused by not using my specialized Simulated Switches"
log.trace e
settings["virtual${i}"]."${evt.value}Physical"()
}
}
}
}
These devices were cheaper and more available but seems to be a bit more difficult to find now. Amazon does not have it and the only place where I could get them was at Fasttech: ORVIBO ZigBee Smart Home Multi-functional Remote Control Relay
Please let me know if this works for you and if you can make the virtual device also act as momentary switch.