Can someone modify the big switch app to call Hello Home Phrases?

also. in reply to my last reply. If you want hello home to tell you what it is doing. add this to each event.

sendNotificationEvent(“Performing “${HHPhraseOn}” because ${master} turned on.”)

OK, used the code from at @leftride and added @tslagle13 's notification (Thank You guys both so much)… No errors in the simulator. Also no reaction in the console when the master switch flips… Should I see one? I am guessing the simulator may not support Hello Home to see the results there.

The simultaor should recognize the switch being turned on and off, make sure you select the right switch in the IDE though. Keep in mind. Without “def configured = (settings.HHPhraseOff && settings.HHPhraseOn)” this code will not work as the script won’t know what phrase to run. I have this exact screnario working in a much larger app with many more variables. I pulled the code directly from there for the prefrences page.

Here is a working app i have so you can see how things work in full scale.

definition(
    name: "Auto away/home with night modes",
    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: "Mode Magic",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.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?", metadata:[values:["Yes","No"]], required:false
  	}
    section(title: "More options", hidden: hideOptionsSection(), hideable: true) {
			
			def timeLabel = timeIntervalLabel()

			href "timeIntervalInput", title: "Only during a certain time", description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : null

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

def installed() {
  init()
  initialize()
  subscribe(app)

}

def updated() {
  unsubscribe()
  initialize()

  init()
}

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

  checkSun();
}

def uninstalled() {
unsubscribe()
}

def initialize() {
	schedule("0 0/5 * 1/1 * ? *", checkSun)
}

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 = "sunset"
  }

  else {
    state.sunMode = "sunrise"
  }

  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() {
  state.sunMode = "sunrise";
  changeSunMode(newMode)
}

def setSunset() {
  state.sunMode = "sunset";
  changeSunMode(newMode)
}


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)
      send(message)
      location.helloHome.execute(settings.awayNight)
    }
    
    else if(state.sunMode == "sunrise") {
      def message = "Performing \"${awayDay}\" for you as requested."
      log.info(message)
      send(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"){
      def message = "Performing \"${homeNight}\" for you as requested."
        log.info(message)
        location.helloHome.execute(settings.homeNight)
			send(message)
            sendSms(phone1, message)
       }
       
      if(state.sunMode == "sunrise"){
      def message = "Performing \"${homeDay}\" for you as requested."
        log.info(message)
        location.helloHome.execute(settings.homeDay)
			send(message)
            sendSms(phone1, message)
            }
    }
    
}

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
}

private send(msg) {
  if(sendPushMessage != "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 hideOptionsSection() {
	(starting || ending || days || modes) ? false : true
}

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

Feel free to copy and paste from here as needed.

The only difference is this app monitors presence instead of a switch variable.

Gonna play with it a little… By the way… Love that App, it is exactly what ST needs… My only reccomentdation, is that I would love to be able to pick different phrases based on which individual sensor is home. Example… I am home but wife is away, run one phrase, wife is home, but I am away run a different one… it seem like you are going in that direction. I think running a different phrase if one person is home isn’t as useful if you don’t act based on which person is home.

OK… What I think I’m doing…

section(“When this switch is turned on or off”) {
input “master”, “capability.switch”, title: “Where?”
}

Having the user select which switch will initiate the Hello Home Phrase

section(“Hello Home Actions”) {
log.trace phrases
input “HHPhrase”, “enum”, title: “Enter Hello Home Phrase”, required: true, options: phrases, refreshAfterSelection:true
}

Having the User select the Hello Home Phrase they want to execute.

def installed()
{
subscribe(settings.master, “switch.on”, onHandler)
subscribe(settings.master, “switch.off”, offHandler)
}

def updated()
{
unsubscribe()
subscribe(master, “switch.on”, onHandler)
subscribe(master, “switch.off”, offHandler)
}

Subscribing to the on and off events from the Switch the user selected

def onHandler(evt) {
log.debug evt.value
sendNotificationEvent(“Performing "${HHPhraseOn}" because ${master} turned on.”)
location.helloHome.execute(settings.HHPhrase)
}

def offHandler(evt) {
log.debug evt.value
}

If the Switch on event is detected, executing the Hello Home Phrase the user selected If a switch off event is detected it is logged, but no activity.

There is obviously something I am missing… I don’t see the on or off action if I select anything but the “Master” Virtual switch in the simulator. and event then I don’t see anything representing the execution of the Hello Phrase.

I didn’t really understand where I would put “def configured = (settings.HHPhraseOff && settings.HHPhraseOn)” and why.

Double check your dynamic page definition:

dynamicPage(name: "selectPhrases", title: "Configure Your Hello Home Phrase.", install: true, uninstall: true)

Make sure install is set to true, originally you were setting that value to configured and I too noticed the event wasn’t firing.

Ok, here is a tested and verified app. Does excatly what you want it to do. When a switch turns off it runs XYS hello home phrase, when a switch turns on it runs XYZ hello home phrase.

copy and past all of it into your app and publish it for yourself and you will be able to install it from your apps on your mobile device. I will also publish it to the shared apps.

/**
 *  Big Switch for Hello Home Phrases
 *
 *  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: "Big Switch for Hello Home Phrases",
    namespace: "",
    author: "Tim Slagle",
    description: "Uses a virtual switch to run hello home phrases.",
    category: "Convenience",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png"
)


preferences {
	page(name: "selectPhrases")
    
    page( name:"Settings", title:"Settings", uninstall:true, install:true ) {
    section(title: "More options", hidden: hideOptionsSection(), hideable: true) {
			
			def timeLabel = timeIntervalLabel()

			href "timeIntervalInput", title: "Only during a certain time", description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : null

			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.HHPhraseOff && settings.HHPhraseOn)
    dynamicPage(name: "selectPhrases", title: "Configure", nextPage:"Settings", uninstall: true) {		
		section("When this switch is turned on or off") {
			input "master", "capability.switch", title: "Where?"
		}
        def phrases = location.helloHome?.getPhrases()*.label
		if (phrases) {
        	phrases.sort()
		section("Run These Hello Home Phrases When...") {
			log.trace phrases
			input "HHPhraseOn", "enum", title: "The Switch Turns On", required: true, options: phrases, refreshAfterSelection:true
			input "HHPhraseOff", "enum", title: "The Switch Turns Off", required: true, options: phrases, refreshAfterSelection:true

		}
		}
    }
}    


def installed(){
subscribe(master, "switch.on", onHandler)
subscribe(master, "switch.off", offHandler)
}

def updated(){
unsubscribe()
subscribe(master, "switch.on", onHandler)
subscribe(master, "switch.off", offHandler)
}

def onHandler(evt) {
log.debug evt.value
log.info("Running Light On Event")
sendNotificationEvent("Performing \"${HHPhraseOn}\" because ${master} turned on.")
location.helloHome.execute(settings.HHPhraseOn)
}

def offHandler(evt) {
log.debug evt.value
log.info("Running Light Off Event")
sendNotificationEvent("Performing \"${HHPhraseOff}\" because ${master} turned off.")
location.helloHome.execute(settings.HHPhraseOff)
}

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 hideOptionsSection() {
	(starting || ending || days || modes) ? false : true
}

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

@tslagle13 It Worked Perfect! I created a virtual switch via the on/off button tile and I put it in my dashboard, and now I can call Hello Home Phrases from the Dashboard and from an IFTTT workflow! Also I want that other app when you are done with it!

Thank You @leftride too!

@bgoodman

Glad to hear it worked for you!!

Ive been using the other app for a few days now. I just published the away/home app to the publoished apps on the IDE. You can grab it from there. Let me know if you see any issues with it. Ive been using it for about a week and I haven’t seen any problems. I would recomend keeping notifications on so you can tell whats happening. (Just in case)

Let me know how it works out for you. If it works out for you I will submit it to smartthings for addition to the publicly available apps in the mobile app. As for the changes you mentioned, it would be way to hard to fit all the logic in there for that. The logic in this one is pretty crazy as it is. I’m good, but not that good :wink:

What does it mean “published apps on the IDE.”? How do I get to those apps?

Create a new smart app and in the code page int he top right there is a Browse Smart Apps drop down. Click that and then click browse shared smart apps. Mine will be in the recent category. Select my app and hit overwirte. publish and install through the mobile app.

Hi Tim,

I modified your app a bit, I added the following:

  • the time selection menu was missing - found it in another smartapp from you
  • the possibility to react only on an OFF event

Thanks for the code.

/**

  • Big Switch for Hello Home Phrases
  • 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: “Big Switch for Hello Home Phrases”,
namespace: “tslagle13”,
author: “Tim Slagle”,
description: “Uses a virtual/or physical switch to run hello home phrases.”,
category: “Convenience”,
iconUrl: “http://icons.iconarchive.com/icons/icons8/windows-8/512/User-Interface-Switch-On-icon.png”,
iconX2Url: “http://icons.iconarchive.com/icons/icons8/windows-8/512/User-Interface-Switch-On-icon.png
)

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

page( name:"Settings", title:"Settings", uninstall:true, install:true ) {
	section("Settings") {
		label title: "Assign a name", required: false
	}
	section(title: "More options", hidden: hideOptionsSection(), hideable: true) {

		def timeLabel = timeIntervalLabel()

		href "timeIntervalInput", title: "Only during a certain time", description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : null

		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.HHPhraseOff && settings.HHPhraseOn)
dynamicPage(name: “selectPhrases”, title: “Configure”, nextPage:“Settings”, uninstall: true) {
section(“When this switch is turned on or off”) {
input “master”, “capability.switch”, title: “Where?”
}
def phrases = location.helloHome?.getPhrases()*.label
if (phrases) {
phrases.sort()
section(“Run These Hello Home Phrases When…”) {
log.trace phrases
input “HHPhraseOn”, “enum”, title: “The Switch Turns On”, required: false, options: phrases, refreshAfterSelection:true
input “HHPhraseOff”, “enum”, title: “The Switch Turns Off”, required: false, options: phrases, refreshAfterSelection:true

		}
	}
}

}

def installed(){
subscribe(master, “switch.on”, onHandler)
subscribe(master, “switch.off”, offHandler)
}

def updated(){
unsubscribe()
subscribe(master, “switch.on”, onHandler)
subscribe(master, “switch.off”, offHandler)
}

def onHandler(evt) {
if(allOk && HHPhraseOn) {
log.debug evt.value
log.info(“Running Light On Event”)
sendNotificationEvent(“Performing “${HHPhraseOn}” because ${master} turned on.”)
location.helloHome.execute(settings.HHPhraseOn)
}
}

def offHandler(evt) {
if(allOk && HHPhraseOff) {
log.debug evt.value
log.info(“Running Light Off Event”)
sendNotificationEvent(“Performing “${HHPhraseOff}” because ${master} turned off.”)
location.helloHome.execute(settings.HHPhraseOff)
}
}

private getAllOk() {
TRACE(“getAllOk - called”)
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”)
{
TRACE(“hhmm - called”)
def t = timeToday(time, location.timeZone)
def f = new java.text.SimpleDateFormat(fmt)
f.setTimeZone(location.timeZone ?: timeZone(time))
f.format(t)
}

private hideOptionsSection() {
TRACE(“hideOptionsSection - called”)
(starting || ending || days || modes) ? false : true
}

private timeIntervalLabel() {
TRACE(“timeIntervalLabel - called”)
(starting && ending) ? hhmm(starting) + “-” + hhmm(ending, “h:mm a z”) : “”
}

private def TRACE(message) {
//log.debug message
}

1 Like

So I was able to instal the smart app but I am not sure where to go from there. I can see it on my phone but I am not sre how to configure it. Any help would be appreciated. This is my first dance into smart apps. Thanks

More specifically when I click on the app from my phone the only options I have under the configure is to set specific modes and give a name.

Can you provide a screenshot?

This was exactly what I was looking for, to integrate Google Calendar with SmartThings via IFTTT. A calendar entry with a specific phrase triggers IFTTT, which switches a virtual switch, which triggers your app, which sets the SmartThings mode to Away. Thanks!

Remember I can’t read code, so forgive me if this is a dumb question.

If there are mode restrictions in the Hello Home phrase itself, are they honored when this triggers?

That is, say I have a switch to trigger my Goodbye! action which turns off the lights, but the Goodbye! is not supposed to run if the mode is Guests. Will flipping the switch cause the lights to go off or not?

Thanks!

No. :smile:


BTW, there is now an easy install version of this available through Smart Setup. No more cut and paste!

See #25 and 26 under convenience. One uses a switch to change the mode and one uses a switch to run a Hello Home Action.

Hey - @bgoodman thank you for this outstanding SmartApp.

Do you think you can modify it to not fire the Routine if the Hub is already in the to-be-activated mode? I tried to give it a shot, but it requires a method to get the mode out of a phrase, which I couldn’t figure out. If someone else knows how to do that, I’ll submit a patch :smile:

Kristopher