Sure, its not my code, I have just added and modified bits. I will try to clean it up for generic use. Key here is parsing the zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd)
Also note sections where you see “encapsulatedCommand.scaledMeterValue * 1.160437”, this is a correction that apply to my meter readings and you will not need to.
scaledConfigurationValue: in configure section for parameter 111, 112 ans 113 is all in seconds
zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 20).format()
1573640 at 103 asks the HEM to send Amps for each clamp, Watts for each clamp and Amps of combined clamps every 20s as set in 113.
/**
* HEM G2 V2.0
*
* Author: Jayant Jhamb (This is a heavily borrowed code from "Barry A. Burke")
*
* Date: 2014-11-06
**/
// for the UI
metadata {
// Automatically generated. Make future change here.
definition (name: "HEM G2 V2.0", author: "Jayant Jhamb") {
capability "Power Meter"
capability "Sensor"
capability "Energy Meter"
capability "Configuration"
attribute "voltage", "string"
attribute "amps", "string"
attribute "powerOne", "string"
attribute "powerTwo", "string"
attribute "energyOne", "string"
attribute "energyTwo", "string"
attribute "ampsOne", "string"
attribute "ampsTwo", "string"
attribute "dataOne", "string"
attribute "dataTwo", "string"
command "refresh"
command "reset"
command "enableDelta"
command "disableDelta"
command "alertHighLoad"
command "testConfiguration"
command "WakeUp"
command "appUpdate"
fingerprint deviceId: "0x2101", inClusters: " 0x70,0x31,0x72,0x86,0x32,0x80,0x85,0x60"
}
// simulator metadata
simulator {
for (int i = 0; i <= 10000; i += 1000) {
status "power ${i} W": new physicalgraph.zwave.Zwave().meterV1.meterReport(
scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage()
}
}
// tile definitions
tiles {
valueTile("power", "device.power") {
state (
"default",
label:'${currentValue} Watt',
foregroundColors:[
[value: 1, color: "#000000"],
[value: 10000, color: "#ffffff"]
],
foregroundColor: "#000000",
backgroundColors:[
[value: "0 Watts", color: "#000000"],
[value: "500 Watts", color: "#0056C9"],
[value: "1000 Watts", color: "#118E8E"],
[value: "2000 Watts", color: "#198E11"],
[value: "3000 Watts", color: "#C9AE00"],
[value: "4000 Watts", color: "#D15212"],
[value: "5000 Watts", color: "#C91000"],
[value: "6000 Watts", color: "#8E071A"],
[value: "7000 Watts", color: "#8E0789"]
]
)
}
valueTile("powerOne", "device.powerOne") {
state (
"default",
label:'${currentValue}W C1',
foregroundColors:[
[value: 1, color: "#000000"],
[value: 10000, color: "#ffffff"]
],
foregroundColor: "#000000",
backgroundColors:[
[value: "0 Watts", color: "#000000"],
[value: "500 Watts", color: "#0056C9"],
[value: "1000 Watts", color: "#118E8E"],
[value: "2000 Watts", color: "#198E11"],
[value: "3000 Watts", color: "#C9AE00"],
[value: "4000 Watts", color: "#D15212"],
[value: "5000 Watts", color: "#C91000"],
[value: "6000 Watts", color: "#8E071A"],
[value: "7000 Watts", color: "#8E0789"]
]
)
}
valueTile("powerTwo", "device.powerTwo") {
state (
"default",
label:'${currentValue}W C2',
foregroundColors:[
[value: 1, color: "#000000"],
[value: 10000, color: "#ffffff"]
],
foregroundColor: "#000000",
backgroundColors:[
[value: "0 Watts", color: "#000000"],
[value: "500 Watts", color: "#0056C9"],
[value: "1000 Watts", color: "#118E8E"],
[value: "2000 Watts", color: "#198E11"],
[value: "3000 Watts", color: "#C9AE00"],
[value: "4000 Watts", color: "#D15212"],
[value: "5000 Watts", color: "#C91000"],
[value: "6000 Watts", color: "#8E071A"],
[value: "7000 Watts", color: "#8E0789"]
]
)
}
valueTile("amps", "device.amps", decoration: "flat") {
state "default", label:'${currentValue} A'
}
valueTile("ampsOne", "device.ampsOne", decoration: "flat") {
state "default", label:'${currentValue}A C1'
}
valueTile("ampsTwo", "device.ampsTwo", decoration: "flat") {
state "default", label:'${currentValue}A C2'
}
valueTile("energy", "device.energy", decoration: "flat") {
state "default", label:'${currentValue}', unit:"kWh"
}
valueTile("energyOne", "device.energyOne", decoration: "flat") {
state "default", label:'${currentValue}', unit:"kWh"
}
valueTile("energyTwo", "device.energyTwo", decoration: "flat") {
state "default", label:'${currentValue}', unit:"kWh"
}
valueTile("dataOne", "device.consOne", decoration: "flat") {
state "default", label:'${currentValue} Units'
}
valueTile("dataTwo", "device.consTwo", decoration: "flat") {
state "default", label:'${currentValue} Units'
}
valueTile("voltage", "device.voltage", decoration: "flat") {
state "default", label:'${currentValue} V'
}
standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat") {
state "default", label:'reset kWh', action:"reset"
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
standardTile("configure", "device.power", inactiveLabel: false, decoration: "flat") {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
main (["power","powerOne","powerTwo","energy"])
details([
"power","powerOne","powerTwo",
"amps","ampsOne","ampsTwo",
"energy",
"refresh","configure","reset"
])
}
}
def parse(String description) {
def result = null
def cmd = zwave.parse(description, [0x31: 1, 0x32: 1, 0x60: 3])
// log.debug cmd
if (cmd) {
// log.debug zwaveEvent(cmd)
result = createEvent(zwaveEvent(cmd))
}
if (result) {
log.debug “Parse returned ${result?.descriptionText}”
// log.debug "Parse returned result ${result}"
return result
} else {
// log.debug “No Result for ${cmd}”
}
}
def zwaveEvent(physicalgraph.zwave.commands.meterv1.MeterReport cmd) {
// log.debug cmd
if (cmd.meterType == 33 && cmd.scale == 0) {
[name: "energy", value: Math.round(cmd.scaledMeterValue * 10) / 10 , unit: "kWh"]
}
else if (cmd.meterType == 161 && cmd.scale == 0) {
[name: "voltage", value: Math.round(cmd.scaledMeterValue), unit: "V"]
}
else if (cmd.meterType == 161 && cmd.scale == 1) {
[name: "amps", value: cmd.scaledMeterValue, unit: "A"]
}
else if (cmd.meterType == 33 && cmd.scale == 2) {
[name: "power", value: Math.round(cmd.scaledMeterValue), unit: "W"]
}
}
def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
// log.debug “MultiChannelCmdEncap $cmd”
// log.debug "cmd.commandClass == ${cmd.commandClass} // cmd.command == ${cmd.command} // cmd.parameter == ${cmd.parameter} // cmd.sourceEndPoint == ${cmd.sourceEndPoint}"
if (cmd.commandClass == 50) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x30: 1, 0x31: 1]) // can specify command class versions here like in zwave.parse
if (encapsulatedCommand) {
if (cmd.sourceEndPoint == 1) {
// -- Test
// log.debug encapsulatedCommand
// log.debug zwaveEvent(encapsulatedCommand)
//— Test
if (encapsulatedCommand.scale == 2 ){
[name: "powerOne", value: Math.round(encapsulatedCommand.scaledMeterValue) as String, unit: "W", descriptionText: "Clamp1 Power Usage ${Math.round(encapsulatedCommand.scaledMeterValue)} W"]
} else if (encapsulatedCommand.scale == 0 ){
[name: "energyOne", value: Math.round(encapsulatedCommand.scaledMeterValue) as String, unit: "kWh", descriptionText: "Clamp1 Energy Usage ${Math.round(encapsulatedCommand.scaledMeterValue)} kWh"]
} else if (encapsulatedCommand.scale == 5 ){
[name: "ampsOne", value: encapsulatedCommand.scaledMeterValue as String, unit: "A", descriptionText: "Clamp1 Current Draw ${encapsulatedCommand.scaledMeterValue} A"]
} else if (encapsulatedCommand.scale == 4 ){
[name: "voltsOne", value: encapsulatedCommand.scaledMeterValue as String, unit: "V"]
}
} else if (cmd.sourceEndPoint == 2) {
if (encapsulatedCommand.scale == 2 ){
[name: "powerTwo", value: Math.round(encapsulatedCommand.scaledMeterValue) as String, unit: "W", descriptionText: "Clamp2 Power Usage ${Math.round(encapsulatedCommand.scaledMeterValue)} W"]
} else if (encapsulatedCommand.scale == 0 ){
[name: "energyTwo", value: Math.round(encapsulatedCommand.scaledMeterValue) as String, unit: "kWh", descriptionText: "Clamp2 Energy Usage ${Math.round(encapsulatedCommand.scaledMeterValue)} kWh"]
} else if (encapsulatedCommand.scale == 5 ){
[name: "ampsTwo", value: encapsulatedCommand.scaledMeterValue as String, unit: "A", descriptionText: "Clamp2 Current Draw ${encapsulatedCommand.scaledMeterValue} A"]
} else if (encapsulatedCommand.scale == 4 ){
[name: "voltsTwo", value: encapsulatedCommand.scaledMeterValue as String, unit: "V"]
}
}
}
}
}
/*
def zwaveEvent(physicalgraph.zwave.commands.meterv1.MeterReport cmd) {
// log.debug cmd
if (cmd.meterType == 33 && cmd.scale == 0) {
[name: "energy", value: Math.round(((cmd.scaledMeterValue - 4465.5) * 1.160437) * 10) / 10 + 96700, unit: "kWh"]
}
else if (cmd.meterType == 161 && cmd.scale == 0) {
[name: "voltage", value: Math.round(cmd.scaledMeterValue * 1.135), unit: "V"]
}
else if (cmd.meterType == 161 && cmd.scale == 1) {
[name: "amps", value: cmd.scaledMeterValue, unit: "A"]
}
else if (cmd.meterType == 33 && cmd.scale == 2) {
[name: "power", value: Math.round(cmd.scaledMeterValue * 1.160437), unit: "W"]
}
}
// MultiChannelCmdEncap and MultiInstanceCmdEncap are ways that devices can indicate that a message
// is coming from one of multiple subdevices or “endpoints” that would otherwise be indistinguishable
def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
//log.debug “-----------------------------------------------”
// log.debug “MultiChannelCmdEncap $cmd”
// log.debug "cmd.commandClass == ${cmd.commandClass} // cmd.command == ${cmd.command} // cmd.parameter == ${cmd.parameter} // cmd.sourceEndPoint == ${cmd.sourceEndPoint}"
if (cmd.commandClass == 50) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x30: 1, 0x31: 1]) // can specify command class versions here like in zwave.parse
if (encapsulatedCommand) {
if (cmd.sourceEndPoint == 1) {
// – Test
// log.debug encapsulatedCommand
// log.debug zwaveEvent(encapsulatedCommand)
//— Test
if (encapsulatedCommand.scale == 2 ){
//sendEvent(name: “powerOne”, value: Math.round((encapsulatedCommand.scaledMeterValue * 1.160437)) as String, unit: “W”, descriptionText: “Clamp1 Power Usage is ${Math.round((encapsulatedCommand.scaledMeterValue * 1.160437))} Watts”)
[name: “powerOne”, value: Math.round((encapsulatedCommand.scaledMeterValue * 1.160437)) as String, unit: “W”, descriptionText: “Clamp1 Power Usage ${Math.round((encapsulatedCommand.scaledMeterValue * 1.160437))} W”]
} else if (encapsulatedCommand.scale == 0 ){
[name: “energyOne”, value: (encapsulatedCommand.scaledMeterValue * 1.160437) as String, unit: “kWh”, descriptionText: “Clamp1 Energy Usage ${Math.round((encapsulatedCommand.scaledMeterValue * 1.160437))} kWh”]
} else if (encapsulatedCommand.scale == 5 ){
[name: “ampsOne”, value: encapsulatedCommand.scaledMeterValue as String, unit: “A”, descriptionText: “Clamp1 Current Draw ${encapsulatedCommand.scaledMeterValue} A”]
} else if (encapsulatedCommand.scale == 4 ){
[name: “voltsOne”, value: encapsulatedCommand.scaledMeterValue as String, unit: “V”]
}
} else if (cmd.sourceEndPoint == 2) {
if (encapsulatedCommand.scale == 2 ){
[name: “powerTwo”, value: Math.round((encapsulatedCommand.scaledMeterValue * 1.160437)) as String, unit: “W”, descriptionText: “Clamp2 Power Usage ${Math.round((encapsulatedCommand.scaledMeterValue * 1.160437))} W”]
} else if (encapsulatedCommand.scale == 0 ){
[name: “energyTwo”, value: (encapsulatedCommand.scaledMeterValue * 1.160437) as String, unit: “kWh”, descriptionText: “Clamp2 Energy Usage ${Math.round((encapsulatedCommand.scaledMeterValue * 1.160437))} kWh”]
} else if (encapsulatedCommand.scale == 5 ){
[name: “ampsTwo”, value: encapsulatedCommand.scaledMeterValue as String, unit: “A”, descriptionText: “Clamp2 Current Draw ${encapsulatedCommand.scaledMeterValue} A”]
} else if (encapsulatedCommand.scale == 4 ){
[name: “voltsTwo”, value: encapsulatedCommand.scaledMeterValue as String, unit: “V”]
}
}
}
}
}
*/
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren’t interested in
[:]
}
def refresh() {
log.debug "Doing Refresh"
def cmd = delayBetween([
zwave.meterV2.meterGet(scale: 0).format(),
zwave.meterV2.meterGet(scale: 2).format()
])
log.debug cmd
cmd
}
def reset() {
// No V1 available
return [
zwave.meterV2.meterReset().format(),
zwave.meterV2.meterGet(scale: 0).format()
]
}
def enableDelta() {
log.debug "Executing ‘enableDelta’"
def cmd = delayBetween([
zwave.configurationV1.configurationSet(parameterNumber: 3, size: 1, scaledConfigurationValue: 1).format()
])
log.debug cmd
cmd
}
def disableDelta() {
log.debug "Executing ‘disableDelta’"
def cmd = delayBetween([
zwave.configurationV1.configurationSet(parameterNumber: 3, size: 1, scaledConfigurationValue: 0).format()
])
log.debug cmd
cmd
}
def alertHighLoad() {
log.debug “Executing ‘alertHighLoad’”
// TODO: handle ‘alertHighLoad’ command
}
def testConfiguration() {
log.debug "Executing ‘testConfiguration’"
def cmd = delayBetween([
zwave.configurationV1.configurationSet(parameterNumber: 3, size: 1, scaledConfigurationValue: 1).format(), // 1 enable Delta
zwave.configurationV1.configurationSet(parameterNumber: 4, size: 2, scaledConfigurationValue: 30).format(), // 20 Trigger if load changes by 20 watts
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 2, scaledConfigurationValue: 30).format(), // 20 Trigger if load changes by 20 watts
zwave.configurationV1.configurationSet(parameterNumber: 6, size: 2, scaledConfigurationValue: 30).format(), // 20 Trigger if load changes by 20 watts
zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: 5).format(), // 5% Load change
zwave.configurationV1.configurationSet(parameterNumber: 9, size: 1, scaledConfigurationValue: 5).format(), // 5% Load change
zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: 5).format() // 5% Load change
])
log.debug cmd
cmd
}
def WakeUp() {
log.debug "Executing WakeUp"
configure()
refresh()
disableDelta()
}
def appUpdate(lastNoonReading, startMonthReading) {
log.debug "Executing appUpdate"
state.lastNoonReading = lastNoonReading
state.startMonthReading = startMonthReading
sendEvent(name: “dataOne”, value: state.lastNoonReading, unit: “”)
sendEvent(name: “dataTwo”, value: state.startMonthReading, unit: “”)
}
def configure() {
log.debug "Configuring"
def cmd = delayBetween([
// zwave.configurationV1.configurationSet(parameterNumber: 1, size: 2, scaledConfigurationValue: 240).format(), // Set voltage to 240
zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 1).format(), // 1 combined power in kWh
zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 600).format(), // every 10 min
zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 14).format(), // 2 combined energy in W, 14 generates report for combined Amps, Power and volts
zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 20).format(), // every 20s
zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 1573640).format(), //0 no third report, (1573640 Amps combined and for each clsmp plus power for each clamp)
zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 20).format() // every 20s
])
log.debug cmd
cmd
}
@storageanarchy hey Barry, just realised, this is mostly your code :)