I’m having a bit of an issue that I"m hoping someone can assist with.
I have a need to monitor 3 appliances. Stove, Washer, and Dryer.
My goal is to be able to send alerting via push / text to phones for both myself and my son for when the washer cycle is complete as well as the dryer cycle. However, in my household it’s not uncommon to run multiple loads of wash and be both washing and drying at the same time.
I also have a 20yr old son who doesn’t like to pay attention, so I want to monitor my stove / oven for power if it’s left on for more then say an hour to also send text / push notification to both myself and my son as the other week I found the stove on from him using it from 9pm to 4:30pm the next day when I went to use it. Not a happy camper to say the least.
To monitor the washer, I purchased an Aeotech Gen 6 Switch which has power monitoring capability, and a Aeotech HEM Gen 1 (dual clamp). I am using the DTH posted in this thread
with a slight modification (washer is now stove and dryer is dryer).
My dilema currently is that when I have the stove turned on and show it reporting watts, I then go and turn on the dryer, and as soon as it turns on and reports watts, Stove reports OFF and reports 0 watts even when the stove is still on and running. I need both clamps to still report independently of one another, even if they’re both on.
I was planning on using Dana’s webcore piston for the dryer, and create a simple piston that states if stove is on and drawing more then 50 watts for more then 60 minutes to send a text / push notification to myself and my son. My power draw for the washer is less then 50 watts after the washers stops so I want to find a piston that will work with the Aeotech Gen 6 switch to monitor power to tell if it’s running or not and notify via text / push when it’s done.
Any advice / code modification to this DTH I have listed below that I already slightly modified for my use? Any recommendation for the washer? I really don’t want to rely to a timer since we use a few different cycles that range from 60 to 2 hours and 20 minutes depending on what’s being washed.
Thanks! Code listed below.
/*
Dual Clamps: Update of Mike Maxwell’s HEM Laundry monitoring device for Aeon HEM V1. Includes customizations
from Oglewon and MEarly.
SmartThings thread: Aeon Home Energy Meter v1 -- Read Clamps Separately
Status:
- Done: Oglewon - Fix reported number of buttons so both are announced/available in SmartApps
- 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.
- Done: Danabw - All Preferences entries labeled
- Need help/later: 1) Add reporting frequency setting to preferences (currently only managed in Configuration section, not available in preferences
- Need help/later: 2) ID what KWhDelay and detailDelay settings control, and remove them from Preferences if user control not necessary
*/
metadata {
definition (name: “Dual Clamps: Update of Maxwell’s Aeon HEM V1 Laundry DTH”, namespace: “MikeMaxwell”, author: “Mike Maxwell”)
{
capability "Configuration"
capability "Switch"
capability “Button”
//capability "Energy Meter"
capability "Actuator"
capability "Holdable Button"
capability “Sensor”
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 {
}
tiles(scale: 2) {
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:'Appliance ON'
attributeState "off", label:'Applicance OFF'
}
}
/*
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(“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"
}
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"
}
valueTile("dryer", "device.dryerWatts", width: 3, height: 2, decoration: "flat") {
state("default", label:'Dryer\n${currentValue} Watts', foregroundColor: "#000000")
}
valueTile("washer", "device.washerWatts", width: 3, height: 2, decoration: "flat") {
state("default", label:'Stove\n${currentValue} Watts', foregroundColor: "#000000")
}
standardTile("configure", "device.configure", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
main "laundryState"
details(["laundryState","washerState","dryerState","washer","dryer","configure"])
}
}
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.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 = "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
}
} else {
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: "Stove is ON.", isStateChange: true)
state.washerIsRunning = true
} else {
//washer is off
if (state.washerIsRunning == true){
//button event
//
// Edited “Held” to send “Push” instead for clamp 1 (Washer clamp).
// Original sendEvent(name: “button”, value: “held”, data: [buttonNumber: 1], descriptionText: “Washer has finished.”, isStateChange: true)
sendEvent(name: “button”, value: “pushed”, data: [buttonNumber: 1], descriptionText: “Stove is OFF.”, isStateChange: true)
}
sendEvent(name: “washerState”, value: “off”, displayed: false)
state.washerIsRunning = false
}
}
if (state.washerIsRunning || state.dryerIsRunning){
sendEvent(name: “switch”, value: “on”, descriptionText: “Stove and/or Dryer is ON…”, 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)
}
,