Z-wave Metering device and Power Reporting


#1

I’ve been working on a bit of code to create a master/slave plug arrangement. It works with the Smarthings SmartPlugs, as they report power use every time it changes. Unfortunately, they are only rated to 12 amps.

I’ve purchased a few of the Aeon-Labs-DSC06106-ZWUS-Z-Wave-Energy plugs rated to 15amps. They are recognized in the ST IDE as “Z-Wave metering Device”. The problem with these and my code, is that the power use doesn’t update like the ST plugs…I often have to hit “refresh” in the app to get them to report power use changes.

I was hoping some of you code gurus might be able to help. Ideally a device handler tweak would be ideal. I’m a complete code newbee, so at a loss. Any help would be very much appreciated :slight_smile: Cheers, Dennis.

/**

  • Shop Dust Management Control
  • Copyright 2016 Dennis Wood
  • Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except
  • in compliance with the License. You may obtain a copy of the License at:
  • http://www.apache.org/licenses/LICENSE-2.0
  • Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
  • on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
  • for the specific language governing permissions and limitations under the License.

*/
definition(
name: “Dust Collector Switch Control”,
namespace: “denniswood”,
author: “Dennis Wood”,
description: “App to Manage Dust Collector”,
category: “My Apps”,
iconUrl: “https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png”,
iconX2Url: “https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png”,
iconX3Url: “https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png”)

preferences {
section {
input(name: “meter”, type: “capability.powerMeter”, title: “When any of These SmartPlugs…”, required: true, multiple: true, description: null)
input(name: “threshold”, type: “number”, title: “Reports Power use Above…”, required: true, description: “in either watts or kw.”)
input(name: “switches”, type: “capability.switch”, title: “Turn On These Switches”, required: true, multiple: true, description: null)
input(name: “offdelay”, type: “number”, title: “Off Delay when Power Drops (seconds)”, required: true )
}
}

def installed() {
log.debug "Installed with settings: ${settings}"
unsubscribe()
initialize()
}

def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}

def initialize() {
subscribe(meter, “power”, meterhandler)
}

def meterhandler(evt) {
def meterValue = evt.value as double
def thresholdValue = threshold as int
log.debug "$evt.displayName is $evt.value"
if (meterValue > thresholdValue) {
switches.on()
}
else {
def delay = offdelay * 1000
log.debug "Delay is ${delay} ms"
switches.off(delay: delay)
}

}


#2

I did find these parameters that may solve the problem in another forum: http://forum.universal-devices.com/topic/13055-aeon-smart-switch-dsc06106-zwus/

I believe the 80(1) 1 HAIL on change tweak is what I need.

Parameter(bytes) Value Purpose
1(1) 1 Report Multisensor as Voltage
80(1) 1 HAIL on change
90(1) 1 Enable change reports
91(2) 50 Min W change for report
92(2) 5 Min % change in wattage for report
101(4) 4 Send Watt in group 1
102(4) 8 Send kWh in group 2
103(4) 2 Send Multi for group 3
111(4) 600 Time interval group 1
112(4) 600 Time interval group 2
113(4) 600 Time interval group 3

This is the code that Smarthings is using for “Zwave Metering Switch”

/**

  • Copyright 2015 SmartThings
  • Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except
  • in compliance with the License. You may obtain a copy of the License at:
  •  http://www.apache.org/licenses/LICENSE-2.0
    
  • Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
  • on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
  • for the specific language governing permissions and limitations under the License.

*/
metadata {
definition (name: “Z-Wave Metering Switch”, namespace: “smartthings”, author: “SmartThings”) {
capability "Energy Meter"
capability "Actuator"
capability "Switch"
capability "Power Meter"
capability "Polling"
capability "Refresh"
capability "Configuration"
capability “Sensor”

  command "reset"
  fingerprint inClusters: "0x25,0x32"

}

// simulator metadata
simulator {
status “on”: "command: 2003, payload: FF"
status “off”: “command: 2003, payload: 00”

  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()
  }
  for (int i = 0; i <= 100; i += 10) {
  	status "energy  ${i} kWh": new physicalgraph.zwave.Zwave().meterV1.meterReport(
  		scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage()
  }
  // reply messages
  reply "2001FF,delay 100,2502": "command: 2503, payload: FF"
  reply "200100,delay 100,2502": "command: 2503, payload: 00"

}

// tile definitions
tiles {
standardTile(“switch”, “device.switch”, width: 2, height: 2, canChangeIcon: true) {
state “on”, label: ‘${name}’, action: “switch.off”, icon: “st.switches.switch.on”, backgroundColor: "#79b821"
state “off”, label: ‘${name}’, action: “switch.on”, icon: “st.switches.switch.off”, backgroundColor: “#ffffff
}
valueTile(“power”, “device.power”) {
state “default”, label:’${currentValue} W’
}
valueTile(“energy”, “device.energy”) {
state “default”, label:’${currentValue} kWh’
}
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”
}

  main(["switch","power","energy"])
  details(["switch","power","energy","refresh","reset"])

}
}

def updated() {
try {
if (!state.MSR) {
response(zwave.manufacturerSpecificV2.manufacturerSpecificGet().format())
}
} catch (e) { log.debug e }
}

def parse(String description) {
def result = null
if(description == “updated”) return
def cmd = zwave.parse(description, [0x20: 1, 0x32: 1, 0x72: 2])
if (cmd) {
result = zwaveEvent(cmd)
}
return result
}

def zwaveEvent(physicalgraph.zwave.commands.meterv1.MeterReport cmd) {
if (cmd.scale == 0) {
createEvent(name: “energy”, value: cmd.scaledMeterValue, unit: “kWh”)
} else if (cmd.scale == 1) {
createEvent(name: “energy”, value: cmd.scaledMeterValue, unit: “kVAh”)
} else if (cmd.scale == 2) {
createEvent(name: “power”, value: Math.round(cmd.scaledMeterValue), unit: “W”)
}
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
def evt = createEvent(name: “switch”, value: cmd.value ? “on” : “off”, type: “physical”)
if (evt.isStateChange) {
[evt, response([“delay 3000”, zwave.meterV2.meterGet(scale: 2).format()])]
} else {
evt
}
}

def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
createEvent(name: “switch”, value: cmd.value ? “on” : “off”, type: “digital”)
}

def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def result = []

def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
log.debug "msr: $msr"
updateDataValue(“MSR”, msr)

// retypeBasedOnMSR()

result << createEvent(descriptionText: “$device.displayName MSR: $msr”, isStateChange: false)

if (msr.startsWith(“0086”) && !state.aeonconfig) { // Aeon Labs meter
state.aeonconfig = 1
result << response(delayBetween([
zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 4).format(), // report power in watts
zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 300).format(), // every 5 min
zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 8).format(), // report energy in kWh
zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 300).format(), // every 5 min
zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 0).format(), // no third report
//zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 300).format(), // every 5 min
zwave.meterV2.meterGet(scale: 0).format(),
zwave.meterV2.meterGet(scale: 2).format(),
]))
} else {
result << response(delayBetween([
zwave.meterV2.meterGet(scale: 0).format(),
zwave.meterV2.meterGet(scale: 2).format(),
]))
}

result
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
log.debug “$device.displayName: Unhandled: $cmd”
[:]
}

def on() {
[
zwave.basicV1.basicSet(value: 0xFF).format(),
zwave.switchBinaryV1.switchBinaryGet().format(),
“delay 3000”,
zwave.meterV2.meterGet(scale: 2).format()
]
}

def off() {
[
zwave.basicV1.basicSet(value: 0x00).format(),
zwave.switchBinaryV1.switchBinaryGet().format(),
“delay 3000”,
zwave.meterV2.meterGet(scale: 2).format()
]
}

def poll() {
delayBetween([
zwave.switchBinaryV1.switchBinaryGet().format(),
zwave.meterV2.meterGet(scale: 0).format(),
zwave.meterV2.meterGet(scale: 2).format()
])
}

def refresh() {
delayBetween([
zwave.switchBinaryV1.switchBinaryGet().format(),
zwave.meterV2.meterGet(scale: 0).format(),
zwave.meterV2.meterGet(scale: 2).format()
])
}

def configure() {
zwave.manufacturerSpecificV2.manufacturerSpecificGet().format()
}

def reset() {
return [
zwave.meterV2.meterReset().format(),
zwave.meterV2.meterGet(scale: 0).format()
]
}


(Jason "The Enabler" as deemed so by @Smart) #3

Follow this link. The code posted in post #2 is what I use. I can configure reporting time and a couple of other things.

I use one of mine as a power sensor. Setting the reporting interval to zero makes it report every minute and it reports with every poweer change.

It works great. Might save you some time.


#4

Jason, thanks so much for that post. I was on the verge of just giving up after trying a bunch of alternates last night…too much pain, given I can just use a manual relay, If I can get this working with the DSC06106, this gives a lot of freedom in terms of how tools are plugged in. If I use the manual method, I need to run all tools from the manual vacuum switch…so a mess of extension cords.

If I can get this to work, it’s just a zwave receptacle for the vacuum system, and 1 metering switch per tool circuit, anywhere in the shop. Much cleaner.


(Jason "The Enabler" as deemed so by @Smart) #5

It reads the power and you can use that to turn things on and off. But it diesr not turn on automatically. But, you set up a rule to do it. I haven’t tried that.


#6

The most important thing is that it reports power changes quickly. My own code was throwing a HAIL exception in the logs, and the 3 or 4 other variations on other device handlers did not result in rapid power updates.

If I turn the switch completely on/off it does report the change quickly…however when an attached device is turned off, the change has yet to be reported quickly.

The ST smart plugs on the other hand report pretty much instantly when there’s a .1V change…just can’t use them with most power tools :frowning:


(Jason "The Enabler" as deemed so by @Smart) #7

My dsc06106 reports instant changes when I set the report interval to zero. I like that I can disable the on/off so it can’t be switched in the app.

I have one for my wife’s beat pump. She did down in her ticket, turns on the pump at the pump. The device immediately reports it and ST starts running the rules we have built for her. When she is done it senses the pump is off, and runs more stuff.

That thing is great.

I just bought six if the iris zone switches with the zwave repeater. The stock code sucks and I’m tweaking some code to do what I want.

It reports quick but doesn’t report correct amounts like I want.

edit

Also, it shows up add an energy meter, but will not report that way. You have to use it as a power meter.


#8

I’ll give this another crack tonight. I have not tried setting report intervals to zero on any of the handler code so far. I’ll post back once I’ve tried out the linked handler. Thanks so much for your input :slight_smile:


#9

Jason, that version still gave me power updates every 60 seconds, even with reporting interval set to zero.

This one works perfectly, from the same thread…and shows watts, max/min and kwh. It also updates wattage instead of the on/off icon right in the app “Things” list, so you don’t need to access the device at all to monitor it. There is in option in the device config (GUI) to choose reporting intervals(0), or updates on changes (1). I was trying to the do the same with no success in code…this works!

https://raw.githubusercontent.com/constjs/jcdevhandlers/master/devicetypes/jscgs350/my-aeon-metering-switch.src/my-aeon-metering-switch.groovy

Thanks for pointing me in the right direction…I must have tried 5-6 device handlers as well as my own code tweaks. This is the first one to provide power change updates within a second or two of actual.


(Jason "The Enabler" as deemed so by @Smart) #10

Awesome! I’m going to check this out. Thanks for letting me know!