Aeon Home Energy Meter ZW095-A

Help. I just received an Aeon Home Energy Meter (ZW095-A) and hubitat did not recognize
it. After adding it as a generic device, I then changed the Device Handler to the built-in Aeon Home Energy Meter. After doing so, I cannot see any data from the unit. What am I doing wrong?

Does the built-in handler not work, or am I doing something wrong.

My device info is as follows:

  • deviceType: 258
  • zwaveSecurePairingComplete: true
  • inClusters: 0x5E,0x86,0x72,0x32,0x56,0x60,0x70,0x59,0x85,0x7A,0x73,0x98
  • outClusters: 0x5A
  • deviceId: 95
  • manufacturer: 134

After changing the driver type, did you click the "Configure" button? This is needed to send the new driver parameters to the device.

1 Like

Also, some devices need a button press to put them in a mode for a few seconds where they will 'listen' for a configuration message to be sent to them. This is usually the case for battery powered devices, but always best to read the documentation that came with the device to make sure.

1 Like

Yes, I tried reset which does nothing at all and configure which results in the browser issuing a refresh and then displaying the two sections of databwith no data, and the status remsins as unknown (i think)

There is only one button on the unit, and that is repairing/restarting the device. Single tap put it into pairing mode. A long press initiates a factory reset.
I doubt that has to do anything with my issue. Aeon Labs does offer device Chandler‘s for SmartThings. If there was a guy on creating device handler’s I would simply convert it over, however every device handler I tried to convert with what little information is available I have been unsuccessful in with no documentation I have no idea why.
I think for my issue, I need somebody who actually has one of these units running to comment on how they did so. I do not really need elementary best practice assistance as I have many devices already configured and I’ve been doing home automation for several years now. This is my very first ever energy metering device. As such, it is quite possible there are steps that I am not familiar with. It could be, that I need to connect the clip meters to a powerline so that it starts collecting data before it will transmit anything. I do not know. What I do know, is that I will not install this in my power panel until after I have confirmed that it works. To test this, I have a set up in a test bed.

Inderstood. I have a Gen 1 Aeon HEM running with a special Hubitat Device Driver that was originally written by @mike.maxwell for SmartThings for monitoring a washer and dryer. While I am pretty sure it will not work for your newer HEM (which I believe is Gen5), it may give you some clues on things to change in the ST DTH when porting it over to Hubitat.

Here is my thread which has a link to my Github Repository. Again, this Driver is not for your device, but it may help with what changes are necessary.

Also, there is a WiKi thread describing some of the changes necessary when porting drivers and apps from ST to Hubitat. You've probably already seen it, but I thought it couldn't hurt to link it here just in case. Since it is a Wiki, please feel free to add to the first post with any additional findings you come across.

Finally, if all else fails, you should reach out to @mike.maxwell as he writes and maintains most of the Hubitat Drivers. He would know for sure which model of the 'Aeon Home Energy Meter' the built-in driver is designed to work with.

I have the first gen DSB09104-ZWUS, same as @ogiewon. I'm also using the @mike.maxwell 's Aeon V1 Laundry DTH that Dan ported to Hubitat. I sought out the DSB09104-ZWUS, because Dan mentioned that he did not think the v2 was compatible with the driver. But that's neither here, nor there if your plan for the device is whole house energy monitoring.

I apologize, it's been a while since I set mine up. I do recall not seeing any readings in the driver configuration page until I clicked configure, and the HEM had a value to read. So I believe you will need to install the clamps to get even a baseline value to appear.

These lot of devices are currently the unloved HE children... :grimacing:

Still no love. I tried pressing the link button, which resulted in an instant auto-link. I tried pressing the configure button, which does not appear to do anything. I launched the inspector, and tried configure again. When I click the Configure button I get an HTTP/302 redirect to GET which downloads the device edit page again. So, I don't know if the post (configure) event works or not. What I do know is that clicking configure has zero impact at the client web interface. I am not looking forward to trying to create a port of the official Aeon Labs DH for SmartThings.

@mike.maxwell, has this DH that is supplied with HE certified to work by anyone? When I pair the home energy meter, it gets added as a generic device, and I have to manually change the handler to the Aeon Home Energy Meter.

I started looking into this today since I have a Gen5 HEM coming soon and would let to get it working for laundry notifications.

I found a V1 driver as a starting point, and it looks like it will need to be updated to support secure inclusion mode, since the V5 will not accept configuration parameters unless it is in secure mode.

Got my Hem Gen5 last night and have HE talking to and configuring the device.

The meter reports are not exactly what I expected, so more work before this is ready to share.

(Also, if anybody knows why I might not be getting a "scaledMeterValue" field, but only a "meterValue", which looks like it's a 4-byte array, let me know. All the HEM driver examples I've seen use "scaledMeterValue" for the actual reading from the device, but I don't have this field included in the meter report that I get back from the device.)

I believe I've figured out the issue. For whatever reason, the Gen5 HEM returns a 4-byte array for meterValue, instead of "scaledMeterValue" that all the other drivers I've seen reference. Once you convert the byte array back to a double, the readings make sense.

I'll get my code cleaned up and post it here soon in case anybody else has this device and wants to get it running in Hubitat.

2 Likes

I'm migrating from ST to HE and my Gen5 is not working, I really want it working, any help will be appreciated, thanks

This is the DTH I used. It is the official one that Aeotech directa you to. I made the recommended changes to support HE, but no go.
https://aeotec.freshdesk.com/support/solutions/articles/6000122372-hem-gen5-smartthings-device-handler

Sounds like @andrewL has a working driver...

Right, but he is unsure about the values being read, and this is the actual ST supported code. The DTH for this is supposedly quite different than the one he used as his source. Supposedly. I did not look at the original, and now That I returned mine, I wont be buying another one until I know it works, and works fully.
Just hoped the link might help

So here's what I have that seems to be working for me. I don't have a way to fully verify that the values I'm getting are correct, other than the following evidence:

  1. When configured to report line voltage, I get a reading that matches what my network UPS displays
  2. When I measure the power draw for a lamp with a 60W bulb, I get 62W.
  3. I get readings from my washer and dryer that look reasonable.

This is my first time writing or modifying drivers for Hubitat, so I make no claims that this is correct-- only that it seems to be working for me, and I now get notifications reliably triggered when my washer and dryer finish their cycles.

If you end up using this, let me know how it goes.

/*
Custom Laundry monitor device for Aeon HEM Gen5 

  originally written by Mike Maxwell for SmartThings (HEM V1)
  
  modified by Dan Ogorchock to work with Hubitat (HEM V1)
  
  updated by Andrew Lewine to work with HEM Gen5 based on Gen5 SmartThings code by Dillon A. Miller

  2018-07-31  Andrew Lewine  Initial release

*/

metadata {
    definition (name: "Aeon HEM Gen5 Laundry DTH", namespace:    "AndrewLewine", author: "Andrew Lewine") 
    {
        capability "Configuration"
        capability "Switch"
        capability "Energy Meter"
        capability "Actuator"
        capability "Pushable Button"
        capability "Sensor"

        attribute "washerWatts", "string"
        attribute "dryerWatts", "string"
        attribute "washerState", "string"
        attribute "dryerState", "string"

        
        fingerprint deviceId: "0x5F", inClusters: "0x5E,0x86,0x72,0x32,0x56,0x60,0x70,0x59,0x85,0x7A,0x73,0x98", outClusters: " 0x5A"
    }

    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
        input name: "debounceDelay", type: "number", title: "Debounce delay time (seconds):", description: "", required: true
    }
}

def parse(String description){
    //log.trace "Parse received ${description}"
    def result = null
    if (description.startsWith("Err 106")) {
        state.sec = 0
        result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
            descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via Hubitat, you must remove it from your network and add it again.")
    } else if (description != "updated") {
        def cmd = zwave.parse(description, [0x32: 4, 0x56: 1, 0x59: 1, 0x5A: 1, 0x60: 4, 0x70: 1, 0x72: 2, 0x73: 1, 0x82: 1, 0x85: 2, 0x86: 2, 0x8E: 3, 0xEF: 1])
        if (cmd) {
            //log.debug "creating zwave event ${cmd}"
			result = zwaveEvent(cmd)
        }
        if (result) { 
        	//log.debug "Parse returned ${result?.descriptionText}"
        	return result
        }
    }else {
    }
}

def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
    def encapsulatedCommand = cmd.encapsulatedCommand([0x32: 4, 0x56: 1, 0x59: 1, 0x5A: 1, 0x60: 4, 0x70: 1, 0x72: 2, 0x73: 1, 0x82: 1, 0x85: 2, 0x86: 2, 0x8E: 3, 0xEF: 1])
    state.sec = 1
    //log.debug "encapsulated: ${encapsulatedCommand}"
    if (encapsulatedCommand) {
        zwaveEvent(encapsulatedCommand)
    } else {
        log.warn "Unable to extract encapsulated cmd from $cmd"
        createEvent(descriptionText: cmd.toString())
    }
}


def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
	response(configure())
}

def zwaveEvent(hubitat.zwave.commands.configurationv1.ConfigurationReport cmd) {
    log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}

def zwaveEvent(hubitat.zwave.commands.associationv2.AssociationReport cmd) {
    log.debug "---ASSOCIATION REPORT V2--- ${device.displayName} groupingIdentifier: ${cmd.groupingIdentifier}, maxNodesSupported: ${cmd.maxNodesSupported}, nodeId: ${cmd.nodeId}, reportsToFollow: ${cmd.reportsToFollow}"
}

def zwaveEvent(hubitat.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
    //log.info "mc3v cmd: ${cmd}"
    if (cmd.commandClass == 50) {
        //log.info "command class 50"
        def encapsulatedCommand = cmd.encapsulatedCommand([0x30: 1, 0x31: 1])
        if (encapsulatedCommand) {
            //log.info "encapuslated command ${encapsulatedCommand}"
            def scale = encapsulatedCommand.scale
            def byteValue = encapsulatedCommand.meterValue
            def source = cmd.sourceEndPoint
            def str = ""
            def name = ""
            def value = ((byteValue[0]*16777216) + (byteValue[1]*65536) + (byteValue[2]*256) + byteValue[3])/1000
            //log.debug "byte array ${byteValue} parsed value ${value}"
            if (scale == 2 ){ //watts
                str = "watts"
                if (source == 1){
                    name = "washerWatts"
                    if (value >= settings.washerRW.toInteger()){
                        if (state.washerIsRunning == false){
                            log.debug "unschedule(sendWasherDone) called"
                            unschedule(sendWasherDone)
                        }
                        state.washerIsRunning = true                       
                        //washer is on
                        sendEvent(name: "washerState", value: "on", displayed: true)
                        
                    } else {
                        //washer is off
                        if (state.washerIsRunning == true){
                            log.debug "runIn(${debounceDelay.toInteger()}, sendWasherDone) called"
                            runIn(debounceDelay.toInteger(), sendWasherDone)
                        }
                        state.washerIsRunning = false
                    }
                } else {
                    name = "dryerWatts"
                    if (value >= settings.dryerRW.toInteger()){
                        if (state.dryerIsRunning == false){
                            log.debug "unschedule(sendDryerDone) called"
                            unschedule(sendDryerDone)
                        }
                        state.dryerIsRunning = true
                        //dryer is on
                        sendEvent(name: "dryerState", value: "on", displayed: true)

                    } else {
                        //dryer is off
                        if (state.dryerIsRunning == true){
                            log.debug "runIn(${debounceDelay.toInteger()}, sendDryerDone) called"
                            runIn(debounceDelay.toInteger(), sendDryerDone)
                        }
                        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]
            } else {
                log.debug "unhandled config class 50 command: ${encapsulatedCommand}"
            }
        }
    }
}

def sendWasherDone(){
    log.debug "sendWasherDone() called"
    sendEvent(name: "washerState", value: "off", displayed: true)
    //button event
    sendEvent(name: "pushed", value: "1", descriptionText: "Washer has finished.", isStateChange: true)
}

def sendDryerDone(){
    log.debug "sendDryerDone() called"
    sendEvent(name: "dryerState", value: "off", displayed: true)  
    //button event
    sendEvent(name: "pushed", value: "2", descriptionText: "Dryer has finished.", isStateChange: true)
}

def zwaveEvent(hubitat.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.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationSet(parameterNumber: 3, size: 1, scaledConfigurationValue: 0)).format(),            // Disable (=0) selective reporting
        zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 768)).format(),       //13056
        zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 30)).format(),         // Every 15 seconds
        zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 0)).format(),       
        zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 7200)).format(),         // Every 15 seconds
        zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 0)).format(),       
        zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 7200)).format(),         // Every 15 seconds

        zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationGet(parameterNumber: 3)).format(),
		zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationGet(parameterNumber: 101)).format(),
		zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationGet(parameterNumber: 102)).format(),
		zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationGet(parameterNumber: 103)).format(),
		zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationGet(parameterNumber: 111)).format(),
		zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationGet(parameterNumber: 112)).format(),
		zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.configurationV1.configurationGet(parameterNumber: 113)).format()
    ],500)
    return cmd
}

def installed() {
    configure()
}

def updated() {
    configure()
}

def initialize() {
    sendEvent(name: "numberOfButtons", value: 2)
    state.sec = 0
    state.washerIsRunning = false
    state.dryerIsRunning = false
}

def push(btnNumber) {
    //log.debug btnNumber
    def desc = bthNumber==1?"Washer has finished":"Dryer has finished"
    sendEvent(name: "pushed", value: btnNumber, descriptionText: desc, isStateChange: true)
}
1 Like

I just looked through the code you linked, and yes, it is very different. But really the difference between the two devices comes down to the Gen5 requiring secure inclusion mode in order to send configuration commands.

When you include the HEM in your zwave network, you need to double click the button on the HEM, rather than single click. This will connect in secure mode. The driver modifications were done to support COMMAND_CLASS_SECURITY V1

I can see wattage, thanks, but if I create a tile on the dashboard using the energy template it doesn't show anything, my meter reads all the house, so I know when something out of normal is turned on, like the pool filter, I turn it off during the night time manually. Yes, I will upgrade it soon...

The device driver I posted is pretty use case specific—I’m monitoring washer and dryer wattages to detect when laundry cycles are done.

I’m not sure what the driver needs to expose to work with the energy meter dashboard tile.

1 Like