GE Enbrighten Z-Wave Plus Smart Plug with 2 USB Ports (3.4A Shared), 2 Individually Controlled Outlets

I have the 28175 with 2 Individually Controlled Outlets. I'd like to use this to independently control my 2 Night Stand Lamps. If you "Double Tap" the physical button, outlet 2 will toggle. How would I go about creating drivers that would enable this double tap feature in the HE driver?

1 Like

This post seemed to end awhile back with no resolution, I just ordered my first HE (Switching from Wink) and am hoping to use the GE Enbrighten Plug with 2 Individually Controlled Outlets, Model 28177. IS there a way to make this work? I am new and as I don't even have the HE yet, I have yet to wrap my head around how everything works. Thank you all in advance for your help.

I have this device and it works ok. I sometimes get weird reporting from it.

You have to select the device type as Generic Zwave Smart Dimmer. I don't have individual control though of the outlets. It just dims both outlets together.

Picked up a 28175 (ZW3106), GE Two Outlet Smart Dimmer plus Two USB .

28175.EP.07

Found these ST Drivers

Parent

/**

  • GE Smart Dual Channel Dimmer (28175)
  • Author: Thomas Slaymaker (sudoursa)
  • Date: 2018-12-06
  • Copyright 2018 Thomas Slaymaker
  • 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: "Z-Wave GE Dual Dimmer", namespace: "sudoursa", author: "Thomas Slaymaker") {
capability "Switch Level"
capability "Actuator"
capability "Indicator"
capability "Switch"
capability "Polling"
capability "Refresh"
capability "Sensor"
capability "Health Check"

    fingerprint mfr: "0063", prod: "5044", model: "3132", deviceJoinName: "Z-Wave GE Dual Outlet Dimmer"
}

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", nextState: "turningOff"
            attributeState "off", label: '${name}', action: "switch.on",
                    icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
            attributeState "turningOn", label: '${name}', action: "switch.off",
                    icon: "st.switches.switch.on", backgroundColor: "#00a0dc", nextState: "turningOff"
            attributeState "turningOff", label: '${name}', action: "switch.on",
                    icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
        }
        tileAttribute("device.level", key: "SLIDER_CONTROL") {
            attributeState "level", action: "switch level.setLevel"
        }
    }

    childDeviceTile("outlet1", "outlet1", height: 2, width: 2, childTileName: "switch")
    childDeviceTile("outlet2", "outlet2", height: 2, width: 2, childTileName: "switch") 
    childDeviceTile("levelSliderControl1", "outlet1", height: 2, width: 2, childTileName: "level")
    childDeviceTile("levelSliderControl2", "outlet2", height: 2, width: 2, childTileName: "level")
    standardTile("refresh", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
        state "default", label: '', action: "refresh.refresh", icon: "st.secondary.refresh"
    }
                  
    main("switch")
    details(["switch", "outlet1", "levelSliderControl1", "refresh", "outlet2", "levelSliderControl2"])
}

}

void installed() {
initialize()
}

private initialize() {
log.debug "initialize()"
// outlet one
addChildDevice(
"Z-Wave GE Dual Dimmer Outlet",
"${device.deviceNetworkId}-ep1",
null,
[completedSetup:true, label:"${device.displayName} (CH1)", isComponent:true, componentName:"outlet1", componentLabel:"Outlet 1"
])
// outlet two
addChildDevice(
"Z-Wave GE Dual Dimmer Outlet",
"${device.deviceNetworkId}-ep2",
null,
[completedSetup:true, label:"${device.displayName} (CH2)", isComponent:true, componentName:"outlet2", componentLabel:"Outlet 2"
])
}

def updated() {
log.debug "Updated with settings: ${settings}"
if (device.label != state.oldLabel) {
childDevices.each {
if (it.label == "${state.oldLabel} (CH${channelNumber(it.deviceNetworkId)})") {
def newLabel = "${device.displayName} (CH${channelNumber(it.deviceNetworkId)})"
it.setLabel(newLabel)
it.save()
}
}
state.oldLabel = device.label
}
}

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.BasicSet cmd, value=null) {
log.debug "BasicSet ${cmd} with a child of ${value}"
def result = createEvent(name: "switch", value: cmd.value ? "on" : "off", type: "digital")
def cmds =
cmds << encap(zwave.switchMultilevelV2.switchMultilevelGet(), 1)
cmds << encap(zwave.switchMultilevelV2.switchMultilevelGet(), 2)
return [result, response(commands(cmds))] // returns the result of response()
}

def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelReport cmd, ep = null) {
log.debug "SwitchMultilevelReport ${cmd} - ep${ep}"
if (ep) {
def event
def childDevice = childDevices.find {
it.deviceNetworkId == "$device.deviceNetworkId-ep$ep"
}
if (childDevice) {
childDevice.sendEvent(name: "switch", value: cmd.value ? "on" : "off")
if (cmd.value && cmd.value <= 100) {
childDevice.sendEvent(name: "level", value: cmd.value == 99 ? 100 : cmd.value)
}
}
if (cmd.value) {
event = [createEvent([name: "switch", value: "on"])]
} else {
def allOff = true
childDevices.each {
n ->
if (n.currentState("switch").value != "off") allOff = false
}
if (allOff) {
event = [createEvent([name: "switch", value: "off"])]
} else {
event = [createEvent([name: "switch", value: "on"])]
}
}
return event
} else {
def result = createEvent(name: "switch", value: cmd.value ? "on" : "off", type: "digital")
def cmds =
cmds << encap(zwave.switchMultilevelV2.switchMultilevelGet(), 1)
cmds << encap(zwave.switchMultilevelV2.switchMultilevelGet(), 2)
return [result, response(commands(cmds))] // returns the result of response()
}
}

def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
log.debug "MultiChannelCmdEncap ${cmd}"
def encapsulatedCommand = cmd.encapsulatedCommand([0x32: 3, 0x25: 1, 0x20: 1])
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand, cmd.sourceEndPoint as Integer)
}
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
log.debug "BasicReport ${cmd} - ep${ep}"
if (ep) {
def event
childDevices.each {
childDevice ->
if (childDevice.deviceNetworkId == "$device.deviceNetworkId-ep$ep") {
childDevice.sendEvent(name: "switch", value: cmd.value ? "on" : "off")
}
}
if (cmd.value) {
event = [createEvent([name: "switch", value: "on"])]
} else {
def allOff = true
childDevices.each {
n ->
if (n.deviceNetworkId != "$device.deviceNetworkId-ep$ep" && n.currentState("switch").value != "off") allOff = false
}
if (allOff) {
event = [createEvent([name: "switch", value: "off"])]
} else {
event = [createEvent([name: "switch", value: "on"])]
}
}
return event
}
}

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
log.error "Unhandled Event: ${cmd}"
[:]
}

def on() {
log.debug "on()"
commands([
zwave.switchAllV1.switchAllOn(),
encap(zwave.switchMultilevelV2.switchMultilevelGet(), 1),
encap(zwave.switchMultilevelV2.switchMultilevelGet(), 2)
])
}

def off() {
log.debug "off()"
commands([
zwave.switchAllV1.switchAllOff(),
encap(zwave.switchMultilevelV2.switchMultilevelGet(), 1),
encap(zwave.switchMultilevelV2.switchMultilevelGet(), 2)
], 3000)
}

def setLevel(value) {
log.debug "setLevel >> value: $value"
def valueaux = value as Integer
def level = Math.max(Math.min(valueaux, 99), 0)
log.debug "both channel setLevel >> value: $value"
if (level > 0) {
sendEvent(name: "switch", value: "on")
} else {
sendEvent(name: "switch", value: "off")
}
sendEvent(name: "level", value: valueaux, unit: "%")
delayBetween([zwave.switchMultilevelV1.switchMultilevelSet(value: level).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def refresh() {
log.debug "refresh()"
commands([
encap(zwave.switchMultilevelV2.switchMultilevelGet() , 1),
encap(zwave.switchMultilevelV2.switchMultilevelGet() , 2),
])
}

def poll() {
log.debug "poll()"
commands([
encap(zwave.switchMultilevelV2.switchMultilevelGet(), 1),
encap(zwave.switchMultilevelV2.switchMultilevelGet(), 2),
])
}

def ping() {
log.debug "ping()"
refresh()
}

//child device methods
void childSetLevel(value, String dni) {
log.debug "childSetLevel($dni,$value)"
def childDevice = childDevices.find {
it.deviceNetworkId == "$dni"
}
def valueaux = value as Integer
def level = Math.max(Math.min(valueaux, 99), 0)
if (level > 0) {
childDevice.sendEvent(name: "switch", value: "on")
} else {
childDevice.sendEvent(name: "switch", value: "off")
}
def cmds =
cmds << new physicalgraph.device.HubAction(command(encap(zwave.switchMultilevelV1.switchMultilevelSet(value: level), channelNumber(dni))))
cmds << new physicalgraph.device.HubAction(command(encap(zwave.switchMultilevelV1.switchMultilevelGet(), channelNumber(dni))))
sendHubCommand(cmds, 1000)
}

void childOn(String dni) {
log.debug "childOn($dni)"
def cmds =
cmds << new physicalgraph.device.HubAction(command(encap(zwave.basicV1.basicSet(value: 0xFF), channelNumber(dni))))
cmds << new physicalgraph.device.HubAction(command(encap(zwave.switchMultilevelV2.switchMultilevelGet(), channelNumber(dni))))
sendHubCommand(cmds, 1000)
}

void childOff(String dni) {
log.debug "childOff($dni)"
def cmds =
cmds << new physicalgraph.device.HubAction(command(encap(zwave.basicV1.basicSet(value: 0x00), channelNumber(dni))))
cmds << new physicalgraph.device.HubAction(command(encap(zwave.switchMultilevelV2.switchMultilevelGet(), channelNumber(dni))))
sendHubCommand(cmds, 1000)

}

void childRefresh(String dni) {
log.debug "childRefresh($dni)"
def cmds =
cmds << new physicalgraph.device.HubAction(command(encap(zwave.switchMultilevelV2.switchMultilevelGet(), channelNumber(dni))))
sendHubCommand(cmds, 1000)
}

// Utility Methods
private encap(cmd, endpoint) {
if (endpoint) {
zwave.multiChannelV3.multiChannelCmdEncap(destinationEndPoint: endpoint).encapsulate(cmd)
} else {
cmd
}
}

private command(physicalgraph.zwave.Command cmd) {
if (state.sec) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}

private commands(commands, delay = 1000) {
delayBetween(commands.collect {
command(it)
}, delay)
}

private channelNumber(String dni) {
dni.split("-ep")[-1] as Integer
}

Child

/**

  • Child Channel
  • Copyright 2017 Thomas Slaymaker
  • 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: "Z-Wave GE Dual Dimmer Outlet", namespace: "sudoursa", author: "Thomas Slaymaker") {
capability "Switch"
capability "Switch Level"
capability "Sensor"
capability "Refresh"
}

tiles(scale: 2) {
    standardTile("switch", "device.switch", width: 2, height: 2) {
		state "off", label:'Off', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
		state "on", label:'On', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff"
		state "turningOn", label:'Turning on', icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState: "turningOff"
		state "turningOff", label:'Turning off', icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState: "turningOn"
	}
	controlTile("level", "device.level", "slider", height: 2, width: 2) {
		state "level", action:"switch level.setLevel", unit: '%'
	}        
    standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
        state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
    }
    main "switch"
    details(["switch", "level", "refresh"])
}

}

void setLevel(value) {
parent.childSetLevel(value, device.deviceNetworkId)
}

void on() {
parent.childOn(device.deviceNetworkId)
}

void off() {
parent.childOff(device.deviceNetworkId)
}

void refresh() {
parent.childRefresh(device.deviceNetworkId)
}

HE is fine with the Child but not with the Parent:

Errors

unable to resolve class physicalgraph.zwave.commands.basicv1.BasicSet @ line 112, column 16. unable to resolve class physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelReport @ line 121, column 16. unable to resolve class physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap @ line 159, column 16. unable to resolve class physicalgraph.zwave.commands.basicv1.BasicReport @ line 167, column 16. unable to resolve class physicalgraph.zwave.Command @ line 195, column 16. unable to resolve class physicalgraph.device.HubAction @ line 270, column 13. unable to resolve class physicalgraph.device.HubAction @ line 271, column 13. unable to resolve class physicalgraph.device.HubAction @ line 278, column 13. unable to resolve class physicalgraph.device.HubAction @ line 279, column 13. unable to resolve class physicalgraph.device.HubAction @ line 286, column 13. unable to resolve class physicalgraph.device.HubAction @ line 287, column 13. unable to resolve class physicalgraph.device.HubAction @ line 295, column 13. unable to resolve class physicalgraph.zwave.Command @ line 309, column 17.

@JasonJoelOld is this a candidate for porting to HE?

Everywhere it says physicalgraph change it to hubitat.

May be that easy.

1 Like

Thanks, seems better but now it's choking on the tile section

DeviceTile error

No signature of method: Script1.childDeviceTile() is applicable for argument types: (java.util.LinkedHashMap, java.lang.String, java.lang.String) values: [[height:2, width:2, childTileName:switch], outlet1, outlet1]

Sooo... found this:

Which certainly sounds easy (and probably is for some people). :face_with_raised_eyebrow:

Time for some googling.

1 Like

Disregard. Looking at wrong code.

I believe all of that needs to go.

1 Like

Hah, got it to save.

And thanks for the info, now to see if it works. :grinning:

Cut Tile code
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", nextState: "turningOff"
            attributeState "off", label: '${name}', action: "switch.on",
                    icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
            attributeState "turningOn", label: '${name}', action: "switch.off",
                    icon: "st.switches.switch.on", backgroundColor: "#00a0dc", nextState: "turningOff"
            attributeState "turningOff", label: '${name}', action: "switch.on",
                    icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
        }
        tileAttribute("device.level", key: "SLIDER_CONTROL") {
            attributeState "level", action: "switch level.setLevel"
        }
    }

    childDeviceTile("outlet1", "outlet1", height: 2, width: 2, childTileName: "switch")
    childDeviceTile("outlet2", "outlet2", height: 2, width: 2, childTileName: "switch") 
    childDeviceTile("levelSliderControl1", "outlet1", height: 2, width: 2, childTileName: "level")
    childDeviceTile("levelSliderControl2", "outlet2", height: 2, width: 2, childTileName: "level")
    standardTile("refresh", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
        state "default", label: '', action: "refresh.refresh", icon: "st.secondary.refresh"
    }
                  
    main("switch")
    details(["switch", "outlet1", "levelSliderControl1", "refresh", "outlet2", "levelSliderControl2"])
}

Edit: It works, sort of, but no better than the generic driver and certainly doesn't give individual control of the outlets.

1 Like

Tagging @bcopeland from Hubitat, as he seems to be able to crank out Z-wave device drivers very quickly. :sunglasses:

4 Likes

:eyes:

3 Likes

It was worth a try. I do not know any specifics of his device. Is it capable of indepemdant control of the sockets?

1 Like

If the ST DTH creates child device(s), that section of code will also require some edits as Hubitat’s call to addChildDevice is slightly different than ST’s, IIRC.

2 Likes

2 Individually Controlled Z-Wave Outlets and 2 Always On USB Ports

So yes.. I’ll get a driver for it..

6 Likes

Perfect, thanks Bryan. :+1:

28175 Discovery

3 Likes

@bcopeland... did you ever get a driver for this device?

I got the device in.. Still in the box I’m afraid.. Been crazy busy..

3 Likes

@bcopeland ... totally understand the "been crazy busy". Is there a Paypal account I can contribute to get this to the top of the To Do list? :slight_smile:

At the moment, I am kinda more interested in contributing to something to get the C-7 issues resolved. :slight_smile:

Given the firestorm a few days ago, I suspect @bcopeland needs someone who can slow down time so he can get more done and still get some sleep. :smiley:

I just appreciate how responsive everyone has been!!!

1 Like

I also have the GE 3106 and can’t find a driver that works. Has anybody figured this out yet?