Here’s the situation… for months now I’ve been using a smartapp cobbled together that combined features from contributions by @sudarkoff, @bmmiller, and @byoung (included below), and using it with an Aeon DSC06106 and the device handler by @jpansarasa. It all worked great until we got a new washer. The old washer had a minimum 4W running wattage and would turn itself off shortly after finishing a cycle, at which point the power draw dropped to zero. Perfect! Our new washer has a minimum running wattage of 1W, BUT toggles down to zero watts briefly every 13 minutes! It then goes back to 1W (even when off) and repeats the 13min cycle until we start a new load or turn off the Aeon switch (which happens when mode switches to Night, using ‘Lighting Automation’).
With the new washer, setting ““Minimum running wattage”” to 1 results in the notifications being delayed 13 minutes. Thinking there might have been some slight decimal fraction of difference in power draw between washer off and the several times during a wash cycle where power dips to 1W, I tried setting "“Minimum running wattage” to 1.01W. This eliminated the 13 minute delay, but introduced a false alarm every time the cycle dipped to an indicated 1W.
I think what is needed is a settable timer test to see if the 1W state has been held at least x minutes. I think 1.5 to 2 minutes would be sufficient, and I realize that it will introduce a corresponding delay before notifying, but it’ll be better than 13 minutes or living with the false alarms! I understand the principle of introducing a runin time, but am not familiar enough with Groovy to come up with the syntax to do so or adding it as a preference. Any help, or does anyone have thoughts on a better way to accomplish this?
import groovy.time.*
definition(
name: "Laundry Monitor II", namespace: "HDFLucky", author: "Mr. Lucky",
description: "This application is a modification of the SmartThings 'Laundry Monitor' SmartApp. Instead of using a vibration sensor, it utilizes Power (wattage) sensing.",
category: "My Apps",
iconUrl: "https://dl.dropboxusercontent.com/u/52901840/laundry.png",
iconX2Url: "https://dl.dropboxusercontent.com/u/52901840/laundry@2x.png",
iconX3Url: "https://dl.dropboxusercontent.com/u/52901840/laundry@3x.png")
preferences {
section("Notify When Cycle Has Stopped"){
input "sensor1", "capability.powerMeter", multiple: false, required: true
}
section("Notifications") {
input "sendPushMessage", "bool", title: "Push notification(s)?"
input "phone1", "phone", title: "Send a text message (enter tel. #)?", required: false
input "phone2", "phone", title: "Also send a text message to:", required: false
input "speech", "capability.speechSynthesis", title:"Speak message via:", multiple: true, required: false
input "message", "text", title: "Notification message:", required: true
}
section("Flash or Turn On These Lights") {
input "switches", "capability.switch", title: "Which?", multiple: true, required: false
input "lightMode", "enum", options: ["Flash Lights", "Turn On Lights"], title: "Action?", required: false
}
section("Appliance Settings") {
input "minimumWattage", "decimal", title: "Minimum running wattage", defaultValue: 10, required: false
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
subscribe(sensor1, "power", powerInputHandler)
}
def powerInputHandler(evt) {
def latestPower = sensor1.currentValue("power")
log.trace "Power: ${latestPower}W"
if (!atomicState.isRunning && latestPower > minimumWattage) {
atomicState.isRunning = true
atomicState.startedAt = now()
atomicState.stoppedAt = null
log.trace "Cycle started."
} else if (atomicState.isRunning && latestPower < minimumWattage) {
atomicState.isRunning = false
atomicState.stoppedAt = now()
log.debug "startedAt: ${atomicState.startedAt}, stoppedAt: ${atomicState.stoppedAt}"
log.info message
if (phone1) {
sendSms phone1, message
} else {
sendPush message
}
if (phone2) {
sendSms phone2, message
}
if (speech) {
speechAlert(message)
}
if (switches) {
if (lightMode?.equals("Turn On Lights")) {
switches.on()
} else {
flashLights()
}
}
} else {
// Do Nothing, no change in either direction
}
}
private speechAlert(msg) {
speech.speak(msg)
}
private flashLights() {
def doFlash = true
def onFor = onFor ?: 1001
def offFor = offFor ?: 999
def numFlashes = numFlashes ?: 3
log.debug "LAST ACTIVATED IS: ${atomicState.lastActivated}"
if (atomicState.lastActivated) {
def elapsed = now() - atomicState.lastActivated
def sequenceTime = (numFlashes + 1) * (onFor + offFor)
doFlash = elapsed > sequenceTime
// log.debug "DO FLASH: $doFlash, ELAPSED: $elapsed, LAST ACTIVATED: ${atomicState.lastActivated}"
}
if (doFlash) {
log.debug "FLASHING $numFlashes times"
atomicState.lastActivated = now()
log.debug "LAST ACTIVATED SET TO: ${atomicState.lastActivated}"
def initialActionOn = switches.collect{it.currentSwitch != "on"}
def delay = 1L
numFlashes.times {
log.trace "Switch on after $delay msec"
switches.eachWithIndex {s, i ->
if (initialActionOn[i]) {
s.on(delay:delay)
} else {
s.off(delay:delay)
}
}
delay += onFor
log.trace "Switch off after $delay msec"
switches.eachWithIndex {s, i ->
if (initialActionOn[i]) {
s.off(delay: delay)
} else {
s.on(delay:delay)
}
}
delay += offFor
}
}
}