Aeon Smart Energy Switch 6 (gen5) + DSC06106

I’ll give that a try but so far jbisson has not replied to any of the updates in this thread.

Yeah, sorry guys, been very busy but I’m alive (that’s the good news :P) I’ll try to fix all of the issues that people brought up either today or tomorrow, in the mean time, could you share what you’ve changed and I could integrate it as part of the new fixes?

1 Like

No worries. I didn’t want to step on your toes.

Here’s my complete code … Like I said, I’ve not solved all issues but I think I’ve improved things.

PART ONE (too big to post in one go)

/**
 *
 *  Aeon Smart Energy Switch 6 (gen5)
 *
 *  Copyright 2017 jbisson
 *  based on James P ('elasticdev'), Mr Lucky, lg kahn code.
 *
 *
 *  The brightness intensity only works in energy mode (does not work in nightlight mode)
 *  You can only change the led color in nightlight mode
 *
 *  The energy cost (current) represent the amount of money you'll pay if the current load stay the same all the time
 *  vs
 *  The energy cost (cumulative) is the amount of money you'll pay based on the amount of energy used between now and
 *  the last time you did a reset. You can clear this counter by hitting the reset icon.
 *  This will take into account the variable aspect of your energy consumption.
 *
 *
 *
 * If you are pairing in secure inclusive mode, make sure you turn it on in the config page.
 *
 *
 *  Revision History
 *  ==============================================
 *  2017-09-02 Version 5.1.6  More display clean-up and fixed reversed ranges on min watts/percent change in report prefs (Nezmo)
 *  2017-08-15 Version 5.1.5  Cleaned-up display for iOS and other display issues (Nezmo)
 *  2017-02-24 Version 5.1.4  Bug fixed around getDeviceInfo
 *  2017-01-21 Version 5.1.0  Added energy meter cost per hours/week/month/year feature, fixed display issues
 *  2016-11-13 Version 5.0.0  Added Z-Wave secure inclusion support (note that you'll need to manually set it up during configuration)
 *  2016-11-12 Version 4.0.5  Added AT&T rebrand fingerprint + added force refresh report notification update preference
 *  2016-08-31 Version 4.0.4  Fixed fingerprint number.
 *  2016-08-15 Version 4.0.3  Fixed setcolor logic when using the Color Control capability
 *  2016-08-12 Version 4.0.2  Added version in preference setting
 *  2016-08-11 Version 4.0.1  Added switch disabled visual on the main tile, added firmware version
 *  2016-08-11 Version 4.0.0  Added log preference, enable/disable switch preference, added dev documentation, changed fingerprint
 *  2016-08-08 Version 3.0.1  Adapt device handler to support gen5 version 3.1
 *  2016-08-08 Version 3.0
 *  2015-09-01 version 2 - lg kahn
 *
 *
 *  Developer's Notes
 *  Raw Description	0 0 0x1001 0 0 0 11 0x5E 0x25 0x26 0x33 0x70 0x27 0x32 0x81 0x85 0x59 0x72 0x86 0x7A 0x73 0xEF 0x5A 0x82
 *  Z-Wave Supported Command Classes:
 *  Code Name					Version
 *  ==== ======================================	=======
 *  0x5E ??
 *  0x25 COMMAND_CLASS_SWITCH_BINARY          V1                 Implemented
 *  0x26 COMMAND_CLASS_SWITCH_MULTILEVEL      V3 (new in gen5)   Implemented - not used
 *  0x32 COMMAND_CLASS_METER                  V3                 Implemented
 *  0x33 COMMAND_CLASS_COLOR                  V1 (new in gen5)   Not implemented
 *  0x70 COMMAND_CLASS_CONFIGURATION          V1                 Implemented
 *  0x27 COMMAND_CLASS_SWITCH_ALL             V1                 Not implemented
 *  0x81 COMMAND_CLASS_CLOCK                  V1 (new in gen5)   Not implemented
 *  0x85 COMMAND_CLASS_ASSOCIATION            V2                 Not implemented
 *  0x72 COMMAND_CLASS_MANUFACTURER_SPECIFIC  V2                 Implemented
 *  0x59 COMMAND_CLASS_ASSOCIATION_GRP_INFO   V1                 Not implemented
 *  0x86 COMMAND_CLASS_VERSION                V2                 Implemented
 *  0xEF COMMAND_CLASS_MARK                   V1                 Not implemented
 *  0x82 COMMAND_CLASS_HAIL                   V1                 Implemented - not used
 *  0x7A COMMAND_CLASS_FIRMWARE_UPDATE_MD_V2  V2 (new in gen5)   Implemented
 *  0x73 COMMAND_CLASS_POWERLEVEL             V1 (new in gen5)   Not implemented
 *  0x5A COMMAND_CLASS_DEVICE_RESET_LOCALLY   V1 (new in gen5)   Not implemented
 *  0x98 COMMAND_CLASS_SECURITY               V1 (For secure Inclusion) Implemented
 *
 */

def clientVersion() {
    return "5.1.6"
}

metadata {
    definition(name: "Aeon Labs Smart Switch 6", namespace: "Nezmo68", author: "Neil White") {
        capability "Switch"
        capability "Polling"
        capability "Power Meter"
        capability "Energy Meter"
        capability "Refresh"
        capability "Switch Level"
        capability "Sensor"
        capability "Actuator"
        capability "Configuration"
        capability "Color Control"

        command "energy"
        command "momentary"
        command "nightLight"

        command "reset"
        command "factoryReset"
        command "setBrightnessLevel"
        command "getDeviceInfo"

        attribute "deviceMode", "String"

        // Base on https://community.smartthings.com/t/new-z-wave-fingerprint-format/48204
        fingerprint mfr: "0086", prod: "0103", model: "0060" // Aeon brand
        fingerprint mfr: "0134", prod: "0259", model: "0096" // AT&T rebrand
        fingerprint type: "1001", cc: "5E,25,26,33,70,27,32,81,85,59,72,86,7A,73", ccOut: "5A,82"
    }

    tiles(scale: 2) {
        multiAttributeTile(name: "mainPanel", type: "lighting", width: 6, height: 4, canChangeIcon: true) {
            tileAttribute("device.switch", key: "PRIMARY_CONTROL") {
                attributeState "on", label: '${name}', action: "switch.off", icon: "st.Appliances.appliances17", backgroundColor: "#00a0dc", nextState: "turningOff"
                attributeState "off", label: '${name}', action: "switch.on", icon: "st.Appliances.appliances17", backgroundColor: "#ffffff", nextState: "turningOn"
                attributeState "turningOn", label: '${name}', action: "switch.off", icon: "st.Appliances.appliances17", backgroundColor: "#00a0dc", nextState: "turningOff"
                attributeState "turningOff", label: '${name}', action: "switch.on", icon: "st.Appliances.appliances17", backgroundColor: "#ffffff", nextState: "turningOn"
            }
            tileAttribute("statusText3", key: "SECONDARY_CONTROL") {
                attributeState "statusText3", label: '${currentValue}'
            }
        }
        standardTile("deviceMode", "deviceMode", canChangeIcon: true,  canChangeBackground: false, width: 2, height: 2) {
            state "energy", label: 'Energy', action: "momentary", icon: "http://mail.lgk.com/aeonv6orange.png"
            state "momentary", label: 'Moment', action: "nightLight", icon: "http://mail.lgk.com/aeonv6white.png"
            state "nightLight", label: 'Night', action: "energy", icon: "http://mail.lgk.com/aeonv6blue.png"
        }

        valueTile("power", "device.power", width: 2, height: 1, decoration: "flat") {
            state "default", label: '${currentValue} W', backgroundColors:[
				[value: 0, color: "#44b621"],
				[value: 500, color: "#e86d13"],
				[value: 1000, color: "#d04e00"]
			]
        }

        valueTile("energy", "device.energy", width: 2, height: 1, decoration: "flat") {
            state "default", label: '${currentValue} kWh'
        }

        valueTile("amperage", "device.amperage", width: 2, height: 1, decoration: "flat") {
            state "default", label: '${currentValue} A'
        }

        valueTile("voltage", "device.voltage", width: 2, height: 1, decoration: "flat") {
            state "default", label: '${currentValue} V'
        }

        valueTile("currentEnergyCostTxt", "currentEnergyCostTxt", width: 2, height: 1, decoration: "flat") {
            state "default", label: 'Energy Cost\n(Current):'
        }

        valueTile("currentEnergyCostHour", "currentEnergyCostHour", width: 1, height: 1, decoration: "flat") {
            state "default", label: 'Per\nHour\n$${currentValue}'
        }

        valueTile("currentEnergyCostWeek", "currentEnergyCostWeek", width: 1, height: 1, decoration: "flat") {
            state "default", label: 'Per\nWeek\n$${currentValue}'
        }

        valueTile("currentEnergyCostMonth", "currentEnergyCostMonth", width: 1, height: 1, decoration: "flat") {
            state "default", label: 'Per\nMonth\n$${currentValue}'
        }

        valueTile("currentEnergyCostYear", "currentEnergyCostYear", width: 1, height: 1, decoration: "flat") {
            state "default", label: 'Per\nYear\n$${currentValue}'
        }

        valueTile("cumulativeEnergyCostTxt", "cumulativeEnergyCostTxt", width: 2, height: 1, decoration: "flat") {
            state "default", label: 'Energy Cost\n(Cumulative)\nSince ${currentValue}:'
        }

        valueTile("cumulativeEnergyCostHour", "cumulativeEnergyCostHour", width: 1, height: 1, decoration: "flat") {
            state "default", label: 'Per\nHour\n$${currentValue}'
        }

        valueTile("cumulativeEnergyCostWeek", "cumulativeEnergyCostWeek", width: 1, height: 1, decoration: "flat") {
            state "default", label: 'Per\nWeek\n$${currentValue}'
        }

        valueTile("cumulativeEnergyCostMonth", "cumulativeEnergyCostMonth", width: 1, height: 1, decoration: "flat") {
            state "default", label: 'Per\nMonth\n$${currentValue}'
        }

        valueTile("cumulativeEnergyCostYear", "cumulativeEnergyCostYear", width: 1, height: 1, decoration: "flat") {
            state "default", label: 'Per\nYear\n$${currentValue}'
        }

        controlTile("levelSliderControl", "device.brightnessLevel", "slider", width: 2, height: 1) {
            state "level", action: "switch level.setLevel"
        }

        valueTile("levelSliderTxt", "device.brightnessLevel", decoration: "flat") {
            state "brightnessLevel", label: '${currentValue}%'
        }

        standardTile("refresh", "device.switch", decoration: "flat", width: 2, height: 2) {
            state "default", label: "", action: "refresh.refresh", icon: "st.secondary.refresh"
        }

        standardTile("reset", "device.energy", decoration: "flat", width: 2, height: 2) {
            state "default", label: 'reset', action: "reset", icon: "st.secondary.refresh-icon"
        }

        controlTile("rgbSelector", "device.color", "color", height: 3, width: 2) {
            state "color", action: "setColor"
        }

        standardTile("configure", "device.power", inactiveLabel: false, decoration: "flat", width: 1, height: 1) {
            state "configure", label: '', action: "configuration.configure", icon: "st.secondary.configure"
        }

        valueTile("deviceInfo", "deviceInfo", decoration: "flat", width: 6, height: 2) {
            state "default", label: '${currentValue}', action: "getDeviceInfo"
        }

        main(["mainPanel", "power", "energy", "voltage", "amperage"])
        details(["mainPanel", "deviceMode", "power", "energy", "amperage", "voltage",
                 "currentEnergyCostTxt", "currentEnergyCostHour", "currentEnergyCostWeek", "currentEnergyCostMonth", "currentEnergyCostYear",
                 "cumulativeEnergyCostTxt", "cumulativeEnergyCostHour", "cumulativeEnergyCostWeek", "cumulativeEnergyCostMonth", "cumulativeEnergyCostYear",
                 "rgbSelector", "levelSliderControl", "levelSliderTxt", "configure", "refresh", "reset", "deviceInfo"])
    }
}

preferences {
    input title: "", description: "Aeon Smart Switch 6 (gen5) v${clientVersion()}", displayDuringSetup: true, type: "paragraph", element: "paragraph"

    input name: "switchDisabled", type: "bool", title: "Disable switch on/off.\n", defaultValue: "false", displayDuringSetup: true
    input name: "refreshInterval", type: "number", title: "Refresh interval \n\nSet the refresh time interval (seconds) between each report.\n", defaultValue: "300", displayDuringSetup: true
    input name: "switchAll", type: "enum", title: "Respond to switch all?\n", description: "How does switch respond to the 'Switch All' command", options: ["Disabled", "Off Enabled", "On Enabled", "On and Off Enabled"], defaultValue: "On and Off Enabled", displayDuringSetup: true, required: false
    input name: "forceStateChangeOnReport", type: "bool", title: "Force state change when receiving a report? If true, you'll always get notification even if report data doesn't change.\n", defaultValue: "false", displayDuringSetup: true
    input name: "secureInclusionOverride", type: "bool", title: "Is this device in secure inclusive mode?\n", defaultValue: "false", displayDuringSetup: true

    input name: "onlySendReportIfValueChange", type: "bool", title: "Only send report if value change (either in terms of wattage or a %).\n", defaultValue: "false", displayDuringSetup: true
    input title: "", description: "The next two parameters are only functional if the 'only send report' is set to true.", type: "paragraph", element: "paragraph", displayDuringSetup: true

    input name: "minimumChangeWatts", type: "number", title: "Minimum change in wattage for a report to be sent (0 - 60000).\n", defaultValue: "25", range: "0..60000", displayDuringSetup: true
    input name: "minimumChangePercent", type: "number", title: "Minimum change in percentage for a report to be sent (0 - 100).\n", defaultValue: "5", range: "0..100", displayDuringSetup: true

    input name: "costPerKwh", type: "decimal", title: "Cost per kWh (Used for energy cost /per kWh).\n", defaultValue: "0.12", displayDuringSetup: true

    input name: "includeWattInReport", type: "bool", title: "Include energy meter (W) in report?\n", defaultValue: "true", displayDuringSetup: true
    input name: "includeVoltageInReport", type: "bool", title: "Include voltage (V) in report?\n", defaultValue: "true", displayDuringSetup: true
    input name: "includeCurrentInReport", type: "bool", title: "Include current (A) in report?\n", defaultValue: "true", displayDuringSetup: true
    input name: "includeCurrentUsageInReport", type: "bool", title: "Include current usage (kWh) in report?\n", defaultValue: "true", displayDuringSetup: true

    input title: "", description: "Logging", type: "paragraph", element: "paragraph"
    input name: "isLogLevelTrace", type: "bool", title: "Show trace log level?\n", defaultValue: "false", displayDuringSetup: true
    input name: "isLogLevelDebug", type: "bool", title: "Show debug log level?\n", defaultValue: "true", displayDuringSetup: true
}

/*******************************************************************************
 * 	Z-WAVE PARSE / EVENTS                                                      *
 ******************************************************************************/

/**
 *  parse - Called when messages from a device are received from the hub
 *
 *  The parse method is responsible for interpreting those messages and returning Event definitions.
 *
 *  String	description		The message from the device
 */
def parse(String description) {
    def result = null
    logTrace "parse: '$description'"

    if (description != "updated") {
        def cmd = zwave.parse(description, [0x98: 1, 0x20: 1, 0x26: 3, 0x70: 1, 0x32: 3])
        logTrace "cmd: '$cmd'"

        if (cmd) {
            result = zwaveEvent(cmd)
            //log.debug("'$description' parsed to $result $result?.name")
        } else {
            log.error "Couldn't zwave.parse '$description'"
        }
    }

    updateStatus()
    result
}

/**
 *  COMMAND_CLASS_SECURITY (0x98)
 *
 *
 */
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
    def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x26: 3, 0x70: 1, 0x32: 3])
    logTrace "secure cmd: '$cmd'"
    state.deviceInfo['secureInclusion'] = true;

    // can specify command class versions here like in zwave.parse
    if (encapsulatedCommand) {
        return zwaveEvent(encapsulatedCommand)
    } else {
        log.error "Unable to extract encapsulated cmd from $cmd"
    }
}

/**
 *  COMMAND_CLASS_SECURITY (0x98)
 *
 *
 */
def zwaveEvent(physicalgraph.zwave.commands.securityv1.NetworkKeyVerify cmd) {
    log.debug "NetworkKeyVerify with cmd: $cmd (node is securely included)"

    //after device securely joined the network, call configure() to config device
    state.deviceInfo['secureInclusion'] = true;
    updateDeviceInfo()
}

/**
 *  COMMAND_CLASS_SWITCH_BINARY (0x25)
 *
 *  Short	value	0xFF for on, 0x00 for off
 */
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) {
    createEvent(name: "switch", value: cmd.switchValue ? "on" : "off")

    //return createEvent(name: "switch", value: cmd.value ? "on" : "off")
}

/**
 *  COMMAND_CLASS_SWITCH_BINARY (0x25)
 *
 *  Short	value	0xFF for on, 0x00 for off
 */
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
    createEvent(name: "switch", value: cmd.value ? "on" : "off", displayed: false, isStateChange: true)
}

def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd) {

}

/**
 *  COMMAND_CLASS_BASIC (0x20)
 *  This command is being ignored in secure inclusion mode.
 *
 *  Short	value	0xFF for on, 0x00 for off
 */
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
    return createEvent(name: "switch", value: cmd.value ? "on" : "off", displayed: false)
}

/**
 *  COMMAND_CLASS_BASIC (0x20)
 *
 *  This command is being ignored in secure inclusion mode.
 *  Short	value	0xFF for on, 0x00 for off
 */
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
    return createEvent(name: "switch", value: cmd.value ? "on" : "off")
}

/**
 *  COMMAND_CLASS_SWITCH_MULTILEVEL (0x26)
 *
 *  Short	value
 */
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelReport cmd) {

}

/**
 *  COMMAND_CLASS_METER (0x32)
 *
 *  Integer	deltaTime		    Time in seconds since last report
 *  Short	meterType		    Unknown = 0, Electric = 1, Gas = 2, Water = 3
 *  List<Short>	meterValue		    Meter value as an array of bytes
 *  Double	scaledMeterValue	    Meter value as a double
 *  List<Short>	previousMeterValue	    Previous meter value as an array of bytes
 *  Double	scaledPreviousMeterValue    Previous meter value as a double
 *  Short	size			    The size of the array for the meterValue and previousMeterValue
 *  Short	scale			    The scale of the values: "kWh"=0, "kVAh"=1, "Watts"=2, "pulses"=3, "Volts"=4, "Amps"=5, "Power Factor"=6, "Unknown"=7
 *  Short	precision		    The decimal precision of the values
 *  Short	rateType		    ???
 *  Boolean	scale2			    ???
 */
def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) {
    if (cmd.meterType == 1) {
        def eventList = []
        if (cmd.scale == 0) {
            logDebug " got kwh $cmd.scaledMeterValue"

            BigDecimal costDecimal = ( costPerKwh as BigDecimal )
            def batteryRunTimeHours = getBatteryRuntimeInHours()
            eventList.push(internalCreateEvent([name: "energy", value: cmd.scaledMeterValue, unit: "kWh"]));

            eventList.push(internalCreateEvent([name: "cumulativeEnergyCostTxt", value: getBatteryRuntime()]));
            eventList.push(internalCreateEvent([name: "cumulativeEnergyCostHour", value: String.format("%5.2f", cmd.scaledMeterValue / batteryRunTimeHours * costDecimal)]));
            eventList.push(internalCreateEvent([name: "cumulativeEnergyCostWeek", value: String.format("%5.2f", cmd.scaledMeterValue / batteryRunTimeHours * costDecimal * 24 * 7)]));
            eventList.push(internalCreateEvent([name: "cumulativeEnergyCostMonth", value: String.format("%5.2f", cmd.scaledMeterValue / batteryRunTimeHours * costDecimal * 24 * 30.42)]));
            eventList.push(internalCreateEvent([name: "cumulativeEnergyCostYear", value: String.format("%5.2f", cmd.scaledMeterValue / batteryRunTimeHours * costDecimal * 24 * 365)]));
        } else if (cmd.scale == 1) {
            logDebug " got kVAh $cmd.scaledMeterValue"
            eventList.push(internalCreateEvent([name: "energy", value: cmd.scaledMeterValue, unit: "kVAh"]));
        } else if (cmd.scale == 2) {
            logDebug " got wattage $cmd.scaledMeterValue"
            eventList.push(internalCreateEvent([name: "power", value: Math.round(cmd.scaledMeterValue), unit: "W"]));
            BigDecimal costDecimal = ( costPerKwh as BigDecimal )
            eventList.push(internalCreateEvent([name: "currentEnergyCostHour", value: String.format("%5.2f", (cmd.scaledMeterValue / 1000) * costDecimal)]));
            eventList.push(internalCreateEvent([name: "currentEnergyCostWeek", value: String.format("%5.2f", (cmd.scaledMeterValue / 1000) * 24 * 7 * costDecimal)]));
            eventList.push(internalCreateEvent([name: "currentEnergyCostMonth", value: String.format("%5.2f", (cmd.scaledMeterValue / 1000) * 24 * 30.42 * costDecimal)]));
            eventList.push(internalCreateEvent([name: "currentEnergyCostYear", value: String.format("%5.2f", (cmd.scaledMeterValue / 1000) * 24 * 365 * costDecimal)]));
        } else if (cmd.scale == 4) { // Volts
            logDebug " got voltage $cmd.scaledMeterValue"
            eventList.push(internalCreateEvent([name: "voltage", value: Math.round(cmd.scaledMeterValue), unit: "V"]));
        } else if (cmd.scale == 5) { //amps scale 5 is amps even though not documented
            logDebug " got amperage = $cmd.scaledMeterValue"
            eventList.push(internalCreateEvent([name: "amperage", value: cmd.scaledMeterValue, unit: "A"]));
        } else {
            eventList.push(internalCreateEvent([name: "electric", value: cmd.scaledMeterValue, unit: ["pulses", "V", "A", "R/Z", ""][cmd.scale - 3]]));
        }

        return eventList

    }
}

/**
 *  COMMAND_CLASS_CONFIGURATION (0x70)
 *
 *  List<Short>	configurationValue
 *  Short	parameterNumber
 *  Short	size
 */
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
    logTrace "received ConfigurationReport for " + cmd.parameterNumber + " (hex:" + Integer.toHexString(cmd.parameterNumber) + ") cmd: " + cmd
    switch (cmd.parameterNumber) {
        case 0x51:
            logTrace "received device mode event"
            if (cmd.configurationValue[0] == 0) {
                return createEvent(name: "deviceMode", value: "energy", displayed: true)
            } else if (cmd.configurationValue[0] == 1) {
                return createEvent(name: "deviceMode", value: "momentary", displayed: true)
            } else if (cmd.configurationValue[0] == 2) {
                return createEvent(name: "deviceMode", value: "nightLight", displayed: true)
            }
            break;
        case 0x54:
            logTrace "received brightness level event"
            return createEvent(name: "level", value: cmd.configurationValue[0], displayed: true)
            break;
    }
}

/**
 *  COMMAND_CLASS_HAIL (0x82)
 *
 */
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
    logDebug "Switch button was pressed"
    return createEvent(name: "hail", value: "hail", descriptionText: "Switch button was pressed")
}

/**
 *  COMMAND_CLASS_VERSION (0x86)
 *
 *  Short	applicationSubVersion
 *  Short	applicationVersion
 *  Short	zWaveLibraryType
 *  Short	zWaveProtocolSubVersion
 *  Short	zWaveProtocolVersion
 */
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
    state.deviceInfo['applicationVersion'] = "${cmd.applicationVersion}"
    state.deviceInfo['applicationSubVersion'] = "${cmd.applicationSubVersion}"
    state.deviceInfo['zWaveLibraryType'] = "${cmd.zWaveLibraryType}"
    state.deviceInfo['zWaveProtocolVersion'] = "${cmd.zWaveProtocolVersion}"
    state.deviceInfo['zWaveProtocolSubVersion'] = "${cmd.zWaveProtocolSubVersion}"

    return updateDeviceInfo()
}

/**
 *  COMMAND_CLASS_MANUFACTURER_SPECIFIC (0x72)
 *
 *  Integer	manufacturerId
 *  Integer	productId
 *  Integer	productTypeId
 *
 */
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
    state.deviceInfo['manufacturerId'] = "${cmd.manufacturerId}"
    state.deviceInfo['manufacturerName'] = "${cmd.manufacturerName}"
    state.deviceInfo['productId'] = "${cmd.productId}"
    state.deviceInfo['productTypeId'] = "${cmd.productTypeId}"

    return updateDeviceInfo()
}

/**
 *  COMMAND_CLASS_MANUFACTURER_SPECIFIC (0x72)
 *
 * List<Short>	deviceIdData
 * Short	deviceIdDataFormat
 * Short	deviceIdDataLengthIndicator
 * Short	deviceIdType
 *
 */
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
    logTrace "deviceIdData:  	          ${cmd.deviceIdData}"
    logTrace "deviceIdDataFormat:         ${cmd.deviceIdDataFormat}"
    logTrace "deviceIdDataLengthIndicator:${cmd.deviceIdDataLengthIndicator}"
    logTrace "deviceIdType:               ${cmd.deviceIdType}"

    return updateDeviceInfo()
}

/**
 *  COMMAND_CLASS_FIRMWARE_UPDATE_MD_V2 (0x7a)
 *
 * Integer	checksum
 * Integer	firmwareId
 * Integer	manufacturerId
 *
 */
def zwaveEvent(physicalgraph.zwave.commands.firmwareupdatemdv2.FirmwareMdReport cmd) {
    state.deviceInfo['checksum'] = "${cmd.checksum}"
    state.deviceInfo['firmwareId'] = "${cmd.firmwareId}"

    return updateDeviceInfo()
}
/*******************************************************************************
 * 	CAPABILITITES                                                              *
 ******************************************************************************/

/**
 *  configure - Configures the parameters of the device
 *
 *  Required for the "Configuration" capability
 */
def configure() {
    logDebug "configure()"

    updateDeviceInfo()

    def switchAllMode = physicalgraph.zwave.commands.switchallv1.SwitchAllSet.MODE_INCLUDED_IN_THE_ALL_ON_ALL_OFF_FUNCTIONALITY
    if (switchAll == "Disabled") {
        switchAllMode = physicalgraph.zwave.commands.switchallv1.SwitchAllSet.MODE_EXCLUDED_FROM_THE_ALL_ON_ALL_OFF_FUNCTIONALITY
    } else if (switchAll == "Off Enabled") {
        switchAllMode = physicalgraph.zwave.commands.switchallv1.SwitchAllSet.MODE_EXCLUDED_FROM_THE_ALL_ON_FUNCTIONALITY_BUT_NOT_ALL_OFF
    } else if (switchAll == "On Enabled") {
        switchAllMode = physicalgraph.zwave.commands.switchallv1.SwitchAllSet.MODE_EXCLUDED_FROM_THE_ALL_OFF_FUNCTIONALITY_BUT_NOT_ALL_ON
    }

    logTrace "forceStateChangeOnReport value: " + forceStateChangeOnReport
    logTrace "switchAll value: " + switchAll

    def reportGroup;
    reportGroup = ("$includeVoltageInReport" == "true" ? 1 : 0)
    reportGroup += ("$includeCurrentInReport" == "true" ? 2 : 0)
    reportGroup += ("$includeWattInReport" == "true" ? 4 : 0)
    reportGroup += ("$includeCurrentUsageInReport" == "true" ? 8 : 0)

    log.trace "setting configuration refresh interval: " + new BigInteger("$refreshInterval")

    /***************************************************************
     Device specific configuration parameters
     ----------------------------------------------------------------
     Param   Size    Default Description
     ------- ------- ------- ----------------------------------------
     0x03 (3)    1       0   Current Overload Protection. Load will be closed when the Current overrun (US: 15.5A, other country: 16.2A) and the
     time more than 2 minutes (0=disabled, 1=enabled).
     0x14 (20)   1       0   Configure the output load status after re-power on (0=last status, 1=always on, 2=always off)
     0x21 (33)   4           Set the RGB LED color value for testing. alternate rgb color level ie res,blue,green,red ie 00ffffff
     0x50 (80)   1       0       Enable to send notifications to associated devices in Group 1 when load changes (0=nothing, 1=hail CC, 2=basic CC report)
     0x51 (81)   1       0       mode 0 - energy, 1 - momentary indicator, 2 - night light
     0x53 (83)   3       0      hex value ffffff00 .. only night light mode
     0x54 (84)   1       50       dimmer level 0 -100 (doesn't work in night light mode)
     0x5A (90)   1       1       Enables/disables parameter 0x5A and 0x5B below
     0x5B (91)   2       25      The value here represents minimum change in wattage (in terms of wattage) for a REPORT to be sent (default 50W, size 2 bytes).
     0x5C (92)   1       5      The value here represents minimum change in wattage (in terms of percentage) for a REPORT to be sent (default 10%, size 1 byte).
     0x65 (101)  4       0x00 00 00 04 Which reports need to send in Report group 1
     0x66 (102)  4       0x00 00 00 08 Which reports need to send in Report group 2
     0x67 (103)  4       0       Which reports need to send in Report group 3
     0x6F (111)  4       0x00 00 02 58 The time interval in seconds for sending Report group 1 (Valid values 0x01-0x7FFFFFFF).
     0x70 (112)  4       0x00 00 02 58 The time interval in seconds for sending Report group 2 (Valid values 0x01-0x7FFFFFFF).
     0x71 (113)  4       0x00 00 02 58 The time interval in seconds for sending Report group 3 (Valid values 0x01-0x7FFFFFFF).
     0xC8 (200)  1       0  Partner ID
     0xFC (252)  1       0  Enable/disable Configuration Locked (0 =disable, 1 =enable).
     0xFE (254)  2       0  Device Tag.
     0xFF (255)  1       N/A     Reset to factory default setting


     Configuration Values for parameters 0x65-0x67:
     BYTE  | 7  6  5  4  3  2  1  0
     ===============================
     MSB 0 | 0  0  0  0  0  0  0  0
     Val 1 | 0  0  0  0  0  0  0  0
     VAL 2 | 0  0  0  0  0  0  0  0
     LSB 3 | 0  0  0  0  A  B  C  0

     Bit A - Send Meter REPORT (for kWh) at the group time interval
     Bit B - Send Meter REPORT (for watt) at the group time interval
     Bit C - Automatically send(1) or don't send(0) Multilevel Sensor Report Command
     ***************************************************************/

    delayBetween([
            formatCommand(zwave.switchAllV1.switchAllSet(mode: switchAllMode)),
            formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x50, size: 1, scaledConfigurationValue: 0)),    //Enable to send notifications to associated devices when load changes (0=nothing, 1=hail CC, 2=basic CC report)
            formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x5A, size: 1, scaledConfigurationValue: ("$onlySendReportIfValueChange" == "true" ? 1 : 0))),    //Enables parameter 0x5B and 0x5C (0=disabled, 1=enabled)
            formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x5B, size: 2, scaledConfigurationValue: new BigInteger("$minimumChangeWatts"))),    //Minimum change in wattage for a REPORT to be sent (Valid values 0 - 60000)
            formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x5C, size: 1, scaledConfigurationValue: "$minimumChangePercent")),    //Minimum change in percentage for a REPORT to be sent (Valid values 0 - 100)

            formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x65, size: 4, scaledConfigurationValue: reportGroup)),    //Which reports need to send in Report group 1
            formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x66, size: 4, scaledConfigurationValue: 0)),    //Which reports need to send in Report group 2
            formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x67, size: 4, scaledConfigurationValue: 0)),    //Which reports need to send in Report group 3

            formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x6F, size: 4, scaledConfigurationValue: new BigInteger("$refreshInterval"))),    // change reporting time
            formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x70, size: 4, scaledConfigurationValue: new BigInteger(0xFFFFF))),
            formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x71, size: 4, scaledConfigurationValue: new BigInteger(0xFFFFF))),

            formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x3, size: 1, scaledConfigurationValue: 0)),      // Current Overload Protection.
    ], 200)
}

/**
 *  on - Turns on the switch
 *
 *  Required for the "Switch" capability
 */
def on() {
    if (switchDisabled) {
        logDebug "switch disabled, doing nothing"
        delayBetween([
                formatCommand(zwave.switchBinaryV1.switchBinaryGet())
        ], 200)
    } else {
        logDebug "switching it on"
        delayBetween([
                formatCommand(zwave.switchBinaryV1.switchBinarySet(switchValue: 0xFF)),
                formatCommand(zwave.switchBinaryV1.switchBinaryGet())
        ], 200)
    }
}

/**
 *  off - Turns off the switch
 *
 *  Required for the "Switch" capability
 */
def off() {
    if (switchDisabled) {
        logDebug "switch disabled, doing nothing"
        delayBetween([
                formatCommand(zwave.switchBinaryV1.switchBinaryGet())
        ], 200)
    } else {
        logDebug "switching it off"
        delayBetween([
                formatCommand(zwave.switchBinaryV1.switchBinarySet(switchValue: 0x00)),
                formatCommand(zwave.switchBinaryV1.switchBinaryGet())
        ], 200)
    }
}

/**
 *  poll - Polls the device
 *
 *  Required for the "Polling" capability
 */
def poll() {
    logTrace "poll()"

    delayBetween([
            formatCommand(zwave.switchBinaryV1.switchBinaryGet()),
            formatCommand(zwave.meterV3.meterGet(scale: 0)), // energy kWh
            formatCommand(zwave.meterV3.meterGet(scale: 1)), // energy kVAh
            formatCommand(zwave.meterV3.meterGet(scale: 2)), // watts
            formatCommand(zwave.meterV3.meterGet(scale: 4)), // volts
            formatCommand(zwave.meterV3.meterGet(scale: 5)), // amps
    ], 200)
}

/**
 *  refresh - Refreshed values from the device
 *
 *  Required for the "Refresh" capability
 */
def refresh() {
    logDebug "refresh()"
    updateDeviceInfo()

    sendEvent(name: "power", value: "0", displayed: true, unit: "W")
    sendEvent(name: "energy", value: "0", displayed: true, unit: "kWh")
    sendEvent(name: "amperage", value: "0", displayed: true, unit: "A")
    sendEvent(name: "voltage", value: "0", displayed: true, unit: "V")

    sendEvent(name: "currentEnergyCostHour", value: "0", displayed: true)
    sendEvent(name: "currentEnergyCostWeek", value: "0", displayed: true)
    sendEvent(name: "currentEnergyCostMonth", value: "0", displayed: true)
    sendEvent(name: "currentEnergyCostYear", value: "0", displayed: true)

    sendEvent(name: "cumulativeEnergyCostHour", value: "0", displayed: true)
    sendEvent(name: "cumulativeEnergyCostWeek", value: "0", displayed: true)
    sendEvent(name: "cumulativeEnergyCostMonth", value: "0", displayed: true)
    sendEvent(name: "cumulativeEnergyCostYear", value: "0", displayed: true)

    delayBetween([
            formatCommand(zwave.switchMultilevelV1.switchMultilevelGet()),
            formatCommand(zwave.meterV3.meterGet(scale: 0)), // energy kWh
            formatCommand(zwave.meterV3.meterGet(scale: 1)), // energy kVAh
            formatCommand(zwave.meterV3.meterGet(scale: 2)), // watts
            formatCommand(zwave.meterV3.meterGet(scale: 4)), // volts
            formatCommand(zwave.meterV3.meterGet(scale: 5)), // amps
            formatCommand(zwave.configurationV1.configurationGet(parameterNumber: 0x51)), // device state
            formatCommand(zwave.configurationV1.configurationGet(parameterNumber: 0x53)), // night light RGB value
            formatCommand(zwave.configurationV1.configurationGet(parameterNumber: 0x54)), // led brightness
    ], 200)
}

/**
 *  reset - Resets the devices energy usage meter and attempt to reset device
 *
 *  Required for the "Switch Level" capability
 */
def setLevel(level) {
    setBrightnessLevel(level)
}

/**
 *  Sets the color to the passed in maps values
 *
 *  Required for the "Color Control" capability
 */
def setColor(colormap) {
    logDebug " in setColor"

    if (colormap.hex == null && colormap.hue) {
        def hexColor = colorUtil.hslToHex(colormap.hue, colormap.saturation)
        logDebug " in setColor colormap = $hexColor"

        sendEvent(name: "color", value: hexColor)
        formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x53, size: 3, configurationValue: colorUtil.hexToRgb(hexColor)))
    } else {
        logDebug " in setColor: hex =  ${colormap.hex}"
        sendEvent(name: "color", value: colormap.hex)
        formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x53, size: 3, configurationValue: [colormap.red, colormap.green, colormap.blue]))
    }
}

/*******************************************************************************
 * 	Methods                                                                    *
 ******************************************************************************/

/**
 *  installed - Called when the device handling is being installed
 */
def installed() {
    log.debug "installed() called"

    if (state.deviceInfo == null) {
        state.deviceInfo = [:]
        state.deviceInfo['secureInclusion'] = false
    }
}

/**
 *  updated - Called when the preferences of the device type are changed
 */
def updated() {
    logDebug "updated()"

    updateStatus()
    //updatePowerStatus(0)
    response(configure())
}

/**
 *  reset - Resets the devices energy usage meter and attempt to reset device
 *
 *  Defined by the custom command "reset"
 */
def reset() {
    logDebug "reset()"
    state.energyMeterRuntimeStart = now()

    delayBetween([
            formatCommand(zwave.meterV3.meterReset()),
            formatCommand(zwave.meterV3.meterGet(scale: 0)), // energy kWh
            formatCommand(zwave.meterV3.meterGet(scale: 1)), // energy kVAh
            formatCommand(zwave.meterV3.meterGet(scale: 2)), // watts
            formatCommand(zwave.meterV3.meterGet(scale: 4)), // volts
            formatCommand(zwave.meterV3.meterGet(scale: 5)), // amps
    ], 200)
}

def factoryReset() {
    logDebug "factoryReset()"

    formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0xFF, size: 4, scaledConfigurationValue: 1))
    //factory reset
    configure()
}

def getDeviceInfo() {
    logDebug "getDeviceInfo()"

    delayBetween([
            formatCommand(zwave.versionV1.versionGet()),
            formatCommand(zwave.firmwareUpdateMdV2.firmwareMdGet()),
            //zwave.manufacturerSpecificV2.deviceSpecificGet().format(),
            formatCommand(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
    ], 200)
}

private updateStatus() {
    def sinceTime = ''
    if (state.energyMeterRuntimeStart != null) {
        sinceTime = "${getBatteryRuntime()}"
    } else {
        sinceTime = now()
    }

    sendEvent(name: "statusText3", value: "Energy meter since: $sinceTime", displayed: false)
}

private updateDeviceInfo() {
    logTrace "updateDeviceInfo()"
	
    if (state.deviceInfo == null) {
        state.deviceInfo = [:]
	}

    def buffer = "Get Device Info";
    def newBuffer = null;

    def switchStatus = "SWITCH ENABLED\n"
    if (switchDisabled) {
        switchStatus = "SWITCH DISABLED\n"
    }

    if (state.deviceInfo['applicationVersion'] == null ||
        state.deviceInfo['manufacturerName'] == null) {
        getDeviceInfo()
    } else {
        newBuffer = "${switchStatus}"
    }

    if (state.deviceInfo['applicationVersion'] != null) {
        if (newBuffer == null) {
            newBuffer = "${switchStatus}"
        }

        newBuffer += "app Version: ${state.deviceInfo['applicationVersion']} Sub Version: ${state.deviceInfo['applicationSubVersion']}\n";
        newBuffer += "zWaveLibrary Type: ${state.deviceInfo['zWaveLibraryType']}\n";
        newBuffer += "zWaveProtocol Version: ${state.deviceInfo['zWaveProtocolVersion']} Sub Version: ${state.deviceInfo['zWaveProtocolSubVersion']}\n";
        newBuffer += "secure inclusion: ${state.deviceInfo['secureInclusion'] || secureInclusionOverride}\n";
    }

    if (state.deviceInfo['manufacturerName'] != null) {
        if (newBuffer == null) {
            newBuffer = "${switchStatus}"
        }

        newBuffer += "manufacturer Name: ${state.deviceInfo['manufacturerName']}\n";
        newBuffer += "manufacturer Id: ${state.deviceInfo['manufacturerId']}\n";
        newBuffer += "product Id: ${state.deviceInfo['productId']} Type Id: ${state.deviceInfo['productTypeId']}\n";
        newBuffer += "firmwareId: ${state.deviceInfo['firmwareId']} checksum: ${state.deviceInfo['checksum']}\n";
    }

    return sendEvent(name: "deviceInfo", value: "$newBuffer", displayed: false)
}

private getBatteryRuntime() {
    def currentmillis = now() - state.energyMeterRuntimeStart
    def days = 0
    def hours = 0
    def mins = 0
    def secs = 0
    secs = (currentmillis / 1000).toInteger()
    mins = (secs / 60).toInteger()
    hours = (mins / 60).toInteger()
    days = (hours / 24).toInteger()
    secs = (secs - (mins * 60)).toString().padLeft(2, '0')
    mins = (mins - (hours * 60)).toString().padLeft(2, '0')
    hours = (hours - (days * 24)).toString().padLeft(2, '0')

    if (days > 0) {
        return "$days days and $hours:$mins:$secs"
    } else {
        return "$hours:$mins:$secs"
    }
}

private getBatteryRuntimeInHours() {
    def currentmillis = now() - state.energyMeterRuntimeStart
    def days = 0
    def hours = 0
    def mins = 0
    def secs = 0
    secs = (currentmillis / 1000)
    mins = (secs / 60)
    hours = (mins / 60)
    return hours
}

void logDebug(str) {
    if (isLogLevelDebug) {
        log.debug str
    }
}

void logTrace(str) {
    if (isLogLevelTrace) {
        log.trace str
    }
}

def nightLight() {
    logDebug "in set nightlight mode"
    sendEvent(name: "deviceMode", value: "nightLight", displayed: true)
    setDeviceMode(2)
}

def energy() {
    logDebug "in set energy mode"
    sendEvent(name: "deviceMode", value: "energy", displayed: true)
    setDeviceMode(0)
}

def momentary() {
    logDebug "in momentary mode"
    sendEvent(name: "deviceMode", value: "momentary", displayed: true)
    setDeviceMode(1)
}

def setDeviceMode(mode) {
    logTrace "set current mode to '$mode'"
    formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x51, size: 1, scaledConfigurationValue: mode))
}

def setBrightnessLevel(newLevel) {
    logDebug "in set setlevel newlevel = '$newLevel'"
    sendEvent(name: "brightnessLevel", value: newLevel.toInteger(), displayed: true)

    // There seems to have an error in the documentation where this config should be a size = 1
    formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x54, size: 3, configurationValue: [newLevel, newLevel, newLevel]))
}

def formatCommand(physicalgraph.zwave.Command cmd) {
    if (isSecured()) {
        logTrace "Formatting secured command: ${cmd}"
        zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
    } else {
        logTrace "Formatting unsecured command: ${cmd}"
        cmd.format()
    }
}

def isSecured() {
    (state.deviceInfo && state.deviceInfo['secureInclusion']) || secureInclusionOverride
}

def internalCreateEvent(event) {
    if (forceStateChangeOnReport) {
        event.isStateChange = true
    }

    return createEvent(event)
}
            state.deviceInfo = [:]
    	}

        def buffer = "Get Device Info";
        def newBuffer = null;

        def switchStatus = "SWITCH ENABLED\n"
        if (switchDisabled) {
            switchStatus = "SWITCH DISABLED\n"
        }

        if (state.deviceInfo['applicationVersion'] == null ||
            state.deviceInfo['manufacturerName'] == null) {
            getDeviceInfo()
        } else {
            newBuffer = "${switchStatus}"
        }

        if (state.deviceInfo['applicationVersion'] != null) {
            if (newBuffer == null) {
                newBuffer = "${switchStatus}"
            }

            newBuffer += "app Version: ${state.deviceInfo['applicationVersion']} Sub Version: ${state.deviceInfo['applicationSubVersion']}\n";
            newBuffer += "zWaveLibrary Type: ${state.deviceInfo['zWaveLibraryType']}\n";
            newBuffer += "zWaveProtocol Version: ${state.deviceInfo['zWaveProtocolVersion']} Sub Version: ${state.deviceInfo['zWaveProtocolSubVersion']}\n";
            newBuffer += "secure inclusion: ${state.deviceInfo['secureInclusion'] || secureInclusionOverride}\n";
        }

        if (state.deviceInfo['manufacturerName'] != null) {
            if (newBuffer == null) {
                newBuffer = "${switchStatus}"
            }

            newBuffer += "manufacturer Name: ${state.deviceInfo['manufacturerName']}\n";
            newBuffer += "manufacturer Id: ${state.deviceInfo['manufacturerId']}\n";
            newBuffer += "product Id: ${state.deviceInfo['productId']} Type Id: ${state.deviceInfo['productTypeId']}\n";
            newBuffer += "firmwareId: ${state.deviceInfo['firmwareId']} checksum: ${state.deviceInfo['checksum']}\n";
        }

        return sendEvent(name: "deviceInfo", value: "$newBuffer", displayed: false)
    }

    private getBatteryRuntime() {
        def currentmillis = now() - state.energyMeterRuntimeStart
        def days = 0
        def hours = 0
        def mins = 0
        def secs = 0
        secs = (currentmillis / 1000).toInteger()
        mins = (secs / 60).toInteger()
        hours = (mins / 60).toInteger()
        days = (hours / 24).toInteger()
        secs = (secs - (mins * 60)).toString().padLeft(2, '0')
        mins = (mins - (hours * 60)).toString().padLeft(2, '0')
        hours = (hours - (days * 24)).toString().padLeft(2, '0')

        if (days > 0) {
            return "$days days and $hours:$mins:$secs"
        } else {
            return "$hours:$mins:$secs"
        }
    }

    private getBatteryRuntimeInHours() {
        def currentmillis = now() - state.energyMeterRuntimeStart
        def days = 0
        def hours = 0
        def mins = 0
        def secs = 0
        secs = (currentmillis / 1000)
        mins = (secs / 60)
        hours = (mins / 60)
        return hours
    }

    void logDebug(str) {
        if (isLogLevelDebug) {
            log.debug str
        }
    }

    void logTrace(str) {
        if (isLogLevelTrace) {
            log.trace str
        }
    }

    def nightLight() {
        logDebug "in set nightlight mode"
        sendEvent(name: "deviceMode", value: "nightLight", displayed: true)
        setDeviceMode(2)
    }

    def energy() {
        logDebug "in set energy mode"
        sendEvent(name: "deviceMode", value: "energy", displayed: true)
        setDeviceMode(0)
    }

    def momentary() {
        logDebug "in momentary mode"
        sendEvent(name: "deviceMode", value: "momentary", displayed: true)
        setDeviceMode(1)
    }

    def setDeviceMode(mode) {
        logTrace "set current mode to '$mode'"
        formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x51, size: 1, scaledConfigurationValue: mode))
    }

    def setBrightnessLevel(newLevel) {
        logDebug "in set setlevel newlevel = '$newLevel'"
        sendEvent(name: "brightnessLevel", value: newLevel.toInteger(), displayed: true)

        // There seems to have an error in the documentation where this config should be a size = 1
        formatCommand(zwave.configurationV1.configurationSet(parameterNumber: 0x54, size: 3, configurationValue: [newLevel, newLevel, newLevel]))
    }

    def formatCommand(physicalgraph.zwave.Command cmd) {
        if (isSecured()) {
            logTrace "Formatting secured command: ${cmd}"
            zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
        } else {
            logTrace "Formatting unsecured command: ${cmd}"
            cmd.format()
        }
    }

    def isSecured() {
        (state.deviceInfo && state.deviceInfo['secureInclusion']) || secureInclusionOverride
    }

    def internalCreateEvent(event) {
        if (forceStateChangeOnReport) {
            event.isStateChange = true
        }

        return createEvent(event)
    }

Note, I am seeing these errors in logging. I don’t think I’ve done anything to cause them:

One Device:

2:35:11 PM: error groovy.lang.MissingMethodException: No signature of method: script150446086497322560422.zwaveEvent() is applicable for argument types: (physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryGet) values: [SensorBinaryGet(sensorType: 1)]
Possible solutions: zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport), zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet), zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport), zwaveEvent(physicalgraph.zwave.commands.firmwareupdatemdv2.FirmwareMdReport), zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail), zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport) @ line 262

2:29:45 PM: error Couldn't zwave.parse 'zw device: 47, command: 7202, payload: 21 74 00 00 00 00 00 00 00 00 00 00 40 00 00 00 '

2:29:45 PM: warn Exception 'java.lang.NullPointerException: Cannot invoke method parse() on null object' encountered parsing 'cmd: 7202, payload: 21 74 00 00 00 00 00 00 00 00 00 00 40 00 00 00'

Second Device:

2:27:28 PM: error groovy.lang.MissingMethodException: No signature of method: script150446087924322560422.zwaveEvent() is applicable for argument types: (physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryGet) values: [SensorBinaryGet(sensorType: 33)]
Possible solutions: zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport), zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet), zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport), zwaveEvent(physicalgraph.zwave.commands.firmwareupdatemdv2.FirmwareMdReport), zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail), zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport) @ line 262

2:24:23 PM: error Couldn't zwave.parse 'zw device: 4E, command: 3200, payload: A1 64 00 01 DB 2B 00 00 00 00 00 00 00 00 00 00 '

2:24:23 PM: warn Exception 'java.lang.NullPointerException: Cannot invoke method parse() on null object' encountered parsing 'cmd: 3200, payload: A1 64 00 01 DB 2B 00 00 00 00 00 00 00 00 00 00'

Also, I am seeing a flood of updates in Recent for each device. It appears any time a new value is determined for costs a new message is sent (this happens even with something plugged in not doing anything). I can’t say for sure but this flood of messages may be causing delays in processing some commands, like on and off. Sometimes my devices are taking minutes to respond to commands (but the messages in Recent are pretty constant). And I cannot get the flood to stop no matter what I set the prefs to. I’m not experienced enough yet in the coding to look for solutions to this. And perhaps I do not understand the prefs well enough. But I do seem to remember reading about this issue in another thread even with another DTH so perhaps it’s a firmware issue.

Let me know if I can help in any way.

I use one for my Dryer. My dryer doesn’t go above 300W. It has been just fine.

Edit: I’ve been running the DTH as “ZWave Metering Switch” all this time. I just now installed @jbisson’s DTH, so hopefully this’ll fix the reporting issues I was having.

I’m using the code at the top of this thread, and no matter what I change the settings to it reports constantly, very annoying, clogging up the “Recently” tab. I set reporting to 7200 “secondes” (sic) but every few minutes with device off it reports volts, cumulative energy cost etc etc

Yes, this is the same thing I am seeing and I reported just above.

FYI, I caught that spelling mistake and corrected it in my version. Hopefully we’ll get a new official version soon.

The option to disable the on/off button does not work for me either.

I’m wondering if the prefs are not getting sent/set on the device.

Ok guys, just pushed a new version: 5.2.0 which can be grabbed from the git repo or update on the platform directly.

I’ve integrated your changes Nezmo, thanks for this.

I’ve also needed to remove the defaultValues in the preference screen as it seems to be a platform bug where the defaultValues does not get saved at all. You’ll need to manually need to type it.

This is exactly the reason why I’ve been a bit more distant in regards to any device handler/smart apps development, samsung keep breaking things and force developer to fix their code. This issue been reported MONTHS ago and still an issue, there are some serious quality issue on the platform.

Venting a little more, UI layout on the tablet platform have changed, it now breaks all previous layout. Of course, samsung did not provide any documentation (I coulndn’t find any documentation) and this topic has not been answered New Tablet Layout - Tile Standards related to this. Again, another lack of quality in terms of backward compatibility issues.

Anyway, sorry for the rent guys, it’s just very annoying to put effort on things that just used to work. All of these issues could have been avoided through unit testing / integration testing on the platform side of thing first.

That being said, please update to latest and let me know if you find any issues.

2 Likes

Thanks Jonathan. As soon as I can devote a little time I will install this and let you know how I get on.

Much appreciated. and yes, I get the venting completely.

Can’t Update via Repo still getting this error:

Also, using SmartThingsPublic is the same as others and makes it difficult to find yours in the list. Naming it something unique to you would make it easier.

What’s the error you are getting? For now, you can do a copy and past, latest code is here:
https://github.com/jbisson/SmartThingsPublic/blob/master/devicetypes/jbisson/aeon-smartSwitch-6.src/aeon-smartSwitch-6-gen5.groovy

good idea about the name change, I’ll rename it soon.

No other information is given. Just the screencap I posted. In the IDE yours is listed in green indicating it is not in any repository. Perhaps I have something set wrong. I’m using these settings

I get the same so I have installed manually.

This was the case before the last update too.

Ok, not sure what’s wrong with the repo or the update to be honest. I’ve tried to renamed it and the update doesn’t work for me either. No error details on what’s the issue, nothing in the logs, thanks samsung (Will stop the rent right here :))

Since the update are not working and I have no way to know how to fix, I’ll leave the repo name as is, please update manually by copy/pasting it for now until the update get fix?

I wish I knew how to fix this but seems to be outside of the device handler code…

Happened to come across this, could it be the problem. I have no clue about github so I couldn’t tell myself.

@jbisson - Try renaming the actual device to match your file name and see if it helps. That was the trick for me after hammering on this for a while. Also, make sure all the naming is consistent throughout.

This is what you have now:
/aeon-smartSwitch-6.src/aeon-smartSwitch-6-gen5.groovy

metadata {
definition(name: “Aeon Labs Smart Switch 6”

What I saw is they all have to be consistent. So you would need to have something like this (change to whatever you’d rather have, I just randomly picked one of the three):
/aeon-smartSwitch-6.src/aeon-smartSwitch-6.groovy

metadata {
definition(name: “Aeon SmartSwitch 6”

Give that a try and see if it works out.

Okay, I have three of these switches and I’m still having some issues across all of them.

  • I am intermittently seeing delays with response to commands. For example, on and off can work great at times and others it can take a minute to respond. Changing LED mode the same.
  • The device sometimes changes to ‘off’ in the ST app but it is not actually off. I have to manually switch the device off/on to get the app to update the true state again. Sometimes a refresh in the app can resolve this but not always. and sometimes the on/off state eventually corrects itself without any intervention. Note that the device is otherwise showing other changes just fine like changes in power, volts, etc.
  • I am still not sure prefs are getting set. For example, disabling on/off is not working for me. If I turn off reporting for something it continues to report.
  • I conitinue to get errors in the logs: examples:
    11:37:50 AM: warn Exception ‘java.lang.NullPointerException: Cannot invoke method parse() on null object’ encountered parsing 'cmd: 3A8A, payload: B0 AC 2A A2 EA B0 AB A6 AA AA A8 A2 E8 2A A6 AA’
    11:37:50 AM: error Couldn’t zwave.parse 'zw device: 47, command: 3A8A, payload: B0 AC 2A A2 EA B0 AB A6 AA AA A8 A2 E8 2A A6 AA '
    The command being reference is not always the same.

Any ideas? I really had high hopes for this switch but I’m really having some troubles.

Note, my mesh is very strong.

@doncaruana thanks, I’ll look into it soon.

@nezmo It seems that the connection from the smartthing hub to the sensor might be flicky. In order to avoid any possible connection issue, can you try to plug the sensor through the wire (not battery) and put it close to the hub and see if you experience the same issues? It really does seems a connection issue?

Just to be 100% sure, this is the type of device you have correct? http://ecx.images-amazon.com/images/I/41pWwcdcpWL.SY400.jpg ?