I use Mike’s dth that another member of community modified two include two buttons (#1one button is the dryer,#2 button is ‘washer’ or however you adapt the energy clamps) combined with webcore, it’s working solid.
Hardware You need: DSB09104 find it in link here:
/*
In-progress update of Mike Maxwell's HEM Laundry monitoring device for Aeon HEM V1. Includes customizations
from Ogiewon and MEarly.
SmartThings thread: https://community.smartthings.com/t/aeon-home-energy-meter-v1-read-clamps-separately/25480/100?u=danabw
Status:
1. Done: Ogiewon - Fix reported number of buttons so both are announced/available in SmartApps
2. Done: MEarly - Set Washer/Dryer On=pushed event; Washer/Dryer Off=held event. Allows notifications at start/end of cycle, & start/stop logging under Recent Activity.
2. Done: Danabw - All Preferences entries labeled
3. Need help: 1) Add reporting frequency setting to preferences (currently only managed in Configuration section, not available in preferences
4. Need help: 2) ID what KWhDelay and detailDelay settings control, and remove them from Preferences if user control not necessary
*/
metadata {
definition (name: "In-progress update of Maxwell's Aeon HEM V1 Laundry DTH", namespace: "MikeMaxwell", author: "Mike Maxwell")
{
capability "Configuration"
capability "Switch"
capability "Button"
capability "Energy Meter"
capability "Power Meter"
capability "Actuator"
capability "Holdable Button"
capability "Sensor"
capability "Refresh"
capability "Polling"
attribute "washerWatts", "string"
attribute "dryerWatts", "string"
attribute "washerState", "string"
attribute "dryerState", "string"
command "configure"
fingerprint deviceId: "0x2101", inClusters: " 0x70,0x31,0x72,0x86,0x32,0x80,0x85,0x60"
}
preferences {
input name: "c1Name", type: "text", title: "Clamp 1 device (e.g., Washer)", description: "", required: true
input name: "washerRW", type: "number", title: "Minimum watts device draws when running:", description: "", required: true
input name: "c2Name", type: "text", title: "Clamp 2 device (e.g., Dryer)", description: "", required: true
input name: "dryerRW", type: "number", title: "Minimum watts device draws when running:", description: "", required: true
input name: "voltageValue", type: "number", title: "Line voltage: 120 or 240", description: "", required: true
input name: "kWhCost", type: "number", title: "Cost per kWh", description: "", required: true
// Not sure what kWhDelay is or does. Not sure how to remove it from the Preferences screen - it displaye w/no label before I created this entry.
input name: "kWhDelay", type: "number", title: "kWh Delay", description: "", required: true
// Not sure what detailDelay is or does. Not sure how to remove it from the Preferences screen - it displaye w/no label before I created this entry.
input name: "detailDelay", type: "number", title: "Detail Delay", description: "", required: true
// Would like to add an entry in Preferences to set the HEM reporting frequency (it is included in the Configuration
// section at the end of the code, but I don't know how to do that. :)
}
//simulator {
//nothing currently in In-Progress
//}
// simulator metadata
simulator {
for (int i = 0; i <= 10000; i += 1000) {
status "power ${i} W-ZZ": new physicalgraph.zwave.Zwave().meterV1.meterReport(
scaledMeterValue: i, precision: 3, meterType: 33, scale: 2, size: 4).incomingMessage()
}
for (int i = 0; i <= 100; i += 10) {
status "energy ${i} kWh-ZZ": new physicalgraph.zwave.Zwave().meterV1.meterReport(
scaledMeterValue: i, precision: 3, meterType: 33, scale: 0, size: 4).incomingMessage()
}
// TODO: Add data feeds for Volts and Amps
}
}// end of metadata
def parse(String description) {
def result = null
def cmd = zwave.parse(description, [0x31: 1, 0x32: 1, 0x60: 3])
if (cmd) {
result = createEvent(zwaveEvent(cmd))
}
if (result) {
log.debug "Parse returned ${result?.descriptionText}"
return result
} else {
}
}
def zwaveEvent(physicalgraph.zwave.commands.meterv1.MeterReport cmd) {
def dispValue
def newValue
def formattedValue
//def timeString = new Date().format("h:mm a", location.timeZone)
if (cmd.meterType == 33) {
if (cmd.scale == 0) {
newValue = Math.round(cmd.scaledMeterValue * 100) / 100
if (newValue != state.energyValue) {
formattedValue = String.format("%5.2f", newValue)
dispValue = "2Ulices Total\n${formattedValue}\nkWh" // total kWh label
sendEvent(name: "energyDisp", value: dispValue as String, unit: "", descriptionText: "Display Energy: ${newValue} kWh", displayed: true)
state.energyValue = newValue
[name: "energy", value: newValue, unit: "kWh", descriptionText: "Ulices1 Total Energy: ${formattedValue} kWh"]
}
}
else if (cmd.scale==2) {
newValue = Math.round(cmd.scaledMeterValue*10)/10
formattedValue = String.format("%5.1f", newValue)
//newValue = Math.round(cmd.scaledMeterValue) // really not worth the hassle to show decimals for Watts
if (newValue != state.powerValue) {
dispValue = "Power \n"+newValue+"\nWatts" // Total watts label
sendEvent(name: "powerDisp", value: dispValue as String, unit: "", descriptionText: "Display Power: ${newValue} Watts", displayed: true)
state.powerValue = newValue
[name: "power", value: newValue, unit: "W", descriptionText: "TPower: ${formattedValue}W"]
}
}
}
}
tiles(scale: 1) {
multiAttributeTile(name:"laundryState", type: "generic", width: 6, height: 4, canChangeIcon: false){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
// attributeState "on", label:'Laundry Running', icon:"st.Appliances.appliances1", backgroundColor:"#53a7c0"
// attributeState "off", label:'Laundry Done', icon:"st.Appliances.appliances1", backgroundColor:"#ffffff"
attributeState "on", label:'', icon:"st.samsung.da.dryer_ic_dryer", backgroundColor:"#79b821"
attributeState "off", label:'', icon:"st.samsung.da.dryer_ic_dryer", backgroundColor:"#ffffff"
}
tileAttribute("device.switch", key: "SECONDARY_CONTROL") {
attributeState "on", label:'Laundry Running'
attributeState "off", label:'Laundry Done'
}
}
/*
valueTile("washerState", "device.washerState", width: 3, height: 2, canChangeIcon: true) {
state "default", label:'Washer\n${currentValue}'
}
valueTile("dryerState", "device.dryerState", width: 3, height: 2, canChangeIcon: true) {
state "default", label:'Dryer\n${currentValue}'
}
*/
standardTile("washerState", "device.washerState", width: 3, height: 3, canChangeIcon: true) {
state "off", label:'${name}', icon: "st.samsung.da.washer_ic_washer", backgroundColor:"#ffffff"
state "on", label:'${name}', icon: "st.samsung.da.washer_ic_washer", backgroundColor:"#79b821"
}
standardTile("dryerState", "device.dryerState", width: 3, height: 3, canChangeIcon: true) {
state "off", label:'${name}', icon: "st.samsung.da.dryer_ic_dryer", backgroundColor:"#ffffff"
state "on", label:'${name}', icon: "st.samsung.da.dryer_ic_dryer", backgroundColor:"#79b821"
}
valueTile("washer", "device.washerWatts", width: 3, height: 2, decoration: "flat") {
state("default", label:'Washer\n${currentValue} Watts', foregroundColor: "#000000")
}
valueTile("dryer", "device.dryerWatts", width: 3, height: 2, decoration: "flat") {
state("default", label:'Dryer\n${currentValue} Watts', foregroundColor: "#000000")
}
valueTile("power", "device.dryerWatts") {
state ( "default", label:'${currentValue}W', foregroundColor: "#000000", backgroundColor:"#79b821" )
}
standardTile("configure", "device.configure", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
main (["power"])
//main "laundryState"
details(["laundryState","washerState","dryerState","washer","dryer","configure", "powerDisp"])
}
def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
//log.info "mc3v cmd: ${cmd}"
if (cmd.commandClass == 50) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x30: 1, 0x31: 1])
if (encapsulatedCommand) {
def scale = encapsulatedCommand.scale
def value = encapsulatedCommand.scaledMeterValue
def source = cmd.sourceEndPoint
def str = ""
def name = ""
if (scale == 2 ){ //watts
str = "watts"
if (source == 1){
name = "washerWatts"
if (value >= settings.washerRW.toInteger()){
//washer is on
sendEvent(name: "washerState", value: "on", displayed: true)
//button event
if (!state.washerIsRunning)
sendEvent(name: "button", value: "pushed", data: [buttonNumber: 1], descriptionText: "Washer has started.", isStateChange: true)
state.washerIsRunning = true
} else {
//washer is off
if (state.washerIsRunning == true){
//button event
sendEvent(name: "button", value: "held", data: [buttonNumber: 1], descriptionText: "Washer has finished.", isStateChange: true)
}
sendEvent(name: "washerState", value: "off", displayed: false)
state.washerIsRunning = false
}
} else {
name = "dryerWatts"
if (value >= settings.dryerRW.toInteger()){
//dryer is on
sendEvent(name: "dryerState", value: "on", displayed: false)
//button event
if (!state.dryerIsRunning)
sendEvent(name: "button", value: "pushed", data: [buttonNumber: 2], descriptionText: "Dryer has started.", isStateChange: true)
state.dryerIsRunning = true
} else {
//dryer is off
if (state.dryerIsRunning == true){
//button event
sendEvent(name: "button", value: "held", data: [buttonNumber: 2], descriptionText: "Dryer has finished.", isStateChange: true)
}
sendEvent(name: "dryerState", value: "off", displayed: false)
state.dryerIsRunning = false
}
}
if (state.washerIsRunning || state.dryerIsRunning){
sendEvent(name: "switch", value: "on", descriptionText: "Washer and/or Dryer running...", displayed: true)
} else {
sendEvent(name: "switch", value: "off", displayed: false)
}
//log.debug "mc3v- name: ${name}, value: ${value}, unit: ${str}"
return [name: name, value: value.toInteger(), unit: str, displayed: false]
}
}
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in
//log.debug "Unhandled event ${cmd}"
[:]
}
def configure() {
log.debug "configure()"
initialize()
def cmd = delayBetween([
//zwave.configurationV1.configurationSet(parameterNumber: 100, size: 4, scaledConfigurationValue:1).format(), //reset if not 0
//zwave.configurationV1.configurationSet(parameterNumber: 110, size: 4, scaledConfigurationValue: 1).format(), //reset if not 0
zwave.configurationV1.configurationSet(parameterNumber: 1, size: 2, scaledConfigurationValue: 120).format(), // assumed voltage
zwave.configurationV1.configurationSet(parameterNumber: 3, size: 1, scaledConfigurationValue: 0).format(), // Disable (=0) selective reporting
zwave.configurationV1.configurationSet(parameterNumber: 9, size: 1, scaledConfigurationValue: 10).format(), // Or by 10% (L1)
zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: 10).format(), // Or by 10% (L2)
zwave.configurationV1.configurationSet(parameterNumber: 20, size: 1, scaledConfigurationValue: 1).format(), //usb = 1
zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 6912).format(),
zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 30).format() // Every 30 seconds
], 2000)
return cmd
}
def installed() {
configure()
}
def updated() {
configure()
}
def initialize() {
sendEvent(name: "numberOfButtons", value: 2)
}