Created
August 16, 2020 21:35
-
-
Save staylorx/581b7be701b47690e6427f6e8f9b7c86 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Aeon HEM Gen5 Aeotec Model ZW095-A | |
* https://products.z-wavealliance.org/products/1289 | |
* | |
* Copyright 2020 Ben Rimmasch | |
* | |
* | |
* 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. | |
* | |
* Change Log: | |
* 2020-02-29: Initial | |
* 2020-04-12: Added energy duration to match the OOB drivers | |
* 2020-04-22: Added preference and handled CRC16 encapsulation | |
* Changed precision from 2 decimal places to read precision from the command for meter reports | |
* Added preference and added descriptive logging to meter reports | |
* | |
*/ | |
import groovy.transform.Field | |
// metadata | |
metadata { | |
definition(name: "Aeon HEM Gen5", namespace: "hubitat-codahq", author: "Ben Rimmasch", | |
importUrl: "https://raw.githubusercontent.com/codahq/hubitat_codahq/master/devicestypes/aeotec-hem-gen5.groovy") { | |
capability "Energy Meter" | |
capability "Power Meter" | |
capability "Configuration" | |
capability "Sensor" | |
capability "Refresh" | |
command "reset" | |
attribute "current", "number" | |
attribute "voltage", "number" | |
attribute "cost", "number" | |
attribute "energyDuration", "text" | |
//comment the ones out that you don't want to persist | |
attribute "power1", "number" | |
attribute "power2", "number" | |
attribute "current1", "number" | |
attribute "current2", "number" | |
attribute "voltage1", "number" | |
attribute "voltage2", "number" | |
attribute "cost1", "number" | |
attribute "cost2", "number" | |
fingerprint deviceId: "0x005F", inClusters: "0x5E,0x86,0x72,0x32,0x56,0x60,0x70,0x59,0x85,0x7A,0x73,0x98" | |
} | |
preferences { | |
section("Aeon HEM") { | |
input "kWhCost", "string", title: "Cost in \$ / kWh", defaultValue: "0.144508" as String, | |
required: false, displayDuringSetup: true | |
input name: "enableCrc16Encapsulation", type: "bool", title: "${paramDescriptions[13]}", defaultValue: false | |
input name: "enableSelectiveReports", type: "bool", title: "${paramDescriptions[3]}", defaultValue: false | |
input name: "wholeHemWattTrigger", type: "number", range: 0..60000, title: "${paramDescriptions[4]}", defaultValue: 10 | |
input name: "clamp1WattTrigger", type: "number", range: 0..60000, title: "${paramDescriptions[5]}", defaultValue: 50 | |
input name: "clamp2WattTrigger", type: "number", range: 0..60000, title: "${paramDescriptions[6]}", defaultValue: 50 | |
input name: "wholeHemPercTrigger", type: "number", range: 0..100, title: "${paramDescriptions[8]}", defaultValue: 5 | |
input name: "clamp1PercTrigger", type: "number", range: 0..100, title: "${paramDescriptions[9]}", defaultValue: 10 | |
input name: "clamp2PercTrigger", type: "number", range: 0..100, title: "${paramDescriptions[10]}", defaultValue: 10 | |
input name: "group1Reports", type: "enum", title: "${paramDescriptions[101]}", multiple: true, required: true, options: reportDescriptions, defaultValue: [1, 2, 4, 8] | |
input name: "group2Reports", type: "enum", title: "${paramDescriptions[102]}", multiple: true, required: true, options: reportDescriptions, defaultValue: [256, 512, 2048, 4096] | |
input name: "group3Reports", type: "enum", title: "${paramDescriptions[103]}", multiple: true, required: true, options: reportDescriptions, defaultValue: [65536, 131072, 524288, 1048576] | |
input "group1Interval", "number", title: "${paramDescriptions[111]}", description: "Interval (secs) for reporting group 1 reports", defaultValue: 60, | |
range: "1..4294967295", required: false, displayDuringSetup: true | |
input "group2Interval", "number", title: "${paramDescriptions[112]}", description: "Interval (secs) for reporting group 2 reports", defaultValue: 60, | |
range: "1..4294967295", required: false, displayDuringSetup: true | |
input "group3Interval", "number", title: "${paramDescriptions[113]}", description: "Interval (secs) for reporting group 3 reports", defaultValue: 60, | |
range: "1..4294967295", required: false, displayDuringSetup: true | |
input name: "refreshReturnsConfig", type: "bool", title: "Refresh command requests configuration parameters", defaultValue: false | |
input name: "descriptiveLoggingForMeterReports", type: "bool", title: "Enable descriptionText logging for meter reports", defaultValue: false | |
input name: "descriptionTextEnable", type: "bool", title: "Enable descriptionText logging", defaultValue: false | |
input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: false | |
input name: "traceLogEnable", type: "bool", title: "Enable trace logging", defaultValue: false | |
} | |
} | |
} | |
def updated() { | |
initialize() | |
configure() | |
} | |
def initialize() { | |
if (!state.energyTime) { | |
state.energyTime = new Date().getTime() | |
} | |
if (!state."Explanation About Selective Reporting") { | |
state."Explanation About Selective Reporting" = "Selective reporting is a way to cut down on Z-Wave traffic by " + | |
"excluding reports from sending that don't meet a certain threshold. Selective reporting is only available for " + | |
"periodic wattage reports for the HEM or the individual clamps. What this means is that if you decide to " + | |
"set report group 1 to send you HEM watts, HEM kWh, HEM volts and HEM amps every 5 seconds and if you set the " + | |
"threshold of the HEM watts to 50 watts and 10% the HEM watts report will only send on the 5 second tick where " + | |
"it actually exceeded the threshold. However, the other three reports (HEM kWh, HEM volts and HEM amps) will " + | |
"still send every 5 seconds." | |
} | |
if (!state."Explanation About Reporting Groups") { | |
state."Explanation About Reporting Groups" = "There are three reporting groups. You can choose as many data points " + | |
"for each group as you want. All of the data points chosen will be reported at the interval specified for each " + | |
"group. Certain combinations do not work for some reason. There is a chart in the PDF documentation that (I think) " + | |
"explains the combinations that do not work but I don't understand it.\n" | |
} | |
if (!state."Explanation About Preferences") { | |
state."Explanation About Preferences" = "Unfortunately, since Hubitat doesn't support multi-select preferences in " + | |
"drivers you will have to select your reports EVERY time you save preferences. Please bring it up with the HE " + | |
"platform developers to prioritize this feature.\n" + | |
"When you first install the driver each of the reporting group multi-select preferences will be single select. " + | |
"Choose any option and save and they will become multi-select on reload." | |
} | |
} | |
def refresh() { | |
//Get HEM totals | |
def request = [ | |
zwave.meterV3.meterGet(scale: 0), //kWh | |
zwave.meterV3.meterGet(scale: 2), //Wattage | |
zwave.meterV3.meterGet(scale: 4), //Volts | |
zwave.meterV3.meterGet(scale: 5), //Amps | |
] | |
//add parameter query | |
if (refreshReturnsConfig) { | |
request += configurationGets | |
} | |
commands(request) | |
} | |
def reset() { | |
def curr = new Date() | |
def stamp = curr.format("YYYY-MM-dd", location.timeZone) + " @ " + curr.format("h:mm a", location.timeZone) | |
state."Last Reset Time" = stamp | |
state.energyTime = curr.getTime() | |
def request = [ | |
zwave.meterV3.meterReset(), | |
zwave.meterV3.meterGet(scale: 0), //kWh | |
zwave.meterV3.meterGet(scale: 2), //Wattage | |
zwave.meterV3.meterGet(scale: 4), //Volts | |
zwave.meterV3.meterGet(scale: 5), //Amps | |
] | |
commands(request) | |
} | |
def configure() { | |
logInfo "Configuring device ${device.label}" | |
def request = [ | |
//Reset meter parameters to defaults | |
//zwave.configurationV1.configurationSet(parameterNumber: 255, size: 1, scaledConfigurationValue: 1), | |
//Reset parameters 101-103 to defaults | |
//zwave.configurationV1.configurationSet(parameterNumber: 100, size: 1, scaledConfigurationValue: 1), | |
//Reset parameters 111-113 to defaults | |
//zwave.configurationV1.configurationSet(parameterNumber: 110, size: 1, scaledConfigurationValue: 1), | |
// Associate so that reports work | |
zwave.associationV2.associationRemove(groupingIdentifier: 1, nodeId: []), | |
zwave.associationV2.associationSet(groupingIdentifier: 1, nodeId: zwaveHubNodeId), | |
//Selective reports. Set to 0 to reduce network traffic. If disabled reports by from parameters 4-11 are disabled | |
zwave.configurationV1.configurationSet(parameterNumber: 3, size: 1, scaledConfigurationValue: enableSelectiveReports ? 1 : 0), | |
//Trigger HEM watts with change by this value (default 10) | |
zwave.configurationV1.configurationSet(parameterNumber: 4, size: 2, scaledConfigurationValue: wholeHemWattTrigger), | |
//Trigger clamp 1 watts with change by this value (default 50) | |
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 2, scaledConfigurationValue: clamp1WattTrigger), | |
//Trigger clamp 2 watts with change by this value (default 50) | |
zwave.configurationV1.configurationSet(parameterNumber: 6, size: 2, scaledConfigurationValue: clamp2WattTrigger), | |
//Trigger HEM watts with change by this percent (default 5%) | |
zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: wholeHemPercTrigger), | |
//Trigger clamp 1 watts with change by this percent (default 10%) | |
zwave.configurationV1.configurationSet(parameterNumber: 9, size: 1, scaledConfigurationValue: clamp1PercTrigger), | |
//Trigger clamp 2 watts with change by this percent (default 10%) | |
zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: clamp2PercTrigger), | |
//Set Crc16 Encapsulation | |
zwave.configurationV1.configurationSet(parameterNumber: 13, size: 1, scaledConfigurationValue: enableCrc16Encapsulation ? 1 : 0), | |
// Which reports need to send in Report group 1. | |
zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: group1Reports.collect { | |
it.toInteger() | |
}.sum()), | |
// Which reports need to send in Report group 2. | |
zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: group2Reports.collect { | |
it.toInteger() | |
}.sum()), | |
// Which reports need to send in Report group 3. | |
zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: group3Reports.collect { | |
it.toInteger() | |
}.sum()), | |
// Interval to send Report group 1. | |
zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: group1Interval.toInteger()), | |
// Interval to send Report group 2. | |
zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: group2Interval.toInteger()), | |
// Interval to send Report group 3. | |
zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: group3Interval.toInteger()) | |
] | |
// Report which configuration commands were sent to and received by the HEM Gen5 successfully. | |
request += configurationGets | |
commands(request) | |
} | |
def parse(String description) { | |
logDebug "parse(description)" | |
logTrace "description: $description" | |
def result | |
def cmd = zwave.parse(description, commandClasses) | |
if (cmd) { | |
result = zwaveEvent(cmd) | |
} | |
else { | |
log.warn "Command not parsed! ${description}" | |
} | |
return result | |
} | |
def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) { | |
logDebug "zwaveEvent(hubitat.zwave.commands.securityv1.SecurityMessageEncapsulation cmd)" | |
logTrace "cmd: $cmd" | |
state.secure = 1 | |
def encapCmd = cmd.encapsulatedCommand(commandClasses) | |
logTrace "encap cmd: ${encapCmd}" | |
if (encapCmd) { | |
zwaveEvent(encapCmd) | |
} | |
else { | |
log.warn "Unable to extract security message encapsulated cmd from $cmd" | |
createEvent(descriptionText: cmd.toString()) | |
} | |
} | |
//def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) { | |
// logDebug "zwaveEvent(hubitat.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd)" | |
// logTrace "cmd: $cmd" | |
//} | |
def zwaveEvent(hubitat.zwave.commands.configurationv2.ConfigurationReport cmd) { | |
logDebug "zwaveEvent(hubitat.zwave.commands.configurationv2.ConfigurationReport cmd)" | |
logTrace "cmd: $cmd" | |
def value = cmd.scaledConfigurationValue?.toInteger() | |
logTrace "value: $value" | |
switch (cmd.parameterNumber) { | |
case 2: | |
sendConfigEvent(cmd.parameterNumber, detectionModeDescriptions[value]) | |
break | |
case 3: | |
case 13: | |
case 252: | |
sendConfigEvent(cmd.parameterNumber, value ? "enabled" : "disabled") | |
break | |
case 4: | |
case 5: | |
case 6: | |
sendConfigEvent(cmd.parameterNumber, "Trigger change by ${value} watts") | |
break | |
case 8: | |
case 9: | |
case 10: | |
sendConfigEvent(cmd.parameterNumber, "Trigger change by ${value}%") | |
break | |
case 101: | |
case 102: | |
case 103: | |
sendConfigEvent(cmd.parameterNumber, getReportsFromInt(value)) | |
break | |
case 111: | |
case 112: | |
case 113: | |
sendConfigEvent(cmd.parameterNumber, "Trigger every ${value} seconds") | |
break | |
case 200: | |
case 254: | |
sendConfigEvent(cmd.parameterNumber, "${value}") | |
break | |
default: | |
log.warn "Unhandled parameter ${cmd.parameterNumber} with value ${value}" | |
break | |
} | |
} | |
private sendConfigEvent(short param, String desc) { | |
logInfo "Parameter ${param} \"${paramDescriptions[param as int]}\" has value:: ${desc}" | |
sendEvent([name: paramDescriptions[param as int], value: desc]) | |
} | |
def zwaveEvent(hubitat.zwave.commands.associationv2.AssociationReport cmd) { | |
logDebug "zwaveEvent(hubitat.zwave.commands.associationv2.AssociationReport cmd)" | |
logTrace "cmd: $cmd" | |
logInfo "Assocation Group ${cmd.groupingIdentifier} has nodes :: ${cmd.nodeId}" | |
sendEvent([name: "Group 1 Assocations", value: cmd.nodeId]) | |
} | |
def zwaveEvent(hubitat.zwave.commands.versionv1.VersionReport cmd) { | |
logDebug "zwaveEvent(hubitat.zwave.commands.versionv1.VersionReport cmd)" | |
logTrace "cmd: $cmd" | |
def firmware = "${cmd.applicationVersion}.${cmd.applicationSubVersion}" | |
updateDataValue("firmware", firmware) | |
logDebug "${device.displayName} is running firmware version: $firmware, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}" | |
} | |
def zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) { | |
logDebug "zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd)" | |
logTrace "cmd: $cmd" | |
logDebug "manufacturerId: ${cmd.manufacturerId}" | |
logDebug "manufacturerName: ${cmd.manufacturerName}" | |
logDebug "productId: ${cmd.productId}" | |
logDebug "productTypeId: ${cmd.productTypeId}" | |
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId) | |
updateDataValue("MSR", msr) | |
updateDataValue("manufacturer", cmd.manufacturerId.toString()) | |
updateDataValue("manufacturerName", cmd.manufacturerName) | |
sendEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false]) | |
} | |
def zwaveEvent(hubitat.zwave.commands.meterv3.MeterReport cmd, int clamp = 0) { | |
logDebug "zwaveEvent(hubitat.zwave.commands.meterv3.MeterReport cmd)" | |
logTrace "cmd: $cmd" | |
def sourceName = clamp == 0 ? "HEM" : "Clamp ${clamp}" | |
def source = clamp == 0 ? "" : "${clamp}" | |
def value = String.format("%5.${cmd.precision}f", cmd.scaledMeterValue) | |
switch (cmd.scale) { | |
case 1: //kVAh | |
case 3: //pulses | |
case 4: //volts | |
case 6: //power factor | |
case 7: //scale2 values | |
break | |
case 0: //kWh | |
def cost = String.format("%5.2f", cmd.scaledMeterValue * (kWhCost as BigDecimal)) | |
def msg = "${sourceName} cost is \$${cost}" | |
logInfo msg | |
sendEvent(name: "cost${source}", value: cost, unit: "", descriptionText: msg) | |
def dur_ms = new Date().getTime() - state.energyTime | |
def days = (dur_ms / (1000.0 * 60.0 * 60.0 * 24.0)) | |
sendEvent(name: "energyDuration", value: "${formatDays(days)} Days") | |
break | |
case 2: //WATTS | |
if (cmd.scaledMeterValue > MAX_WATTS) { | |
log.warn "Watts ${cmd.scaledMeterValue} too high for ${sourceName}" | |
return | |
} | |
break | |
case 5: //Amps | |
if (cmd.scaledMeterValue > MAX_AMPS) { | |
log.warn "Amps ${cmd.scaledMeterValue} too high for ${sourceName}" | |
return | |
} | |
break | |
default: | |
log.warn "scale ${cmd.scale} not handled!" | |
break | |
} | |
def msg = "${sourceName} ${unitNames[cmd.scale]} is ${value} ${unitAbbrs[cmd.scale]}" | |
if (descriptiveLoggingForMeterReports) { | |
logInfo msg | |
} | |
sendEvent(name: "${unitNames[cmd.scale]}${source}", value: cmd.scaledMeterValue, unit: "", descriptionText: msg) | |
} | |
def zwaveEvent(hubitat.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) { | |
logDebug "zwaveEvent(hubitat.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd)" | |
logTrace "cmd: $cmd" | |
if (cmd.commandClass == 50) { | |
//extract encapsulated command | |
def encapCmd = cmd.encapsulatedCommand([0x30: 1, 0x31: 1]) | |
logTrace "Command from clamp ${cmd.sourceEndPoint}: ${encapCmd}" | |
if (encapCmd) { | |
zwaveEvent(encapCmd, cmd.sourceEndPoint) | |
} | |
else { | |
log.warn "Couldn't extract encapsulated command!" | |
} | |
} | |
else { | |
log.warn "cmd.commandClass: ${cmd.commandClass}" | |
} | |
} | |
def zwaveEvent(hubitat.zwave.commands.crc16encapv1.Crc16Encap cmd) { | |
logDebug "zwaveEvent(hubitat.zwave.commands.crc16encapv1.Crc16Encap cmd)" | |
logTrace "cmd: $cmd" | |
def version = commandClasses[cmd.commandClass as int] ?: 1 | |
def encapsulatedCommand = zwave.getCommand(cmd.commandClass, cmd.command, cmd.data, version) | |
if (!encapsulatedCommand) { | |
log.warn "zwaveEvent(): Could not extract command from ${cmd}" | |
} | |
else { | |
logDebug("zwaveEvent(): Extracted command ${encapsulatedCommand}") | |
return zwaveEvent(encapsulatedCommand) | |
} | |
} | |
def zwaveEvent(hubitat.zwave.Command cmd) { | |
log.warn "Unhandled: $cmd" | |
createEvent(descriptionText: cmd.toString(), isStateChange: false) | |
} | |
def getConfigurationGets() { | |
return [ | |
zwave.configurationV1.configurationGet(parameterNumber: 2), //Energy detection mode configuration for parameters 101~103 | |
zwave.configurationV1.configurationGet(parameterNumber: 3), //enable/disable parameter selective reporting parameters 4~10 | |
zwave.configurationV1.configurationGet(parameterNumber: 4), //Induce an automatic report of HEM by watts | |
zwave.configurationV1.configurationGet(parameterNumber: 5), //Induce an automatic report of Channel 1 by watts | |
zwave.configurationV1.configurationGet(parameterNumber: 6), //Induce an automatic report of Channel 2 by watts | |
zwave.configurationV1.configurationGet(parameterNumber: 8), //Induce an automatic report of HEM by percent | |
zwave.configurationV1.configurationGet(parameterNumber: 9), //Induce an automatic report of Channel 1 by percent | |
zwave.configurationV1.configurationGet(parameterNumber: 10), //Induce an automatic report of Channel 2 by percent | |
zwave.configurationV1.configurationGet(parameterNumber: 13), //Enable/disable CRC-16 Encapsulation | |
zwave.configurationV1.configurationGet(parameterNumber: 101), //Report group 1 reports | |
zwave.configurationV1.configurationGet(parameterNumber: 102), //Report group 2 reports | |
zwave.configurationV1.configurationGet(parameterNumber: 103), //Report group 3 reports | |
zwave.configurationV1.configurationGet(parameterNumber: 111), //Report group 1 frequency | |
zwave.configurationV1.configurationGet(parameterNumber: 112), //Report group 2 frequency | |
zwave.configurationV1.configurationGet(parameterNumber: 113), //Report group 3 frequency | |
zwave.configurationV1.configurationGet(parameterNumber: 200), //Is Aeon or Third-party | |
zwave.configurationV1.configurationGet(parameterNumber: 252), //Configuration locked? | |
zwave.configurationV1.configurationGet(parameterNumber: 254), //Device Tag | |
zwave.associationV2.associationGet(groupingIdentifier: 1), | |
zwave.versionV1.versionGet(), | |
zwave.manufacturerSpecificV1.manufacturerSpecificGet() | |
] | |
} | |
private getCommandClasses() { | |
[ | |
0x32: 3, | |
0x56: 1, | |
0x59: 1, | |
0x5A: 1, | |
//0x5E: 2, | |
0x60: 3, | |
0x70: 4, //even though firmware v1.31 on hubitat reports 1 | |
0x72: 2, | |
0x73: 1, | |
//0x7A: 2, | |
0x82: 1, | |
0x85: 2, | |
0x86: 1, //even though firmware v1.31 on hubitat reports v2 | |
0x8E: 2, | |
//0x98: 1, | |
0xEF: 1 | |
] | |
} | |
@Field def detectionModeDescriptions = [ | |
0: "(Default) Report wattage and the absolute KWH value", | |
1: "Report positive/negative wattage and the algebraic sum KWH value", | |
2: "Report positive/negative wattage and the positive KWH value (consuming electricity)", | |
3: "Report positive/negative wattage and the negative KWH value (generating electricity)" | |
] | |
@Field def paramDescriptions = [ | |
2: "Group Reporting Energy Detection Mode ", //parameters 101~103 | |
3: "Selective Reporting", //parameters 4~11 | |
4: "Whole HEM Watts Change", | |
5: "Clamp 1 Watts Change", | |
6: "Clamp 2 Watts Change", | |
7: "Clamp 3 Watts Change", | |
8: "Whole HEM Watts Percentage Change", | |
9: "Clamp 1 Watts Percentage Change", | |
10: "Clamp 2 Watts Percentage Change", | |
11: "Clamp 3 Watts Percentage Change", | |
13: "CRC-16 Encapsulation", | |
101: "Reporting Group 1", | |
102: "Reporting Group 2", | |
103: "Reporting Group 3", | |
111: "Reporting Group 1 Frequency", | |
112: "Reporting Group 2 Frequency", | |
113: "Reporting Group 3 Frequency", | |
200: "Partner ID", | |
252: "Configuration Locked?", | |
254: "Device Tag" | |
] | |
@Field def reportDescriptions = [ | |
1: "KWH HEM", | |
2: "Watts HEM", | |
4: "Voltage HEM", | |
8: "Current HEM", | |
16: "kVarh HEM", | |
32: "kVar HEM", | |
256: "Watts Clamp 1", | |
512: "Watts Clamp 2", | |
//1024: "Watts Clamp 3", | |
2048: "KWH Clamp 1", | |
4096: "KWH Clamp 2", | |
//8192: "KWH Clamp 3", | |
65536: "Voltage Clamp 1", | |
131072: "Voltage Clamp 2", | |
//262144: "Voltage Clamp 3", | |
524288: "Current (Amperes) Clamp 1", | |
1048576: "Current (Amperes) Clamp 2", | |
//2097152: "Current (Amperes) Clamp 3" | |
] | |
@Field def unitNames = ["energy", "energy", "power", "count", "voltage", "current", "powerFactor", "unknown"] | |
@Field def unitAbbrs = ["kWh", "kVAh", "W", "pulses", "V", "A", "Power Factor", ""] | |
@Field def MAX_AMPS = 220 | |
@Field def MAX_WATTS = 24000 | |
private getReportsFromInt(int value) { | |
def result = [] | |
while (value > 0) { | |
reportDescriptions.reverseEach { | |
if (value >= it.key) { | |
value = value - it.key | |
result << it.value | |
} | |
} | |
} | |
return "${result.reverse()}" | |
} | |
private command(hubitat.zwave.Command cmd) { | |
if (state.secure) { | |
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() | |
} | |
else { | |
cmd.format() | |
} | |
} | |
private commands(commands, delay = 500) { | |
delayBetween(commands.collect { command(it) }, delay) | |
} | |
private String formatDays(BigDecimal duration) { | |
java.text.DecimalFormat df = new java.text.DecimalFormat(); | |
df.setMaximumFractionDigits(2); | |
df.setMinimumFractionDigits(0); | |
df.setGroupingUsed(false); | |
return df.format(duration); | |
} | |
private logInfo(msg) { | |
if (descriptionTextEnable) log.info msg | |
} | |
def logDebug(msg) { | |
if (logEnable) log.debug msg | |
} | |
def logTrace(msg) { | |
if (traceLogEnable) log.trace msg | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment