Aeon Smartstrip driver update?

Here is a solution that works for me:

Create the parent and child device drivers in the "Drivers code" section of your hub interface, using the codes below:

  1. Driver for the parent device
/*
*  Zooz ZEN20 Power Strip turned into a driver for Aeotec's
*/
metadata {
    definition (name: "Aeotec SmartStrip for Hubitat", namespace: "hubitat", author: "hubitat, denise.grider and elfege") {
        capability "Switch"
        capability "Energy Meter"
        capability "Power Meter"
        capability "Refresh"
        capability "Configuration"
        capability "Actuator"
        capability "Sensor"
        capability "Temperature Measurement"
        capability "Health Check"

        command "reset"


        command "childOn"
        command "childOff"
        command "recreateChildDevices"

        fingerprint manufacturer: "0086", prod: "0003", model: "000B", deviceJoinName: "Zooz ZEN20 Power Strip"
        fingerprint deviceId: "0x1001", inClusters: "0x25,0x32,0x27,0x70,0x85,0x72,0x86,0x60", outClusters: "0x82"

    }
}

	// simulator metadata
	simulator {
		status "on":  "command: 2003, payload: FF"
		status "off":  "command: 2003, payload: 00"
		status "switch1 on": "command: 600D, payload: 01 00 25 03 FF"
		status "switch1 off": "command: 600D, payload: 01 00 25 03 00"
		status "switch4 on": "command: 600D, payload: 04 00 25 03 FF"
		status "switch4 off": "command: 600D, payload: 04 00 25 03 00"
		status "power": new hubitat.zwave.Zwave().meterV1.meterReport(
		        scaledMeterValue: 30, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage()
		status "energy": new hubitat.zwave.Zwave().meterV1.meterReport(
		        scaledMeterValue: 200, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage()
		status "power1": "command: 600D, payload: 0100" + new hubitat.zwave.Zwave().meterV1.meterReport(
		        scaledMeterValue: 30, precision: 3, meterType: 4, scale: 2, size: 4).format()
		status "energy2": "command: 600D, payload: 0200" + new hubitat.zwave.Zwave().meterV1.meterReport(
		        scaledMeterValue: 200, precision: 3, meterType: 0, scale: 0, size: 4).format()

		// reply messages
		reply "2001FF,delay 100,2502": "command: 2503, payload: FF"
		reply "200100,delay 100,2502": "command: 2503, payload: 00"
	}

preferences {
    input("enableDebugging", "bool", title:"Enable Debugging")
}

def installed() {
    logging("installed")
    createChildDevices()
    configure()
}

def updated() {
    logging("updated")

    if (!childDevices) {
        createChildDevices()
    }
    else if (device.label != state.oldLabel) {
        childDevices.each {
            def newLabel = "$device.displayName (CH${channelNumber(it.deviceNetworkId)})"
            it.setLabel(newLabel)
        }

        state.oldLabel = device.label
    }

    configure()
}

def configure() {
    state.enableDebugging = settings.enableDebugging
    logging("configure()")
    sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
    def cmds = [
        // Configuration of what to include in reports and how often to send them (if the below "change" conditions are met
        // Parameter 101 & 111: Send energy reports every 60 seconds (if conditions are met)
        // Parameter 102 & 112: Send power reports every 60 seconds (if conditions are met)
        zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, configurationValue: [0,0,0,127]).format(),
        zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, configurationValue: [0,0,127,0]).format(),
        zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 60).format(),
        zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 60).format(),
    ]
    [5, 6, 7, 8, 9, 10, 11].each { p ->
        // Send power reports at the time interval if they have changed by at least 1 watt
        cmds << zwave.configurationV1.configurationSet(parameterNumber: p, size: 2, scaledConfigurationValue: 100).format()
    }
    [12, 13, 14, 15, 16, 17, 18].each { p ->
        // Send energy reports at the time interval if they have changed by at least 5%
        cmds << zwave.configurationV1.configurationSet(parameterNumber: p, size: 1, scaledConfigurationValue: 50).format()
    }
    cmds += [
        // Parameter 4: Induce automatic reports at the time interval if the above conditions are met to reduce network traffic 
        zwave.configurationV1.configurationSet(parameterNumber: 4, size: 1, scaledConfigurationValue: 100).format(),
        // Parameter 80: Enable to send automatic reports to devices in association group 1
        zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, scaledConfigurationValue: 2).format(),
    ]

    delayBetween(cmds, 1000) + "delay 5000" + refresh()
}

def refresh() {
    logging("refresh")
    def cmds = [
        zwave.basicV1.basicGet().format(),
        zwave.meterV3.meterGet(scale: 0).format(),
        zwave.meterV3.meterGet(scale: 2).format(),
        encap(zwave.basicV1.basicGet(), 1)  // further gets are sent from the basic report handler
    ]
    cmds << encap(zwave.switchBinaryV1.switchBinaryGet(), null)
    (1..4).each { endpoint ->
        cmds << encap(zwave.switchBinaryV1.switchBinaryGet(), endpoint)
    }
    (1..6).each { endpoint ->
        cmds << encap(zwave.meterV2.meterGet(scale: 0), endpoint)
        cmds << encap(zwave.meterV2.meterGet(scale: 2), endpoint)
    }
    [90, 101, 102, 111, 112].each { p ->
        cmds << zwave.configurationV1.configurationGet(parameterNumber: p).format()
    }
    delayBetween(cmds, 1000)
}

def recreateChildDevices() {
    logging("recreateChildDevices")
    deleteChildren()
    createChildDevices()
}

def deleteChildren() {
    logging("deleteChildren")
    def children = getChildDevices()

    children.each {child->
        deleteChildDevice(child.deviceNetworkId)
    }
}


def parse(String description) {

    state.enableDebugging = settings.enableDebugging

    def result = []
    if (description.startsWith("Err")) {
        result = createEvent(descriptionText:description, isStateChange:true)
    } else if (description != "updated") {
        def cmd = zwave.parse(description, [0x60: 3, 0x32: 3, 0x25: 1, 0x20: 1])
        logging("Command: ${cmd}")
        if (cmd) {
            result += zwaveEvent(cmd, null)
        }
    }

    def statusTextmsg = ""
    if (device.currentState('power') && device.currentState('energy')) statusTextmsg = "${device.currentState('power').value} W ${device.currentState('energy').value} kWh"
    sendEvent(name:"statusText", value:statusTextmsg, displayed:false)

    logging("parsed '${description}' to ${result.inspect()}")

    result

}


def resetCmd(endpoint = null) {
    logging("resetCmd($endpoint)")
    delayBetween([
        encap(zwave.meterV2.meterReset(), endpoint),
        encap(zwave.meterV2.meterGet(scale: 0), endpoint)
    ])
}

def reset() {
    logging("reset()")
    delayBetween([resetCmd(null), reset1(), reset2(), reset3(), reset4(), reset5(), reset6()])
}

def reset1() { resetCmd(1) }
def reset2() { resetCmd(2) }
def reset3() { resetCmd(3) }
def reset4() { resetCmd(4) }
def reset5() { resetCmd(5) }
def reset6() { resetCmd(6) }

def zwaveEvent(hubitat.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd, ep) {
    def encapsulatedCommand = cmd.encapsulatedCommand([0x32: 3, 0x25: 1, 0x20: 1])
    if (encapsulatedCommand) {
        if (encapsulatedCommand.commandClassId == 0x32) {
            // Metered outlets are numbered differently than switches
            Integer endpoint = cmd.sourceEndPoint
            if (endpoint > 2) {
                zwaveEvent(encapsulatedCommand, endpoint - 2)
            } else if (endpoint == 0) {
                zwaveEvent(encapsulatedCommand, 0)
            } else if (endpoint == 1 || endpoint == 2) {
                zwaveEvent(encapsulatedCommand, endpoint + 4)
            } else {
                log.debug "Ignoring metered outlet ${endpoint} msg: ${encapsulatedCommand}"
                []
            }
        } else {
            zwaveEvent(encapsulatedCommand, cmd.sourceEndPoint as Integer)
        }
    }
}

def endpointEvent(endpoint, map) {
    logging("endpointEvent($endpoint, $map)")
    if (endpoint) {
        map.name = map.name + endpoint.toString()
    }
    createEvent(map)
}

def zwaveEvent(hubitat.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
    logging("multichannelv3.MultiChannelCmdEncap $cmd")
    // def encapsulatedCommand = null//cmd.encapsulatedCommand([0x25: 1, 0x20: 1]) // throws "java.lang.IndexOutOfBoundsException: toIndex = 8 on line 109 (parse)"

    def encapsulatedCommand = cmd.encapsulatedCommand([0x32: 3, 0x25: 1, 0x20: 1])
    logging("encapsulatedCommand: $encapsulatedCommand")

    if (encapsulatedCommand) {
        return zwaveEvent(encapsulatedCommand, cmd.sourceEndPoint as Integer)
    } else {
        logging("Unable to get encapsulated command: $encapsulatedCommand")
        return []
    }
}

def zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd, endpoint = null) {
    logging("basicv1.BasicReport $cmd, $endpoint")
    zwaveBinaryEvent(cmd, endpoint, "digital")
}

def zwaveEvent(hubitat.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd, endpoint = null) {
    logging("switchbinaryv1.SwitchBinaryReport $cmd, $endpoint")
    zwaveBinaryEvent(cmd, endpoint, "physical")
}

def zwaveBinaryEvent(cmd, endpoint, type) {
    logging("zwaveBinaryEvent cmd $cmd, endpoint $endpoint, type $type")
    def childDevice = childDevices.find{it.deviceNetworkId.endsWith("$endpoint")}
    def result = null

    if (childDevice) {
        logging("childDevice.sendEvent $cmd.value")
        childDevice.sendEvent(name: "switch", value: cmd.value ? "on" : "off", type: type)
    } else {
        result = createEvent(name: "switch", value: cmd.value ? "on" : "off", type: type)
    }

    result
}

def zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
    logging("manufacturerspecificv2.ManufacturerSpecificReport cmd $cmd")
    updateDataValue("MSR", String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId))
}

def zwaveEvent(hubitat.zwave.commands.configurationv2.ConfigurationReport cmd, ep) {
    def temperatureEvent
    if (cmd.parameterNumber == 90) { 
        def temperature = convertTemp(cmd.configurationValue)
        if(getTemperatureScale() == "C"){
            temperatureEvent = [name:"temperature", value: Math.round(temperature * 100) / 100]
        } else {
            temperatureEvent = [name:"temperature", value: Math.round(celsiusToFahrenheit(temperature) * 100) / 100]
        }
        state.lastTempReport = now()
    } else {
        //log.debug "${device.displayName} parameter '${cmd.parameterNumber}' with a byte size of '${cmd.size}' is set to '${cmd.configurationValue}'"
    }
    if (temperatureEvent) { 
        createEvent(temperatureEvent) 
    }
}

def convertTemp(value) {
    def highbit = value[0]
    def lowbit = value[1]

    if (highbit > 127) highbit = highbit - 128 - 128
    lowbit = lowbit * 0.00390625

    return highbit+lowbit
}

def zwaveEvent(hubitat.zwave.commands.configurationv1.ConfigurationReport cmd) {
    logging("configurationv1.ConfigurationReport: parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}")
}

def zwaveEvent(hubitat.zwave.commands.versionv1.VersionReport cmd, endpoint) {
    logging("versionv1.VersionReport, applicationVersion $cmd.applicationVersion, cmd $cmd, endpoint $endpoint")
}

def zwaveEvent(hubitat.zwave.Command cmd, endpoint) {
    logging("${device.displayName}: Unhandled ${cmd}" + (endpoint ? " from endpoint $endpoint" : ""))
}

def zwaveEvent(hubitat.zwave.Command cmd) {
    logging("${device.displayName}: Unhandled ${cmd}")
}

def on() {
    logging("on")
    def cmds = []
    cmds << zwave.basicV1.basicSet(value: 0xFF).format()
    cmds << zwave.basicV1.basicGet().format()
    logging("cmds = $cmds")

    (1..5).each { endpoint ->
        cmds << encap(zwave.basicV1.basicSet(value: 0xFF), endpoint)
        cmds << encap(zwave.basicV1.basicGet(), endpoint)
    }

    return delayBetween(cmds, 1000)
}

def off() {
    logging("off")
    def cmds = []
    cmds << zwave.basicV1.basicSet(value: 0x00).format()
    cmds << zwave.basicV1.basicGet().format()

    (1..5).each { endpoint ->
        cmds << encap(zwave.basicV1.basicSet(value: 0x00), endpoint)
        cmds << encap(zwave.basicV1.basicGet(), endpoint)
    }

    return delayBetween(cmds, 1000)
}

def childOn(String dni) {
    onOffCmd(0xFF, channelNumber(dni))
}

def childOff(String dni) {
    onOffCmd(0, channelNumber(dni))
}

private onOffCmd(value, endpoint) {
    logging("onOffCmd, value: $value, endpoint: $endpoint")

    def cmds = []
    cmds << encap(zwave.basicV1.basicSet(value: value), endpoint)
    cmds << encap(zwave.basicV1.basicGet(), endpoint)

    return delayBetween(cmds, 1000)
}

private channelNumber(String dni) {
    def ch = dni.split("-")[-1] as Integer
    return ch
}

private void createChildDevices() {
    logging("createChildDevices")

    for (i in 1..4) {
        addChildDevice("hubitat", "Zooz Power Strip Outlet", "$device.deviceNetworkId-$i", [name: "ch$i", label: "$device.displayName $i", isComponent: true])
    }
}


private encap(cmd, endpoint) {
    if (endpoint) {
        if (cmd.commandClassId == 0x32) {
            // Metered outlets are numbered differently than switches
            if (endpoint == 5 || endpoint == 6) {
                endpoint -= 4
            }
            else if (endpoint < 0x80) {
                endpoint += 2
            } else {
                endpoint = ((endpoint & 0x7F) << 2) | 0x80
            }
        }
        zwave.multiChannelV3.multiChannelCmdEncap(destinationEndPoint:endpoint).encapsulate(cmd).format()
    } else {
        cmd.format()
    }
}


private def logging(message) {
    //log.debug "state.enableDebugging = $state.enableDebugging"
    if (state.enableDebugging == true) log.debug message
}
  1. Child devices driver:
/*
 *  Zooz Power Strip Outlet
 */
metadata {
    definition (name: "Zooz Power Strip Outlet", namespace: "hubitat", author: "hubitat") {
        capability "Switch"
        capability "Actuator"
        capability "Sensor"
    }
}



void on() { 
    log.debug "$device on"    
    parent.childOn(device.deviceNetworkId)
    sendEvent(name: "switch", value: "on")
}

void off() {
    log.debug "$device off"
    sendEvent(name: "switch", value: "off")
    parent.childOff(device.deviceNetworkId)
}
1 Like