Virtual Tile to ignore certain smartapps when on vacation


(Jake) #1

I swear I saw this topic somewhere else, but I cannot find it anymore. Really wishing I would have starred it right now! Oh well…

What I am trying to do is create a virtual tile that essentially just keeps my home in away mode while on vacation. I’ve got lights in the house set to timers, thermostat apps and a jawbone up24 that I would like to be ignored while I am out. On the other hand, I would like to keep my foscam camera alarm on the whole time. What I’m thinking is a virtual tile that when switched on, keeps the house in away mode and when switched off goes about business as usual (i.e. up24 functions again, lights on timers again, foscam alarm off, etc.)

Has anyone done something like this that they could share? Thanks in advance!


(Tim Slagle) #2

Check this out :smile: Wrote this for this exact scenario.

Then just limit your apps to only run when your house is set to one of the “home modes” or “away modes” depending on when you want them to run.

/**
 *  Auto Home/Away with night modes
 *
 *  Copyright 2014 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.
 *
 */
definition(
    name: "Magic Home",
    namespace: "tslagle13",
    author: "Tim Slagle",
    description: "Monitor a set of presence sensors and change mode based on when your home is empty or occupied.  Included Night and Day modes for both an occupied and unoccupied house.",
    category: "Convenience",
    iconUrl: "http://icons.iconarchive.com/icons/icons8/ios7/512/Very-Basic-Home-Filled-icon.png",
    iconX2Url: "http://icons.iconarchive.com/icons/icons8/ios7/512/Very-Basic-Home-Filled-icon.png"
)

preferences {
  page(name: "selectPhrases")
    
  page( name:"Settings", title:"Settings", uninstall:true, install:true ) {
  	section("False alarm threshold (defaults to 10 min)") {
    	input "falseAlarmThreshold", "decimal", title: "Number of minutes", required: false
  	}

  	section("Zip code (for sunrise/sunset)") {
   		input "zip", "decimal", required: true
  	}

      section("Notifications") {
        input "sendPushMessage", "enum", title: "Send a push notification when house is empty?", metadata:[values:["Yes","No"]], required:false
        input "sendPushMessageHome", "enum", title: "Send a push notification when home is occupied?", metadata:[values:["Yes","No"]], required:false
  	}

    section(title: "More options", hidden: hideOptionsSection(), hideable: true) {
    		label title: "Assign a name", required: false
			input "days", "enum", title: "Only on certain days of the week", multiple: true, required: false,
				options: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
			input "modes", "mode", title: "Only when mode is", multiple: true, required: false
		}
  }
}

def selectPhrases() {
	def configured = (settings.awayDay && settings.awayNight && settings.homeDay && settings.homeNight)
    dynamicPage(name: "selectPhrases", title: "Configure", nextPage:"Settings", uninstall: true) {		
		section("Who?") {
			input "people", "capability.presenceSensor", title: "Monitor These Presences", required: true, multiple: true,  refreshAfterSelection:true
		}
        
		def phrases = location.helloHome?.getPhrases()*.label
		if (phrases) {
        	phrases.sort()
			section("Run This Phrase When...") {
				log.trace phrases
				input "awayDay", "enum", title: "Everyone Is Away And It's Day", required: true, options: phrases,  refreshAfterSelection:true
				input "awayNight", "enum", title: "Everyone Is Away And It's Night", required: true, options: phrases,  refreshAfterSelection:true
                input "homeDay", "enum", title: "At Least One Person Is Home And It's Day", required: true, options: phrases,  refreshAfterSelection:true
                input "homeNight", "enum", title: "At Least One Person Is Home And It's Night", required: true, options: phrases,  refreshAfterSelection:true
			}
            section("Select modes used for each condition. (Needed for better app logic)") {
        input "homeModeDay", "mode", title: "Select Mode Used for 'Home Day'", required: true
        input "homeModeNight", "mode", title: "Select Mode Used for 'Home Night'", required: true
  	}
		}
    }
}

def installed() {
  init()
  initialize()

}

def updated() {
  unsubscribe()
  initialize()

  init()
}

def init() {
  subscribe(people, "presence", presence)
}

def uninstalled() {
unsubscribe()
}

def initialize() {
    runIn(60, checkSun)
	subscribe(location, "sunrise", setSunrise)
	subscribe(location, "sunset", setSunset)
}

def checkSun() {
  def zip     = settings.zip as String
  def sunInfo = getSunriseAndSunset(zipCode: zip)
 def current = now()

if (sunInfo.sunrise.time < current && sunInfo.sunset.time > current) {
    state.sunMode = "sunrise"
   setSunrise()
  }
  
else {
   state.sunMode = "sunset"
    setSunset()
  }

log.info("Sunset: ${sunInfo.sunset.time}")
 log.info("Sunrise: ${sunInfo.sunrise.time}")
 log.info("Current: ${current}")
log.info("sunMode: ${state.sunMode}")

 if(current < sunInfo.sunrise.time) {
  runIn(((sunInfo.sunrise.time - current) / 1000).toInteger(), setSunrise)
  }

  if(current < sunInfo.sunset.time) {
  runIn(((sunInfo.sunset.time - current) / 1000).toInteger(), setSunset)
 }
}

def setSunrise(evt) {
  state.sunMode = "sunrise";
  changeSunMode(newMode);
  sendNotificationEvent("Setting Sunrise Mode")
}

def setSunset(evt) {
  state.sunMode = "sunset";
  changeSunMode(newMode)
  sendNotificationEvent("Setting Sunset Mode")
}


def changeSunMode(newMode) {
  if(allOk) {

  if(everyoneIsAway() && (state.sunMode == "sunrise")) {
    log.info("Home is Empty  Setting New Away Mode")
    def delay = (falseAlarmThreshold != null && falseAlarmThreshold != "") ? falseAlarmThreshold * 60 : 10 * 60 
    runIn(delay, "setAway")
  }

  if(everyoneIsAway() && (state.sunMode == "sunset")) {
    log.info("Home is Empty  Setting New Away Mode")
    def delay = (falseAlarmThreshold != null && falseAlarmThreshold != "") ? falseAlarmThreshold * 60 : 10 * 60 
    runIn(delay, "setAway")
  }
  
  else {
  log.info("Home is Occupied Setting New Home Mode")
  setHome()


  }
}
}

def presence(evt) {
  if(allOk) {
  if(evt.value == "not present") {
    log.debug("Checking if everyone is away")

    if(everyoneIsAway()) {
      log.info("Nobody is home, running away sequence")
      def delay = (falseAlarmThreshold != null && falseAlarmThreshold != "") ? falseAlarmThreshold * 60 : 10 * 60 
      runIn(delay, "setAway")
    }
  }

else {
	def lastTime = state[evt.deviceId]
    if (lastTime == null || now() - lastTime >= 1 * 60000) {
  		log.info("Someone is home, running home sequence")
  		setHome()
    }    
	state[evt.deviceId] = now()

  }
}
}

def setAway() {
  if(everyoneIsAway()) {
    if(state.sunMode == "sunset") {
      def message = "Performing \"${awayNight}\" for you as requested."
      log.info(message)
      sendAway(message)
      location.helloHome.execute(settings.awayNight)
    }
    
    else if(state.sunMode == "sunrise") {
      def message = "Performing \"${awayDay}\" for you as requested."
      log.info(message)
      sendAway(message)
      location.helloHome.execute(settings.awayDay)
      }
    else {
      log.debug("Mode is the same, not evaluating")
    }
  }

  else {
    log.info("Somebody returned home before we set to '${newAwayMode}'")
  }
}

def setHome() {

log.info("Setting Home Mode!!")
if(anyoneIsHome()) {
      if(state.sunMode == "sunset"){
      if (location.mode != "${homeModeNight}"){
      def message = "Performing \"${homeNight}\" for you as requested."
        log.info(message)
        sendHome(message)
        location.helloHome.execute(settings.homeNight)
        }
       }
       
      if(state.sunMode == "sunrise"){
      if (location.mode != "${homeModeDay}"){
      def message = "Performing \"${homeDay}\" for you as requested."
        log.info(message)
        sendHome(message)
        location.helloHome.execute(settings.homeDay)
            }
      }      
    }
    
}

private everyoneIsAway() {
  def result = true

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

  log.debug("everyoneIsAway: ${result}")

  return result
}

private anyoneIsHome() {
  def result = false

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

  log.debug("anyoneIsHome: ${result}")

  return result
}

def sendAway(msg) {
  if(sendPushMessage != "No") {
    log.debug("Sending push message")
    sendPush(msg)
  }

  log.debug(msg)
}

def sendHome(msg) {
  if(sendPushMessageHome != "No") {
    log.debug("Sending push message")
    sendPush(msg)
  }

  log.debug(msg)
}

private getAllOk() {
	modeOk && daysOk && timeOk
}

private getModeOk() {
	def result = !modes || modes.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
	}
	log.trace "timeOk = $result"
	result
}

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)
}

private getTimeIntervalLabel()
{
	(starting && ending) ? hhmm(starting) + "-" + hhmm(ending, "h:mm a z") : ""
}

private hideOptionsSection() {
	(starting || ending || days || modes) ? false : true
}

(Greg) #3

Why not go into your hello home, gear settings - good morning & goodnight (and any other time based mode change) and select for them not to automatically happen if you are in away mode?

that’s what I use and it works well.


(Tim Slagle) #4

Yes this can work as well. But i wanted my modes to be sunrise and sunset specific. Unfortuantely at the moment that isn’t easy with Hello, Home. Rule builder will fix this im sure… but your way will work if you just care about our house knowing whether you’re home or not and not have time based requirements on it as well.


(Greg) #5

out of curiosity what are you doing with modes that is sunrise/sunset specific?

I really hope rule builder is what I think it is. Something that non coders like me can use to make our own smart apps for our specific use cases we can’t seem to bribe ST, or coders, into making.


(Tim Slagle) #6

I have “security lights” that turn on only at night based on when im home and gone. Different light levels for when im home and gone and whether it is night or day… as well as a random light switcher when im gone. These only run at night so im not turning on lights during the day.

Also, my windows face both sunrsie and sunset so the house is set to a cooler temp duing the day then at night if i am away so the dog can remain comfy.

I also have foscams that i control the “night Vision” on as well as their motion detection sensitivity during the day or night. And probably a few more reasons that i am not remembering.


(Jake) #7

@greg and @tslagle13 thanks guys!! I think I should be able to do what I’m looking for using a combo of your suggestions. I really appreciate it!


(Barry) #8

Suggestion - make your Zip code a string instead of a decimal. That way, users can take advantage of the full array of WeatherUnderground stations, selecting a more local station’s weather if desired. I use my own by entering the string “pws:KMATYNGS02” in the ZipCode field.


(Tim Slagle) #9

Working on it:)

Also working on having it check whether conditions and if the weather is “dark” it will turn it to a certain mode. Updates coming soon(ish) :smile:

Also, thiking about adding something like when someone comes home turn on this mode at night for 15 minutes then turn on XYZ mode. I like it to be nice and bright when i get home and then after that i like it have it dim and peaceful.

I’d love to see if you have any other suggestions :smile:


(Barry) #10

I customized the SmartWeather tile app to calculate a Lux based on Solar or UV observations of the station, but an AEON Multi-sensor provides more reliable light readings. I use that approach for my Smart Pet Light app…


(Tim Slagle) #11

I got a few of these a couple weeks ago and they ROCK!

Just sayin…