[OBSOLETE] Vacation Light Director

It’s not authored by “SmartThings” so it doesn’t show up in the templates. I had to go to the source code and copy/paste it into a new application, but then (see earlier post) it wouldn’t let me use it :frowning:

Hi, without looking back at the code (it’s not to hand) I think this should go just before the } at the end of the Initialize() routine.

Ran fine for me over 5 days - I suspect your hub reset itself. There’s still the bug whereby if the hub is already in one of the active modes for the application, it won’t start itself (see my code suggestion), so if the hub rebooted back into the mode it was already running in, it would start the app, which would wait for the trigger of going into that mode - which it wouldn’t get as it was already in the mode. Hopefully the author will fix this soon.

@tslagle13 is the author. I think you can submit your changes to him here.

1 Like

Hi Tim @slagle
The vacation light app seems to work fine for a few days but then in 2-3 days seems to stop working. I tried to run this while I was on vacation and it seemed to work for 2 days when I changed modes, but then after that stopped working- with either the lights stuck on or never switching on in the first place during the assigned time window. I went into the app and changed the mode and reset it and it began working again. So I think it works fine to start off with but has an issue later. Just letting you know in case there is a bug to be fixed. Not sure if the hub has been rebooting as someone on the thread mentioned.

Thanks

Hi all.
I have put in the additional code as suggested by rgledhill and the rule is functioning ok when I am away.
Also if I look in the activity feed i can see that the rule is triggering every 15min which is the time set in the rule. The lights do not come on when I am home or outside the time window but can be seen in the activity log.
Fingers crossed that this will continue to work OK as I feel that this is a fantastic app.

That’s good news, considering I didn’t even have time to test that code :slight_smile:

Can you post the code? I made the edits that @rgledhill described but I’m getting the “unauthorized” banner on installation - and I have to delete the installed instance via the ide as described above.

Here is the code that is working for me.
No guarantees though. :wink:

/**

  • Vacation Lighting Director
  • Version 2.4 - Added information paragraphs
  • Source code can be found here: https://github.com/tslagle13/SmartThings/blob/master/smartapps/tslagle13/vacation-lighting-director.groovy
  • Copyright 2015 Tim Slagle
  • 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.

*/

// Automatically generated. Make future change here.
definition(
name: “Vacation Lighting Director”,
namespace: “Tim Slagle”,
author: “Tim Slagle”,
category: “Safety & Security”,
description: “Randomly turn on/off lights to simulate the appearance of a occupied home while you are away.”,
iconUrl: “http://icons.iconarchive.com/icons/custom-icon-design/mono-general-2/512/settings-icon.png”,
iconX2Url: “http://icons.iconarchive.com/icons/custom-icon-design/mono-general-2/512/settings-icon.png
)

preferences {
page name:"pageSetup"
page name:"Setup"
page name:“Settings”

}

// Show setup page
def pageSetup() {

def pageProperties = [
    name:       "pageSetup",
    title:      "Status",
    nextPage:   null,
    install:    true,
    uninstall:  true
]

return dynamicPage(pageProperties) {
    section(""){
        paragraph "This app can be used to make your home seem occupied anytime you are away from your home. " +
        "Please use each othe the sections below to setup the different preferences to your liking. " +
        "I recommend this app be used with at least two away modes.  An example would be 'Away Day' 'and Away Night'. " 
    }
    section("Setup Menu") {
        href "Setup", title: "Setup", description: "", state:greyedOut()
        href "Settings", title: "Settings", description: "", state: greyedOutSettings()
        }
    section([title:"Options", mobileOnly:true]) {
        label title:"Assign a name", required:false
    }
}

}

// Show “Setup” page
def Setup() {

def newMode = [
    name:           "newMode",
    type:           "mode",
    title:          "Which?",
    multiple:       true,
    required:       true
]
def switches = [
    name:           "switches",
    type:           "capability.switch",
    title:          "Switches",
    multiple:       true,
    required:       true
]

def frequency_minutes = [
    name:           "frequency_minutes",
    type:           "number",
    title:          "Minutes?",
    required:    true
]

def number_of_active_lights = [
    name:           "number_of_active_lights",
    type:           "number",
    title:          "Number of active lights",
    required:    true,
]

def people = [
    name:       "people",
    type:       "capability.presenceSensor",
    title:      "If these people are home do not change light status",
    required:    true,
    multiple:    true
]

def pageName = "Setup"

def pageProperties = [
    name:       "Setup",
    title:      "Setup",
    nextPage:   "pageSetup"
]

return dynamicPage(pageProperties) {

    section(""){            
                paragraph "In this section you need to setup the deatils of how you want your lighting to be affected while " +
                paragraph "you are away.  All of these settings are required in order for the simulator to run correctly."
    }
    section("Which mode change triggers the simulator? (This app will only run in selected mode(s))") {
                input newMode           
    }
    section("Light switches to turn on/off") {
                input switches           
    }
    section("How often to cycle the lights") {
                input frequency_minutes            
    }
    section("Number of active lights at any given time") {
                input number_of_active_lights           
    }    
    section("People") {
                input people            
    }
}

}

// Show “Setup” page
def Settings() {

def falseAlarmThreshold = [
    name:       "falseAlarmThreshold",
    type:       "decimal",
    title:      "Default is 2 minutes",
    required:    false
]
def days = [
    name:       "days",
    type:       "enum",
    title:      "Only on certain days of the week",
    multiple:   true,
    required:   false,
    options: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
]

def pageName = "Settings"

def pageProperties = [
    name:       "Settings",
    title:      "Settings",
    nextPage:   "pageSetup"
]

return dynamicPage(pageProperties) {

    section(""){              
                paragraph "In this section you can restrict how your simulator runs.  For instance you can restrict on which days it will run " +
                paragraph "as well as a delay for the simulator to start after it is in the correct mode.  Delaying the simulator helps with false starts based on a incorrect mode change."
    }
    section("Delay to start simulator") {
                input falseAlarmThreshold
    }
    section("More options") {
                href "timeIntervalInput", title: "Only during a certain time", description: getTimeLabel(starting, ending), state: greyedOutTime(starting, ending), refreshAfterSelection:true
                input days
    } 
}   

}

page(name: “timeIntervalInput”, title: “Only during a certain time”, refreshAfterSelection:true) {
section {
input “starting”, “time”, title: “Starting”, required: false
input “ending”, “time”, title: “Ending”, required: false
}
}

def installed() {
initialize()
if (newMode.any{ it == location.mode } || newMode == location.mode)
{ def delay = (falseAlarmThreshold != null && falseAlarmThreshold != “”) ? falseAlarmThreshold * 60 : 2 * 60 }
runIn(delay, scheduleCheck)
}

def updated() {
unsubscribe();
unschedule();
initialize()
}

def initialize(){

if (newMode != null) {
    subscribe(location, modeChangeHandler)
}

}

def modeChangeHandler(evt) {
log.debug "Mode change to: ${evt.value}"
def delay = (falseAlarmThreshold != null && falseAlarmThreshold != “”) ? falseAlarmThreshold * 60 : 2 * 60
runIn(delay, scheduleCheck)
}

//Main logic to pick a random set of lights from the large set of lights to turn on and then turn the rest off
def scheduleCheck(evt) {
if(allOk){
log.debug(“Running”)
// turn off all the switches
switches.off()

// grab a random switch
def random = new Random()
def inactive_switches = switches
for (int i = 0 ; i < number_of_active_lights ; i++) {
// if there are no inactive switches to turn on then let’s break
if (inactive_switches.size() == 0){
break
}

// grab a random switch and turn it on
def random_int = random.nextInt(inactive_switches.size())
inactive_switches[random_int].on()

// then remove that switch from the pool off switches that can be turned on
inactive_switches.remove(random_int)

}

// re-run again when the frequency demands it
runIn(frequency_minutes * 60, scheduleCheck)
}
//Check to see if mode is ok but not time/day. If mode is still ok, check again after frequency period.
else if (modeOk) {
log.debug(“mode OK. Running again”)
runIn(frequency_minutes * 60, scheduleCheck)
switches.off()
}
//if none is ok turn off frequency check and turn off lights.
else if(people){
//don’t turn off lights if anyone is home
if(someoneIsHome()){
log.debug(“Stopping Check for Light”)
}
else{
log.debug(“Stopping Check for Light and turning off all lights”)
switches.off()
}
}
}

//below is used to check restrictions
private getAllOk() {
modeOk && daysOk && timeOk && homeIsEmpty
}

private getModeOk() {
def result = !newMode || newMode.contains(location.mode)
log.trace "modeOk = $result"
result
}

private getDaysOk() {
def result = true
if (days) {
def df = new java.text.SimpleDateFormat(“EEEE”)
if (location.timeZone) {
df.setTimeZone(location.timeZone)
}
else {
df.setTimeZone(TimeZone.getTimeZone(“America/New_York”))
}
def day = df.format(new Date())
result = days.contains(day)
}
log.trace "daysOk = $result"
result
}

private getTimeOk() {
def result = true
if (starting && ending) {
def currTime = now()
def start = timeToday(starting).time
def stop = timeToday(ending).time
result = start < stop ? currTime >= start && currTime <= stop : currTime <= stop || currTime >= start
}

else if (starting){
    result = currTime >= start
}
else if (ending){
    result = currTime <= stop
}

log.trace "timeOk = $result"
result

}

private getHomeIsEmpty() {
def result = true

if(people?.findAll { it?.currentPresence == “present” }) {
result = false
}

log.debug(“homeIsEmpty: ${result}”)

return result
}

private getSomeoneIsHome() {
def result = false

if(people?.findAll { it?.currentPresence == “present” }) {
result = true
}

log.debug(“anyoneIsHome: ${result}”)

return result
}

//gets the label for time restriction. Label phrasing changes depending on if there is both start and stop times or just one start/stop time.
def getTimeLabel(starting, ending){

def timeLabel = "Tap to set"

if(starting && ending){
    timeLabel = "Between" + " " + hhmm(starting) + " "  + "and" + " " +  hhmm(ending)
}
else if (starting) {
    timeLabel = "Start at" + " " + hhmm(starting)
}
else if(ending){
timeLabel = "End at" + hhmm(ending)
}
timeLabel

}

//fomrats time to readable format for time label
private hhmm(time, fmt = “h:mm a”)
{
def t = timeToday(time, location.timeZone)
def f = new java.text.SimpleDateFormat(fmt)
f.setTimeZone(location.timeZone ?: timeZone(time))
f.format(t)
}

//sets complete/not complete for the setup section on the main dynamic page
def greyedOut(){
def result = ""
if (switches) {
result = “complete”
}
result
}

//sets complete/not complete for the settings section on the main dynamic page
def greyedOutSettings(){
def result = ""
if (starting || ending || days || falseAlarmThreshold) {
result = “complete”
}
result
}

//sets complete/not complete for time restriction section in settings
def greyedOutTime(starting, ending){
def result = ""
if (starting || ending) {
result = “complete”
}
result
}

1 Like

Thanks. I was able to at least install it now. Now for testing.

I ended up created two modes. Vacation Day and Vacation Night to get around the issue with it failing after a day or two. Sunrise triggers Day, Sunset triggers Night. Vacation Light Director fires from 7:00 to 11:30 then turns off. Rinse, repeat.

2 Likes

I am using the vacation light director found in the marketplace. I set up a Vacation mode and activated the routine manually when I left for vacation. It ran fine the first night so I thought all was good. Just looked only to discover that the rule has not run for the last five days after initial night.

Anyone have any ideas. Still on vacation so I don’t want to spend too much time on it.

I had the same issue about 6 weeks ago. Never did resolve it.

I initially had the same issue where it would not run after the first night or two. I uninstalled and reinstalled, and it’s been running fine ever since.

The issue I’m having now is, while it is running during my scheduled time, the lights stay on.

I set it to 20 minutes cycle. Every 20 minutes, I see Vacation Light Director send an Off command, then an On command directly after. So basically, the lights are on the entire time. Instead of randomly telling it on or off every 20 minutes, it gets an Off then On command every 20 minutes, so the lights are always on.

Any ideas?

How can I test if this works if my presence (phone) is always detected?

Hi.
How can I get this into my personal repository.
I beleive I need I need to put in the owner and name of the file in my apps settings on ide GitHub Repository Integration.
For example I have bravenel and Rule-Trigger for the Rule Machine App.
Thanks.

I am in exactly the same boat. Reinstalled starting working fine except for the lights never going off. Well and running outside of the time frame that I set. it stays with the mode but doesn’t pay attention to what I put in only run between.

You could always try out the “Fake TV” http://www.amazon.com/gp/product/B003S5SOLG More power efficient too!

1 Like

This looks like a great addition to “the arsenal” of options to deter theft. You could put a smart outlet with it to ensure it is only on while in away mode.

I’ve had one of these for years and love it. I always make sure it’s included in my VLD setups.