I got this working with no issues for reading the clamps and reporting the values, however I can not figure out how to get it to refresh the values in the dashboard or viewing them within the device. If I hit the refresh button the values are updated. Anyone else have this issue and resolve it? Also should I stay on FW 1.31 or upgrade to 1.35?
No! 1.35 is a mess be glad you have 1.31 (I wish I did, wanna trade?)
What values are you looking for and how to you have your preferences setup? Please post screen shots and details on prefs selection and log files, so we can help.
Enable "descriptiveText logging for meter reports"
That should at least create a log for the events. If it does not fix the refresh, post the log please.
I set Reporting Group 1 Frequency
Interval (secs) for reporting group 1 reports
to 20.
Works great.
I fixed it by creating a device refresh at X min. Also applied the same to my garage lock which sometimes would not report back that it was open after double turning to unlock until locked again by someone.
Might be a hack at it but it's working.
As long as your X is reasonable, and you don't have to do it with lots of devices, it should be ok.
I went with 15 minutes. The Information is not that important for me to have a constant refresh.
Thanks!
Since the github link is gone nowI am posting my copy of @codahq's code here. @markebby
I have also reached out to @codahq to make sure he is doing well, and see what is going on with the github. We hope it's all good with him enjoying vacation. Will update when possible.
See below.
It is with much regret that I learned @codahq is no longer supporting Hubitat. To my knowledge that includes this driver.
The code posted here is from the last time he, and I worked on it. This is sad since we were also working with Aeotec to fix a known bug with firmware v1.35, and I was enjoying being able to contribute. This code was/is all Ben's fine work with not much help but testing, and complaining from me.
Unfortunately I'm not a coder and cannot maintain this driver or help with any problems that may come from using it. If anyone who is capable would like to carry on Ben's fine work (with proper credit due), I would be happy to work with them in any testing capacity needed.
/*
* 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
}
Thanks. This worked for me!
Working for me.
How do you guys do reporting for one specific month?
I have a webcore routine that resets my device each month. Just before reset I write the current month's energy data to a thingsspeak graph. I want to switch this to Hubigraphs, but the current version will only display 2 months of data. I use a virtual sensor to hold the data for HE, but you could also write it to a file with HE or write to a google spreadsheet.
Sounds complicated and tedious. How do you do it with the virtual sensor?
Just read the month's end usage from your HEM and then write it to a Virtual Sensor. The virtual sensor then holds your monthly energy usage. I mainly did this so I could then use Hubigraphs to plot the data. I do the same for my daily and hourly energy usage as well. Those I can plot with hubigraphs and see in my dashboard. The monthly is not very useful right now because as I mentioned hubigraphs will only let you keep about 2 months of data, and can only plot about 1. The developer has said he may extend that at some point.
So I still send my monthly data to a free thingspeak account and plot that data there.
My HEM is actually still connected to ST, but I control everything through HE via Hubconnect. I have to reset the HEM with ST as the Hubconnect driver won't let me, but I read all my energy data using RM. My plan is to move the HEM to HE when I get my C7 hub up and running. I just haven't got around to it yet.
The RM rules to capture and store the data in the virtual sensor are not that complicated.
This is the rule for capturing the daily data and writing to a sensor. EnergyMidnight is a global that I set at midnight with the energy reading from the HEM. Daily Energy is the virtual sensor.
thank you so much for the explanation. Will try to apply the same to mine.
@TechMedX I'm working on getting this working with my 2 clamp v5 HEM to monitor my dryer.
Any idea on what my preferences should be set to get power and current readings? I have my reporting groups setup as per your first post here. Thanks.
@inetjnky If you have it set like my first post it should look like this (except not negative numbers)...
Once you have selected all 3 items per group using the CTRL key, hit "Preferences." and then "Configure".
Funny enough I just move from C4 to C7 yesterday. I actually just reset them using my 1st posy after you mentioned it, thanks!