Timely Mode Change Help


(Jam Dawz) #1

I’ve modified the “Rise and Shine” smart app to change modes during a specific time frame if motion is detected at a specified sensor. Here’s the problem: it will only fire once. I install the app, set the preferences and it works exactly as I want. But, once it fires the first time, it won’t do it again. I can change the mode back and activate the motion sensor, but the mode remains the same. I really don’t know what I’m doing, so I may have goofed the code. Please help! Here’s the code:

`
/**
preferences {
section(“When there’s motion on this sensor”) {
input “motionSensors”, “capability.motionSensor”, multiple: false
}
section(“During this time window”) {
input “timeOfDay”, “time”, title: "Start Time?"
input “endTime”, “time”, title: “End Time?”, required: true
}
section(“Change to this mode”) {
input “newMode”, “mode”, title: “Mode?”
}
section(“And (optionally) turn on these appliances”) {
input “switches”, “capability.switch”, multiple: true, required: false
}
section( “Notifications” ) {
input “sendPushMessage”, “enum”, title: “Send a push notification?”, metadata:[values:[“Yes”,“No”]], required:false
input “phoneNumber”, “phone”, title: “Send a Text Message?”, required: false
}
}

def installed() {
log.debug "installed, current mode = ${location.mode}, state.actionTakenOn = ${state.actionTakenOn}"
initialize()
}

def updated() {
log.debug "updated, current mode = ${location.mode}, state.actionTakenOn = ${state.actionTakenOn}"
unsubscribe()
initialize()
}

def initialize() {
log.trace "timeOfDay: $timeOfDay, endTime: $endTime"
subscribe(motionSensors, “motion.active”, motionActiveHandler)
subscribe(location, modeChangeHandler)
if (state.modeStartTime == null) {
state.modeStartTime = 0
}
}

def modeChangeHandler(evt) {
state.modeStartTime = now()
}

def motionActiveHandler(evt)
{
// for backward compatibility
if (state.modeStartTime == null) {
subscribe(location, modeChangeHandler)
state.modeStartTime = 0
}

def t0 = now()
def modeStartTime = new Date(state.modeStartTime)
def timeZone = location.timeZone ?: timeZone(timeOfDay)
def startTime = timeTodayAfter(modeStartTime, timeOfDay, timeZone)
def endTime = timeTodayAfter(startTime, endTime ?: "24:00", timeZone)
log.debug "startTime: $startTime, endTime: $endTime, t0: ${new Date(t0)}, modeStartTime: ${modeStartTime},  actionTakenOn: $state.actionTakenOn, currentMode: $location.mode, newMode: $newMode "

if (t0 >= startTime.time && t0 <= endTime.time && location.mode != newMode) {
	def message = "SmartThings changed the mode to '$newMode'"
	send(message)
	setLocationMode(newMode)
	log.debug message

	def dateString = new Date().format("yyyy-MM-dd")
	log.debug "last turned on switches on ${state.actionTakenOn}, today is ${dateString}"
	if (state.actionTakenOn != dateString) {
		log.debug "turning on switches"
		state.actionTakenOn = dateString
		switches?.on()
	}

}
else {
	log.debug "not in time window, or mode is already set, currentMode = ${location.mode}, newMode = $newMode"
}

}

private send(msg) {
if ( sendPushMessage != “No” ) {
log.debug( “sending push message” )
sendPush( msg )
}

if ( phoneNumber ) {
	log.debug( "sending text message" )
	sendSms( phoneNumber, msg )
}

log.debug msg

}
*/


(Atticusalien) #2

Because of this code:

def dateString = new Date().format(“yyyy-MM-dd”)
log.debug “last turned on switches on ${state.actionTakenOn}, today is ${dateString}”
if (state.actionTakenOn != dateString) {
log.debug “turning on switches”
state.actionTakenOn = dateString
switches?.on()
}

The switches will only turn on once per day, even if the mode changes back during the time frame.

Change it to this to not care about happening more than once per day:

log.debug “turning on switches”
switches?.on()

(Jam Dawz) #3

I guess I’m not getting this right. I changed to code to:

    def dateString = new Date().format("yyyy-MM-dd")
    	log.debug "last turned on switches on ${state.actionTakenOn}, today is ${dateString}"
    if (state.actionTakenOn != dateString) {
    	log.debug "turning on switches"
        switches?.on()
	}

But it hasn’t changed anything! What am I missing?

Thank you for helping this ignorant fool!!


(Jam Dawz) #4

@atticusalien

Did I change the code correctly or did I miss something?


(Atticusalien) #5

You’ll need to remove ALL of the lines I mentioned and replace with just these two lines:

log.debug “turning on switches”
switches?.on()

Here is what the code is doing and why you need to remove all of those lines:

//Define a string that contains today's date.
def dateString = new Date().format(“yyyy-MM-dd”)

//The last time the switches were turned on is stored in the state.actionTakenOn variable.
//The below line logs this along with the today's date
log.debug “last turned on switches on ${state.actionTakenOn}, today is ${dateString}”

//If the last time the switches were turned on (what is stored in the state.actionTakenOn variable)
//does not equal today's date (what is stored in the dateString variable) then execute the code within the brackets
//otherwise, do nothing. This is why the switches are getting turned on only once. If we remove this check, then the
//switches will be turned on even if they have already been turned on today.
if (state.actionTakenOn != dateString) {

//Log a message
log.debug “turning on switches”

//Store the current date in the state.actionTakenOn variable
state.actionTakenOn = dateString

//Turn the switches on
switches?.on()
}

(Jam Dawz) #6

I tried that, too, but it gave me an error when I tried to save the changes. I will test it again. Thanks for setting me straight!!


(Jam Dawz) #7

@atticusalien

Okay, I changed the code to this:

	{
    	log.debug "turning on switches"
        switches?.on()

Tried to save the change and got this:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: script13838813691591131040937.groovy: 72: Ambiguous expression could be a parameterless closure expression, an isolated open code block, or it may continue a previous statement; solution: Add an explicit parameter list, e.g. {it -> ...}, or force it to be treated as an open block by giving it a label, e.g. L:{...}, and also either remove the previous newline, or add an explicit semicolon ';' @ line 72, column 1. { ^

1 error

Sorry, but it’s not working.


(Jam Dawz) #8

@atticusalien

Okay, I removed the { and } from the code and saved the changes. I installed the app and tested the scenario, but it’s not working. The app is set to change the mode to Night and turn on a switch when there is movement in BEDROOM between 07:36 PM and 10:36 PM. After first install, movement in BEDROOM switched the mode to Night and turned on the switch. I allowed the Motion Sensor to send the “No motion detected” status update then activated the Motion Sensor, but nothing happened. Here are the logs for the app:

9:41:24 PM: debug not in time window, or mode is already set, currentMode = Home, newMode = Night

9:41:24 PM: debug startTime: Sat Nov 09 01:36:00 UTC 2013, endTime: Sat Nov 09 04:36:00 UTC 2013, t0: Fri Nov 08 03:41:24 UTC 2013, modeStartTime: Fri Nov 08 03:39:34 UTC 2013, actionTakenOn: null, currentMode: Home, newMode: Night

9:38:00 PM: debug turning on switches

9:38:00 PM: debug SmartThings changed the mode to ‘Night’

9:38:00 PM: debug SmartThings changed the mode to ‘Night’

9:38:00 PM: debug startTime: Fri Nov 08 01:36:00 UTC 2013, endTime: Fri Nov 08 04:36:00 UTC 2013, t0: Fri Nov 08 03:38:00 UTC 2013, modeStartTime: Thu Jan 01 00:00:00 UTC 1970, actionTakenOn: null, currentMode: Home, newMode: Night

9:36:48 PM: trace HOME was provided…creating subscription

9:36:48 PM: trace motion.active from BEDROOM was provided with motionActiveHandler…creating subscription

9:36:48 PM: trace timeOfDay: 2013-11-07T19:36:23.000-0600, endTime: 2013-11-07T22:36:23.000-0600
bc7cc963-1616-423d-8377-613d1e857849 9:36:48 PM: debug installed, current mode = Home, state.actionTakenOn = nul

What else can I try?


(Atticusalien) #9

Hmmm… The log says its not in the time window for some reason?

Try changing ALL of this:

// for backward compatibility
if (state.modeStartTime == null) {
subscribe(location, modeChangeHandler)
state.modeStartTime = 0
}

def t0 = now()
def modeStartTime = new Date(state.modeStartTime)
def timeZone = location.timeZone ?: timeZone(timeOfDay)
def startTime = timeTodayAfter(modeStartTime, timeOfDay, timeZone)
def endTime = timeTodayAfter(startTime, endTime ?: “24:00″, timeZone)
log.debug “startTime: $startTime, endTime: $endTime, t0: ${new Date(t0)}, modeStartTime: ${modeStartTime}, actionTakenOn: $state.actionTakenOn, currentMode: $location.mode, newMode: $newMode ”

if (t0 >= startTime.time && t0 <= endTime.time && location.mode != newMode) {

To this:

def t0 = now()
def timeZone = location.timeZone ?: timeZone(timeOfDay)
def start = timeToday(timeOfDay, timeZone)
def end = timeToday(endTime, timeZone)
log.debug “startTime: $start, endTime: $end, t0: ${new Date(t0)}, currentMode: $location.mode, newMode: $newMode ”

if (t0 >= start.time && t0 <= end.time && location.mode != newMode) {

(Jam Dawz) #10

@atticusalien

EXCELLENT!!!

I made the changes to the code and the test worked like a champ exactly the way it should!

I believe you have done it!! Thank you very much!