Aeon Home Energy Meter v1 -- Read Clamps Separately


(Dana ) #162

I recently changed from Core to WebCore, and as a part of that had to recreate my pistons for Washer and Dryer notification. They are below for any webcore users who’d like to look at/use/take and modify them in their dual clamp setup. I’m using a modified version of Mike’s (@Mike_Maxwell) great HEM DTH that he and @MEarly and @ogiewon helped me adjust.

Washer:
Wattage is all over the place crazy, and I found that I could not find a reliable way to manage “done” via watts monitoring or washer state, so I went w/a simple timer, as 90% of our loads are the same cycle, takes about 50 minutes.

Dryer:
Nice and reliable, so I could use a wattage setting to determine “done” and then message. If only my washer was as friendly… :slight_smile:

Washer Piston - timer, starts w/Push Some slight funkiness in what I’ve done here - I’ve edited the DTH to replace the “Held” signal from the first clamp with a “Push” since I’m not using “Held” and don’t need/want it for the piston. There are more elegant way of handling this, but elegant ain’t me. :slight_smile: washerPiston variable is created w/initial value set to ‘nothing selected’ but should be initialized to false.

Washer piston - push to timer

Dryer Piston - Starts w/Push, ends w/Held This is simple, starts w/Push, ends w/Held. (Ignore the “lowWattsCount” variable - that was from an early draft and I’m no longer using that variable and I forgot to remove it from the piston define section.)

Dryer Piston - Push then Held

DTH (Based on the one that @Mike_Maxwell created)

/*
Dual Clamps: Update of Mike Maxwell's HEM Laundry monitoring device for Aeon HEM V1. Includes customizations 
from Oglewon and MEarly. 
SmartThings thread: https://community.smartthings.com/t/aeon-home-energy-meter-v1-read-clamps-separately/25480/100?u=danabw
Status: 
1. Done: Oglewon - 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/later: 1) Add reporting frequency setting to preferences (currently only managed in Configuration section, not available in preferences
4. 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:'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")
        }
       
		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 = "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
// 
// 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: "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)
}

220v Dryer suggestions. Using Aeotec HEM?
#163

@danabw did some great work with his WebCORE pistons. I’m using his Dryer piston and that works great. But like him, my washing machine is much more finicky than my dryer, but there are some patterns that I could take advantage of, namely the machine will occasionally pause and the power will dip, but not for long. Meanwhile the resting wattage would often spike high enough to make the monitor think the washer was running for a brief moment.

I think I figured out how to effectively ignore those blips, dips and spikes and still notify me at the end of the load.

Wanted to share this code to see how it works for you. You’ll notice a lot of code referring to lights, this is great if you want it to notify you using smart lights, while turning off the lights that were off and keeping the lights you had on, on. Feel free to delete it but be careful.

If you use it and run into problems, would be good to know.


(Dana ) #164

Very nice work on your piston, @Fe2_O3. Fun to put these things together.

To be frank, I’m probably not going to try your piston just because I spent so much time pouring through my device log looking at washer wattages that I just can’t bear to go back into it to see if I could find the values that might work w/your piston. The time I’m using in my washer piston works perfectly for us, so I’m going to leave well enough along for once. :slight_smile:

I have updated my pistons, and you might enjoy including a looping reminder I added, as I found that one notification was never enough w/my family. :slight_smile:

I’m using a new service/smartapp/DTH combo created by @ghesp to do my announcing via GH - if you have a way to run node.js on an existing computer (or get a Pi Raspberry for <$50) you could integrate voice announcements on all the GH in your home. :slight_smile: Or just remove those lines from the piston.

If you want to look at it see below. It is my absolute favorite ST integration to date…getting voice announcements on all my GH (and auto pause/resume music if it’s playing) is both very useful/effective, and absolutely cool. :smiley:

Anyway, here are my current pistons, Washer monitor/looping reminder and Dryer monitor/looping reminder. I use global variable so I can hand off between the monitor and looping reminders. I can’t remember who had posted their own looping reminder pistons that led me integrate a version of that myself, so unfortunately can’t give them credit.

Washer Monitor

Washer Looping Reminder

Dryer Monitor

Dryer looping reminder


(llcanada) #165

@Danabw was looking at your piston you and @Fe2_O3 have done a great job on these pistons? I do have a question are you using a contact sensor on your washing machine and dryer door? Thanks and good work.


(Dana ) #166

That would be a “Yep” on the contact sensors. :slight_smile:

Used Visonic, my favorite low-profile contact sensor. Aside from indicating when the load is done, I use the “contact sensor closed less than xx minutes” conditions in the piston to avoid responding to spurious energy readings that might cause a false positive on a load being started or ended.

These pistons are heavily leveraged from other (smarter) webCore users work - I don’t want to give the impression I created them on my own or anything. I have customized them to meet my needs and to accommodate the (often annoying) behaviors of my own washer and dryer. :slight_smile:


#167

I use the same thing as a reminder on my laundry… Door sensors on the washer and on the dryer to keep triggering a reminder text every hour after a load is done, until the door has been opened.


#168

Here’s my updated version, building off @Azat I was just messing around trying to get it to work better with my webCoRE pistons, and seems to be doing pretty well now (I can actually get the watts / kWh reporting to work a numeric values without converting them in the piston!)


(Tony B.) #169

@Smartphi

Either your sensor is really good or, maybe not updating dryer when it’s at exactly 6.7 Watts.

Total drops to 0 but dryer stays at 6.7.

Can I fix something in the DTH to say ‘total is 0, must be 0 everywhere’?


(Jason) #170

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:

  1. Done: Oglewon - 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.
  3. Done: Danabw - All Preferences entries labeled
  4. Need help/later: 1) Add reporting frequency setting to preferences (currently only managed in Configuration section, not available in preferences
  5. 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. :slight_smile:

}

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)
}

,


(Dan) #171

I am still using a very old version of Mike Maxwell’s DTH for the Aeon HEM v1 with no issues. I my case, I have a very well behaved washer and dryer, in that they both always stay above a certain wattage when running, and always drop below a simple threshold when the cycle completes. It looks like the DTH you’re using may be much more sophisticated these days, which may be leading to the confusion.

Here is the version I have been using for years with zero issues. Make sure you click “Configure” after switching to this DTH as it will send a special configuration to the Aeon HEM v1 to send independent wattages for each clamp. (Perhaps this is all you need to do to fix your issue???)

/*
Custom Laundry monitor device for Aeon HEM V1 

*/

metadata {
	definition (name: "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: "washerRW", type: "number", title: "Washer running watts:", description: "", required: true
        input name: "dryerRW", type: "number", title: "Dryer running watts:", description: "", required: true
    }
	
    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:'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")
        }
       
		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 = "washerWatts"
                    if (value >= settings.washerRW.toInteger()){
                    	//washer is on
                        sendEvent(name: "washerState", value: "on", displayed: true)
                        state.washerIsRunning = true
                    } else {
                    	//washer is off
                        if (state.washerIsRunning == true){
                        	//button event
                            sendEvent(name: "button", value: "pushed", data: [buttonNumber: 1], descriptionText: "Washer has finished.", isStateChange: true)
                        }
                        sendEvent(name: "washerState", value: "off", displayed: true)
                        state.washerIsRunning = false
                    }
                } else {
                	name = "dryerWatts"
                    if (value >= settings.dryerRW.toInteger()){
                    	//dryer is on
                        sendEvent(name: "dryerState", value: "on", displayed: true)
                        state.dryerIsRunning = true
                    } else {
                    	//dryer is off
                        if (state.dryerIsRunning == true){
                        	//button event
                            sendEvent(name: "button", value: "pushed", data: [buttonNumber: 2], descriptionText: "Dryer has finished.", isStateChange: true)
                        }
                        sendEvent(name: "dryerState", value: "off", displayed: true)
                        state.dryerIsRunning = false
                    }
                }
                if (state.washerIsRunning || state.dryerIsRunning){
                	sendEvent(name: "switch", value: "on", descriptionText: "Laundry has started...", 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)
}

No sensor readings from Aeon HEM v1
Look for advice for sump pump project
(Jason) #172

Will this show as separate clamps from the things page? I’m having trouble figuring out how to tell webCoRE to use a specific clamp to monitor for energy usage with the HEM v1.


(Dan) #173

I believe you can have webCoRE read the values of custom attributes.


(Jason) #174

Thanks I’m looking into that now. With the DTH you have listed can you run both washer and dryer at the same time and get a reading off both?


(Dan) #175

Yes. You will have to select the device from the Things page to see the full device with both readings.


(Jason) #176

Ok I’ll give it a shot as soon as I can get into my app… grrr


(Tony B.) #177

Here’s my try at it.

Icon’s like MikeMaxwell and Energy/Power reading for stuff like Grafana.

There is a lot of code puke in there since it’s my first. Anyone want to clean it up, go right ahead.


#178

Help! I have a HEM V.1 and was digging (for a few hours) through multiple threads / posts on getting a DTH to get it to function the way I want and have not found a truly clear and cohesive set of answers so I thought I would post it here and hope someone else has solved this already (or has enough knowledge to solve it). Hoping that someone will provide a complete answer / solution for me. This is what I want to do… Using a single HEM V1 I want to use one leg (clamp) to monitor “power on” status to my stand alone freezer (via a clamp on a easy access wire going to my freezers internal power on lamp). I want to use the other leg (clamp) to monitor the voltage going through the units wiring (easily accessible under the freezer) to the built in “temp alert”. and to complete the set up I want it to alert me via text and push when EITHER power is off to the freezer on lamp (no voltage being consumed) OR the temperature alarm goes off (voltage goes to the alarm). After a freezer failure with a few years back I have tried to solve this several times the obvious way (with battery powered temp sensors) but a combination of high battery wear-out factor and bad radio reception inside the freezer has me repeatedly abandoning the project. Till today when I thought of this other way to “skin a cat” as they say. I have looked specifically for “HEM Freezer monitor” but it seems it is a rare (dare I say virgin?) concept on SThings Community. It seems that most everyone is using the HEM for washer / dryer monitoring. Originally I thought I was going to use 2 separate HEMs to achieve my stated goal till I faintly remembered reading about the concept of splitting the legs of the HEM. For device types / alert delivery, I was probably just going to use a multi clamp supporting laundry type smart DTH and a laundry type smart app. Here are a few SPECIFIC questions that I am hoping for some help with.

  1. Is it possible to use a hem V1 as I am proposing? So that SThings would send one text/alarm for having no voltage coming from clamp 1(freezer “power on” lamp) for a (user determined) amount of time and a different alert for Clamp 2 (Temp Alert) reading any voltage above zero for any length of time?
  2. Is there any “freezer monitor” specific DTH / smartapps that anyone knows of and if so what are they?
  3. What (specific) DTH is best for this task?
  4. What (specific) Smart App is best for this task?
    For those of you who have ever experienced broken freezer with meat in it it’s not a fun thing! Any help in creating this insurance against a lot of spoiled meat, etc would be greatly appreciated. PS if you are reading this and have not ever considered the above project, then I respectfully and strongly urge you to imagine your whole freezer ROTTEN (and it being easily avoidable) and then use that for motivation to consider creating a solution for yourself. Help!

#179

For what you’re wanting to do, the HEM and associated apps to be developed/configured, would be a PITA and overkill.

I’ve been in your shoes, and solved my problem this way: (I’ve been doing this for a few years with ST, so I know it works)

I have a frig/freezer combo in the garage, and I use 2 Iris open/close sensors and a wall outlet (like an Aeon or Zooz metering switch). I also do this for my kitchen and bar frig/freezers.

1 Iris sensor is inside the frig so I can monitor open/close state and temperature.

1 Iris sensor is inside the freezer so I can monitor open/close state and temperature.

Yes, these sensors work great inside frig/freezers, and you can specify temperature offsets if you so desire.

I use SHM with a custom rule to monitor if the temperature of the frig/freezer goes above a particular value. If/When it does, I get a push and text notification. Pretty darn simple, and super easy to set up.

The Aeon or Zooz device is there so I can watch/monitor power consumption, but I also use the Energy Alerts SmartApp (found in the Marketplace under Energy Management) to notify me if power drops below a desired value, like 1 watt. You’ll have to monitor for a while to see what’s a good low value to look for.

Between all the devices and SmartApps I’m using, I’m confident of catching something before it gets out of control and I lose all my frozen food; which did happen this past summer.

I got an alert that my garage freezer was warming up, and saw that my metering switch wasn’t reading out watts like it should with the compressor running for the freezer. That helped me discover I had a bad main control board, so off to Amazon I went, and I moved the frozen food to the other freezers until the board came in and everything was good again.