Independent Dual Receptacle Control

Has anyone figured out how to independently control both receptacles on a single Z-Wave wall outlet? Currently I’m using a combination of a GE Z-Wave outlet with a GE 45603 appliance module. The problem is that the whole setup is way too bulky and in order to gain access to the outlet button, I need to add a spacer between the appliance module and outlet.

There are the requirements I’d like to have:

  1. Each receptacle be independently controlled.
  2. Each receptacle have a button for local control.
  3. Not be so damn bulky.

To the best of my knowledge there are no receptacles that have both sockets controlled by Z-wave, let alone two that are independently controllable. I believe they are all one z-wave controlled, the other always on. There was some discussion about this once in the past and IIRC the prevailing theory was that it was a code issue that required at least one socket always be hot.

And yeah, I agree when you want two in one spot it makes it bulky.

You can do it with this ZigBee device. I have it connected to a two plug outlet so it switches two 110v AC loads on and off. You will have to write a custom device type that is aware of this plugs two on/off end nodes. I have one written and it works great in my SmartThings app would be happy to share if it helps.

Just a ping here. Do you have a link to the device that you referenced above?

@JohnR , I should have done a search before posting my question below. Can you tell me how ST sees this device? Does it see it as 1 device, or did you have to include each relay to get 2 devices in ST? I’m seriously considering this, so any help would be great. I also wouldn’t mind getting a copy of your custom device type if you don’t mind.

SmartThings sees it as one device. The relays are on unique ZigBee end points. Here is my custom device type:

>  *  Custom Device type for SmartenIT Dual-Relay Controller
>  *
>  *  Copyright 2014
>  *
>  *  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:
>  *
>  *
>  *
>  *  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: "Dual-Relay Controller", namespace: "JohnRucker", author: "") {
>         capability "Refresh"
>         capability "Polling"
>         capability "Sensor"
>         capability "Configuration"
>         capability "Switch"

>         command "on2"
>         command "off2"

>         attribute "switch2","ENUM", ["on","off"]

>     	//fingerprint profileId: "0104", inClusters: "0000", outClusters: "000D,0006"
>         fingerprint inClusters: "0000 0001 0003 0004 0005 0006", endpointId: "01", deviceId: "0100", profileId: "0104"

> 	}

> 	// simulator metadata
> 	simulator {
>     }

> 	// UI tile definitions
> 	tiles {

> 		standardTile("switch1", "device.switch", width: 2, height: 2, canChangeIcon: true) {
> 			state "off", label: '${name}', action: "Switch.on", icon: "", backgroundColor: "#ffffff"
> 			state "on", label: '${name}', action: "", icon: "st.switches.switch.on", backgroundColor: "#79b821"
> 		}

> 		standardTile("switch2", "device.switch2", width: 2, height: 2, canChangeIcon: true) {
> 			state "off", label: '${name}', action: "on2", icon: "", backgroundColor: "#ffffff"
> 			state "on", label: '${name}', action: "off2", icon: "st.switches.switch.on", backgroundColor: "#79b821"
> 		}

>         standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") {
> 			state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
> 		}

> 		main (["switch1", "switch2"])
> 		details (["switch1", "switch2", "refresh"])
> 	}
> }

> // Parse incoming device messages to generate events
> def parse(String description) {
>     log.debug "Parse description $description"
>     def name = null
>     def value = null

>     if (description?.startsWith("catchall: 0104 0006 01")) {
>         log.debug "On/Off command received from EP 1"
>         if (description?.endsWith(" 01 0140 00 38A8 00 00 0000 01 01 0000001000")){
>         	name = "switch"
>             value = "off"}
>         else if (description?.endsWith(" 01 0140 00 38A8 00 00 0000 01 01 0000001001")){
>         	name = "switch"
>             value = "on"}                        
>     }  
>     else if (description?.startsWith("catchall: 0104 0006 02")) {
>         log.debug "On/Off command received from EP 2"    
>         if (description?.endsWith(" 01 0140 00 38A8 00 00 0000 01 01 0000001000")){
>         	name = "switch2"
>             value = "off"}
>         else if (description?.endsWith(" 01 0140 00 38A8 00 00 0000 01 01 0000001001")){
>         	name = "switch2"
>             value = "on"}
>     }

> 	def result = createEvent(name: name, value: value)
>     log.debug "Parse returned ${result?.descriptionText}"
>     return result
> }

> // Commands to device

> def on() {
> 	log.debug "Relay 1 on()"
> 	sendEvent(name: "switch", value: "on")
> 	"st cmd 0x${device.deviceNetworkId} 0x01 0x0006 0x1 {}"
> }

> def off() {
> 	log.debug "Relay 1 off()"
> 	sendEvent(name: "switch", value: "off")
> 	"st cmd 0x${device.deviceNetworkId} 0x01 0x0006 0x0 {}"
> }

> def on2() {
> 	log.debug "Relay 2 on()"
> 	sendEvent(name: "switch2", value: "on")
> 	"st cmd 0x${device.deviceNetworkId} 0x02 0x0006 0x1 {}"
> }

> def off2() {
> 	log.debug "Relay 2 off()"
> 	sendEvent(name: "switch2", value: "off")
> 	"st cmd 0x${device.deviceNetworkId} 0x02 0x0006 0x0 {}"
> }

> def poll(){
> 	log.debug "Poll is calling refresh"
> 	refresh()
> }

> def refresh() {
> 	log.debug "sending refresh command"
>     def cmd = []

>     cmd << "st rattr 0x${device.deviceNetworkId} 0x01 0x0006 0x0000"	// Read on / off value at End point 0x01 
>     cmd << "delay 150"

>     cmd << "st rattr 0x${device.deviceNetworkId} 0x02 0x0006 0x0000"	// Read on / off value at End point 0x02 

>     cmd
> }

> def configure() {
> 	log.debug "Binding SEP 0x01 and 0x02 DEP 0x01 Cluster 0x0006 On / Off cluster to hub" 
>     def cmd = []
>     cmd << "zdo bind 0x${device.deviceNetworkId} 0x01 0x01 0x0006 {${device.zigbeeId}} {}"	// Bind on/off output to SmartThings hub for end point 1
>     cmd << "delay 150"
>     cmd << "zdo bind 0x${device.deviceNetworkId} 0x02 0x01 0x0006 {${device.zigbeeId}} {}" 	// Bind on/off output to SmartThings hub for end point 2
>     cmd
> }

So how does one subscribe to, or control the second outlet from a standard app? When you are connecting to the capability.switch, it will not see the switch2, correct? Or am I missing something?

Oh, and by the way, I think the new Quirky-GE outlet is dual controlled outlet using zigbee.

@wackware That’s what I’m trying to understand as well. I remember reading last night about including relay 1 and then 2, but I wasn’t sure how ST would see each one: (per their docs)

  1. Binding
    To bind Relay1 or Relay 2 to a ZigBee controller, press and hold the Program Button once on the ZBLC15 for 3 seconds or until you get a single blink on the Bind LED. Within 5 seconds, tap the Program Button once to bind to Relay 1 or twice for Relay 2. Now, press the Program Button on the client device (such as a switch) according to the instructions of that device.

Take a look at my Aeon Power Strip Binder smartapp (It’s shared in the IDE). I have an AEON power strip that has custom capabilities for the 4 switchable outlets (on1, off1, on2, off2, etc).

The Binder SmartApp “binds” a virtual switch to each outlet. When the virtual switch turns on or off, it turns on or off the associated outlet on the strip. The virtual on/off tile obviously has the standard capability.switch, so you can use that in any standard SmartApp.

1 Like

I see, you worked around it by using the virtual rendition of each outlet. Don’t you end up with 7 devices for a 4 outlet strip?

In the quirky powerstrip, I created a device for each individual outlet directly. So no on2, off2, etc. It works out well that way.

1 Like

Would it be possible to make this so when you pressed The tile on your app to an ON state it sent a momentary style connection from relay one and when you pressed the tile on your app back to an off state it would send s momentary style connection from relay two ?

I need it to control and up/down motor for my tv bed lift mechanism through an rf remote with the up/down buttons wired to a dual zigbee relay . . . so i need it to replicate momentary button presses for up/down using the dual relays (one for the up botton / one for the down button)


In the code above (from your post above), I notice you immediately call sendEvent() with the presumed new State of the Switch.

Isn’t this atypical of a Device Handler’s Commands; since the Device itself will send a response indicating whether or not the Switch was actually turned on or off?

For example; here is the equivalent code section for a standard SmartThings Centralite Outlet:

(Notice there is no “sendEvent()” method calls: In other words, it seems “improper” to have your Device Type Handler assume that the Switch State has changed just because the Command was issued.

Although, I don’t know the full function of the zigbee.on/off() methods; I presume they do not block waiting for confirmed response from the Device, right?

So the above SmartThings Outlet, for example, and as typical of most of the Switch DTH, actually represent an interim State in the UI (i.e., “turningOn”, “turningOff”) and the DTH waits for an event to be sent from the Device to parse(), which, in turn, sets the SmartThings Switch State from “turningOn” to actual “On” (etc.).

The reason this is important at this stage in my coding, is I don’t know what Cluster and/or Command should be sent from the Device to indicate that the Switch is now on or off.

Using the OutCluster for 0x0006 seems incorrect; since that is being used as the message that the “physical” Switch/Button was activated, which is not true in this case.


  • "st cmd 0x${device.deviceNetworkId} 0x08 0x0006 0x1 {}" sends the “turn on Switch” command to the Device.

  • my Device currently responds with a Command 0x0B (“Default Response”): "[raw:0104 0006 08 01 0100 00 8719 00 00 0000 0B 01 0100, profileId:0104, clusterId:0006, clusterInt:6, sourceEndpoint:08, destinationEndpoint:01, options:0100, messageType:00, dni:8719, isClusterSpecific:false, isManufacturerSpecific:false, manufacturerId:0000, command:0B, direction:01, data:[01, 00]]"

That response is sufficient for me to determine that the Command was received, but it does not confirm that the Device actually turned the Switch on.

Is there a Cluster / Command which indicates that a Switch Device has changed from Off to On, but not with a physical press?

This perhaps is a more general Topic regarding the source and meaning of “isPhysical()” and I’ll look at more DTH examples to see if I can figure out what messages they are receiving, but maybe something here is obvious. Thanks.

Oh man you are going back in time. I agree, the send event signaling the switch is on even though it may not be, is not a good practice. If I recall correctly, I don’t think I was getting the acknowledgement back from the relay for both switches so I couldn’t parse it and instead of troubleshooting the problem I just left it as is.

Here is what I think is the correct way to do this: My CoopBoss custom device type, has two buttons that turn on and off relays connected to the Aux port on the CoopBoss CPU. When you push the button it changes to “Sent” state, the button truns orange and says Sent. Here is what the tiles look like.

	standardTile("aux1", "device.Aux1", width: 2, height: 2, canChangeIcon: true) {
		state "off", label:'Aux 1', action:"Aux1On", icon:"", backgroundColor:"#ffffff", nextState:"Sent"        
		state "on", label:'Aux 1', action:"Aux1Off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"Sent"
		state "Sent", label: 'wait', icon: "", backgroundColor: "#ffa81e"            
	standardTile("aux2", "device.Aux2", width: 2, height: 2, canChangeIcon: true) {
		state "off", label:'Aux 2', action:"Aux2On", icon:"", backgroundColor:"#ffffff", nextState:"Sent"        
		state "on", label:'Aux 2', action:"Aux2Off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"Sent"
		state "Sent", label: 'wait', icon: "", backgroundColor: "#ffa81e"   

As you can see aux1 calls a method called Aux1On to send the on command. Here is the method:

 def Aux1On(){
 	log.debug "Sending Aux1 = on command"
 	"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x14 {}"             

Short and sweet. Now to change the button tile from the “Sent” state to the “on” state I wait for the CoopBoss to send back an acknowledgement for the on command. Here is that bit from my parse method:

if (cluster.clusterId == 0x0101 && cluster.command == 0x0b) {		// This is a default response to a command sent to cluster 0x0101 door control
	//log.debug "Default Response Data = $"
    switch( {
    case "[20, 0]":		// 0x14 Aux1 On command verified "verified Aux1 On"
	sendEvent(name: "switch", value: "on", displayed: false) = "Aux1"
    resultMap.value = "on"        

So now the buttons (tiles) always represent the true status of the switches. It looks like your thinking about doing the same thing in your code (keying on the acknowledgement). I think that is the right thing to do! A device should not send an acknowledgment of a command unless that command was actually carried out.

1 Like

Thanks very much for the response, John.

There’s one part that I’m still a bit unsure about and that is the response “cluster.Command”. You said you get (use sufficiently use, parse, etc.) Command “0x0b”. I can certainly do the same.

But from a ZigBee standard viewpoint, is there some standard Cluster or Command that can or should be sent from the Device?

  1. i.e., When I physically activate the Switch Button on the Device, it sends a “0x0600-0x02” (i.e., Switch-Toggle). That makes it like a “remote control”. I can also have that command locally process the Button and turn on the relay (just an LED at the moment).

  2. But I also support the opposite direction … SmartThings sends an on/off/toggle to the Device, and that, in turn, activates the relay/LED.

In Case #2, it is incorrect for the Device to send back a “0x0600-0x00” (or 0x01, or 0x02), to indicate the new state of the “Switch”, because that implies the Switch Button was physically pressed. So that leaves us with the generic “Default Response Command” “0x0b”.

Is there something “non-generic” that is applicable or more appropriate in this situation?

(And even if the default response is sufficient and accuate, that does leave open the question of what to send back if the Device is unable to activate the Relay, even if it successfully “received” the command.)

When SmartThings sends the on command to your device your device is only required to send back an acknowledgement of that command with the original transaction sequence number of the command. SmartThings does not give us access to any of the transaction sequence numbers so there is no way we can truly match up an acknowledgement to a command but that’s not too big of deal (and I don’t want to get off on a tangent).

In general there are three ways your device can report its switch status:

  1. Acknowledge an On command. This is what we have been talking about.
  2. Respond to a read attribute command. This is usually done from the poll method in your custom device type.
  3. Report when it has changed. This requires the device to be bound to the hub and reporting has to be configured and turned on. When reporting is enabled (and the device is correctly bound) it will report based on time or when it changes state. So lets say your device is a relay with a local button on it. You can open and close the relay from SmartThings but also with the local button. So if you close the relay with a command from SmartThings you can track that it actualy happend with the acknowledgement (option 1). However if someone comes along and pushes the local button that is when reporting kicks in. A report will be sent to SmartThings as soon as the person pushes the local button.

What a device should or should not send back is very well defined in the cluster documentation. Here are the details for the On/Off Cluster. Its pretty basic but take a look at some of the other clusters like temperature or the door lock. This document also discuss what to send back if your device can’t carry out the command or the command is not valid.

Your getting deep into it my friend!! Good stuff!!!

1 Like

It sure is!!! !!!

A lot of this is certainly “RTFM” stuff, (or "ZigBee for Dummies"tm?), but your summary and Refs are getting me through this little crunch a heck of a lot faster; thanks!

1 Like

Hey everybody. So i bought a Smartenit ZBLC15 Device and properly wired it to a pair of 220V powerful LED Outdoor Flood Lights.

First of all once i added it to smartthings it appeared as a “Samsung TV” Device type and didnt work at all. I tried looking for Smartenit and never found the device handler. Tried looking online and found some handlers that were made by people in this community. None of them work. At the end i tried ZIGBEE Switch and the tried turning it ON. the device CLICKS but does not send any Electricity through the outputs.

I double checked the manual to see if i was doing something wrong.
step 1 is join the network, i was never able to do this i suppose because i do not have a smartenit Hub. i skipped step 1 and went over to step 2.

Step 2 Binding. here i tried binding relay 1, added it to smartthings and tried to make it work. no good.
Tried the same process with relay 2 and no luck either.

Dont know what else to do. if any one has any ideas please help me out.

First things first: which app are you using, “SmartThings (Samsung Connect)” or “SmartThings Classic”?

The first cannot use ANY custom device type handler as of this writing, and with either app there’s pretty much no way it could mistake a zigbee device for a Samsung television.

Instead, if it was the new app it was probably discovering a neighbor’s tv (creepy, but it’s how the new app works).

Meanwhile, have you verified the specs with your lights? At 220v, it can only handle 10A total.