Orvibo Zigbee Relay RL804QZB

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.