Compare commits

...

1 Commits

Author SHA1 Message Date
Nicki
b6773cf28b MSA-2221: d 2017-09-14 13:19:23 -07:00
2 changed files with 1379 additions and 0 deletions

View File

@@ -0,0 +1,993 @@
/**
*
* 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-04 Version 5.2.0 Removed defaultValues on preference screen as a work-around for a platform bug, crash protection fixes
* 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 COMMAND_CLASS_ZWAVE_PLUS_INFO
* 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.2.0"
}
metadata {
definition(name: "Aeon Labs Smart Switch 6", namespace: "jbisson", author: "Jonathan Bisson") {
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: 'momentary', action: "nightLight", icon: "http://mail.lgk.com/aeonv6white.png"
state "nightLight", label: 'NightLight', 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, required: true
input name: "refreshInterval", type: "number", title: "Refresh interval \n\nSet the refresh time interval (seconds) between each report [Default (300)].\n", displayDuringSetup: true, required: 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, required: true
input name: "secureInclusionOverride", type: "bool", title: "Is this device in secure inclusive mode?\n", defaultValue: "false", displayDuringSetup: true, required: 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, required: 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, required: true
input name: "minimumChangeWatts", type: "number", title: "Minimum change in wattage for a report to be sent (0 - 60000) [Default (25)].\n", range: "0..60000", displayDuringSetup: true, required: true
input name: "minimumChangePercent", type: "number", title: "Minimum change in percentage for a report to be sent (0 - 100) [Default (5)]\n", range: "0..100", displayDuringSetup: true, required: true
input name: "costPerKwh", type: "decimal", title: "Cost per kWh (Used for energy cost /per kWh) [Default (0.12)]\n", displayDuringSetup: true, required: true
input name: "includeWattInReport", type: "bool", title: "Include energy meter (W) in report?\n", defaultValue: "true", displayDuringSetup: true, required: true
input name: "includeVoltageInReport", type: "bool", title: "Include voltage (V) in report?\n", defaultValue: "true", displayDuringSetup: true, required: true
input name: "includeCurrentInReport", type: "bool", title: "Include current (A) in report?\n", defaultValue: "true", displayDuringSetup: true, required: true
input name: "includeCurrentUsageInReport", type: "bool", title: "Include current usage (kWh) in report?\n", defaultValue: "true", displayDuringSetup: true, required: true
input title: "", description: "Logging", type: "paragraph", element: "paragraph"
input name: "isLogLevelTrace", type: "bool", title: "Show trace log level ?\n", defaultValue: "false", displayDuringSetup: true, required: true
input name: "isLogLevelDebug", type: "bool", title: "Show debug log level ?\n", defaultValue: "true", displayDuringSetup: true, required: 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") {
if (description.contains("command: 5E02")) {
logInfo "Ignoring command 5E02 has it's not supported by the platform."
return
}
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 {
logError "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 {
logError "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 ("$costPerKwh" == "null") {
logError "costPerKwh is null, please go through the configuration page first"
return
}
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() {
logInfo "configure()"
if ("$refreshInterval" == "null" || "$minimumChangeWatts" == "null") {
logError "Some preferences are null, please go through the configuration page first"
return
}
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)
logTrace "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() {
logInfo "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() {
logInfo "installed() called"
if (state.deviceInfo == null) {
state.deviceInfo = [:]
state.deviceInfo['secureInclusion'] = false
}
// Call a reset upon install to clear all values.
reset();
updateDeviceInfo();
}
/**
* updated - Called when the preferences of the device type are changed
*/
def updated() {
logInfo "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() {
logInfo "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() {
logInfo "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";
}
if (newBuffer == null) {
newBuffer = buffer
}
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 logInfo(str) {
log.info str
}
void logWarn(str) {
log.warn str
}
void logError(str) {
log.error str
}
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)
}

View File

@@ -0,0 +1,386 @@
/*
* V 0.4 of Aeon Smart Switch 6 code 10/5/2015
* 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.
*
* some code used from various SmartThings device type and metering code from ElasticDev
*
* change log:
* v 0.2 - added support for secure inclusion and command encapsulation
* v 0.3 - added brightness control and zwave power level node report reporting support (6 second button press)
* v 0.4 - added color control for the night light behavior
*/
metadata {
definition (name: "Aeon Smart Switch 6 - RV v0.4", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Energy Meter"
capability "Power Meter"
capability "Actuator"
capability "Switch"
capability "Color Control"
capability "Configuration"
capability "Polling"
capability "Refresh"
capability "Sensor"
command "reset"
fingerprint deviceId: "0x1001", inClusters: "0x98"
fingerprint inClusters: "0x25,0x26,0x27,0x32,0x2C,0x2B,0x33,0x85,0x56,0x59,0x5A,0x5E,0x70,0x72,0x73,0x85,0x86", outClusters: "0x82"
}
// simulator metadata
simulator {
status "on": "command: 2003, payload: FF"
status "off": "command: 2003, payload: 00"
for (int i = 0; i <= 10000; i += 1000) {
status "power ${i} W":
new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage()
}
for (int i = 0; i <= 100; i += 10) {
status "energy ${i} kWh":
new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage()
}
// reply messages
reply "2001FF,delay 100,2502": "command: 2503, payload: FF"
reply "200100,delay 100,2502": "command: 2503, payload: 00"
}
// tile definitions
tiles (scale: 2) {
multiAttributeTile(name:"main", type:"generic", 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: "#79b821"
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
tileAttribute("device.power", key: "SECONDARY_CONTROL") {
attributeState "default",label:'${currentValue} W'
}
}
valueTile("energy", "device.energy", decoration: "flat", width: 2, height: 2) {
state "default", label:'${currentValue} kWh', action:"poll"
}
valueTile("current", "device.current", decoration: "flat", width: 2, height: 2) {
state "default", label:'${currentValue} A', action:"poll"
}
valueTile("voltage", "device.voltage", decoration: "flat", width: 2, height: 2) {
state "default", label:'${currentValue} V', action:"poll"
}
controlTile("rgbSelector", "device.color", "color", height: 2, width: 2, inactiveLabel: false) {
state "color", action:"setColor"
}
standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'reset kWh', action:"reset"
}
standardTile("configure", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
main "main","energy","current","voltage"
details(["main","energy","current","voltage","rgbSelector","reset","refresh","configure"])
}
preferences {
input "ledBehavior", "integer",
title: "LED Behavior",
description: "0=energy tracking, 1=momentary status, 2=night light",
defaultValue: 0,
displayDuringSetup: true,
range: "0..2"
input "monitorInterval", "integer",
title: "Monitoring Interval",
description: "The time interval in seconds for sending device reports",
defaultValue: 60,
range: "1..4294967295",
required: false,
displayDuringSetup: true
input "ledBrightness", "integer",
title: "LED Brightness",
description: "Set the % brightness of indicator LEDs",
defaultValue: 50,
range: "0..100",
required: false,
displayduringSetup: true
}
}
def updated()
{
if (state.sec && !isConfigured()) {
// in case we miss the SCSR
response(configure())
}
}
def parse(String description)
{
def result = null
if (description.startsWith("Err 106")) {
state.sec = 0
result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.")
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x25: 1, 0x26: 1, 0x27: 1, 0x32: 3, 0x33: 3, 0x59: 1, 0x70: 1, 0x72: 2, 0x73: 1, 0x82: 1, 0x85: 2, 0x86: 2])
if (cmd) {
result = zwaveEvent(cmd)
}
}
// log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x25: 1, 0x26: 1, 0x27: 1, 0x32: 3, 0x33: 3, 0x59: 1, 0x70: 1, 0x72: 2, 0x73: 1, 0x82: 1, 0x85: 2, 0x86: 2])
state.sec = 1
// log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
response(configure())
}
def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) {
log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}"
def request = [
physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet()
]
response(commands(request))
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) {
def meterTypes = ["Unknown", "Electric", "Gas", "Water"]
def electricNames = ["energy", "energy", "power", "count", "voltage", "current", "powerFactor", "unknown"]
def electricUnits = ["kWh", "kVAh", "W", "pulses", "V", "A", "Power Factor", ""]
//NOTE ScaledPreviousMeterValue does not always contain a value
def previousValue = cmd.scaledPreviousMeterValue ?: 0
def map = [ name: electricNames[cmd.scale], unit: electricUnits[cmd.scale], displayed: state.display]
switch(cmd.scale) {
case 0: //kWh
previousValue = device.currentValue("energy") ?: cmd.scaledPreviousMeterValue ?: 0
map.value = cmd.scaledMeterValue
break;
case 1: //kVAh
map.value = cmd.scaledMeterValue
break;
case 2: //Watts
previousValue = device.currentValue("power") ?: cmd.scaledPreviousMeterValue ?: 0
map.value = Math.round(cmd.scaledMeterValue)
break;
case 3: //pulses
map.value = Math.round(cmd.scaledMeterValue)
break;
case 4: //Volts
previousValue = device.currentValue("voltage") ?: cmd.scaledPreviousMeterValue ?: 0
map.value = cmd.scaledMeterValue
break;
case 5: //Amps
previousValue = device.currentValue("current") ?: cmd.scaledPreviousMeterValue ?: 0
map.value = cmd.scaledMeterValue
break;
case 6: //Power Factor
case 7: //Unknown
map.value = cmd.scaledMeterValue
break;
default:
break;
}
//Check if the value has changed by more than 5%, if so mark as a stateChange
//map.isStateChange = ((cmd.scaledMeterValue - previousValue).abs() > (cmd.scaledMeterValue * 0.05))
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
[name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
[name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
[name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd)
{
[name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
log.debug "Unhandled: $cmd"
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def on() {
def request = [
zwave.basicV1.basicSet(value: 0xFF),
zwave.basicV1.basicGet(),
zwave.switchBinaryV1.switchBinaryGet()
]
commands(request)
}
def off() {
def request = [
zwave.basicV1.basicSet(value: 0x00),
zwave.basicV1.basicGet(),
zwave.switchBinaryV1.switchBinaryGet()
]
commands(request)
}
def setColor(value) {
def result = []
log.debug "setColor: ${value}"
if (value.hex) {
def c = value.hex.findAll(/[0-9a-fA-F]{2}/).collect { Integer.parseInt(it, 16) }
result << zwave.configurationV1.configurationSet(parameterNumber: 83, size: 3, configurationValue: [c[0], c[1], c[2]])
}
if(value.hex) sendEvent(name: "color", value: value.hex)
commands(result)
}
def poll() {
def request = [
zwave.switchBinaryV1.switchBinaryGet(),
zwave.basicV1.basicGet(),
zwave.meterV3.meterGet(scale: 0), //kWh
zwave.meterV3.meterGet(scale: 1), //kVAh
zwave.meterV3.meterGet(scale: 2), //Wattage
zwave.meterV3.meterGet(scale: 4), //Volts
zwave.meterV3.meterGet(scale: 5), //Amps
zwave.meterV3.meterGet(scale: 6) //Power Factor
]
commands(request)
}
def refresh() {
def request = [
zwave.basicV1.basicGet(),
zwave.switchBinaryV1.switchBinaryGet()
]
commands(request)
}
def reset() {
def request = [
zwave.meterV3.meterReset(),
zwave.meterV3.meterGet(scale: 0), //kWh
zwave.meterV3.meterGet(scale: 1), //kVAh
zwave.meterV3.meterGet(scale: 2), //Wattage
zwave.meterV3.meterGet(scale: 4), //Volts
zwave.meterV3.meterGet(scale: 5), //Amps
zwave.meterV3.meterGet(scale: 6) //Power Factor
]
commands(request)
}
def configure() {
def monitorInt = 60
if (monitorInterval) {
monitorInt=monitorInterval.toInteger()
}
def ledBehave = 0
if (ledBehavior) {
ledBehave=ledBehavior.toInteger()
}
def ledBright = 50
if (ledBrightness) {
ledBright=ledBrightness.toInteger()
}
log.debug "Sending configure commands - monitorInterval '${monitorInt}', ledBehavior '${ledBehave}'"
def request = [
// Reset switch configuration to defaults
// zwave.configurationV1.configurationSet(parameterNumber: 255, size: 1, scaledConfigurationValue: 1),
// Enable to send notifications to associated devices (Group 1) when the state of Micro Switchs load changed (0=nothing, 1=hail CC, 2=basic CC report)
zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, configurationValue: [2]),
// set LED behavior 0 energy mode 1 momentary display 2 night light
zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: ledBehave),
// Set LED brightness
zwave.configurationV1.configurationSet(parameterNumber: 84, size: 3, configurationValue: [ledBright,ledBright,ledBright]),
// Which reports need to send in Report group 1
zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 4|2|1),
// Which reports need to send in Report group 2
zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 8),
// Which reports need to send in Report group 3
zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 0),
// Interval to send Report group 1
zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: monitorInt),
// Interval to send Report group 2
zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 60),
// Interval to send Report group 3
zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 0),
// get LED behavior
zwave.configurationV1.configurationGet(parameterNumber: 81),
// get night light RGB value
zwave.configurationV1.configurationGet(parameterNumber: 83),
// get Energy Mode/momentary indicate LED brightness value
zwave.configurationV1.configurationGet(parameterNumber: 84),
// Which reports need to send in Report group 1
zwave.configurationV1.configurationGet(parameterNumber: 101),
// Which reports need to send in Report group 2
zwave.configurationV1.configurationGet(parameterNumber: 102),
// Which reports need to send in Report group 3
zwave.configurationV1.configurationGet(parameterNumber: 103),
// Interval to send Report group 1
zwave.configurationV1.configurationGet(parameterNumber: 111),
// Interval to send Report group 2
zwave.configurationV1.configurationGet(parameterNumber: 112),
// Interval to send Report group 3
zwave.configurationV1.configurationGet(parameterNumber: 113),
// Can use the zwaveHubNodeId variable to add the hub to the device's associations:
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)
]
commands(request)
}
private setConfigured() {
updateDataValue("configured", "true")
}
private isConfigured() {
getDataValue("configured") == "true"
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=500) {
delayBetween(commands.collect{ command(it) }, delay)
}