Two events to trigger one action - Help!


#1

Okay, I haven’t coded anything in 15 years and even then I was pretty beginner. I’m struggling to wrap my head around groovy and can’t figure out what I know should be exceptionally basic coding.

I have indoor cats and we just moved into a house I’m automating. So I want to set up an alert for when I’ve left the door into the house open AND, the garage door OR the other garage door. So three doors with two of them being left open, one of which must be the door into the house.

I’m trying to look at other code as examples but I can’t find anything that requires multiple conditions to perform a single action. Any help would be appreciated!


(Tim Slagle) #2

This will take some funky coding. Could get it to work using somehitng like this.

Two seperate values for the settings in the smart app and then check to see if any of the itsm in the values match a certain value and trigger if both meet the criteria.

def openGarage = garage.findAll { it?.latestValue("contact") == 'open' }
    def openDoor = door.findAll { it?.latestValue("contact") == 'open' }

   	if (openDoor&& openGarage){
    	DO XYZ THING
        }

#3

Unfortunately I couldn’t get that to work. I really haven’t a clue what I’m doing. I plan on adding other contact sensors on other doors, so my plan is to make the garage entrance selectable and not have this happen with all doors. Also, to have it push after 3 minutes as sometimes I’ll be bringing something inside or taking out the trash and leave the door open for a few moments without wanting it to go off. I just don’t understand how a logic function that takes seconds to program in something like Excel can be so overly unnecessarily complicated and why SmartThings wouldn’t have a generic ‘If this AND that, then this’ written into their system. It seems most HA systems are a lot more flexible. frustrated

preferences {
	section("Door into house to watch"){
		input "door", "capability.contactSensor", title: "Door Contact", required: true
	}
	section("Send message via push notification"){
		input "openText", "Text", title: "Message", required: true
  	}

}

def openText = "The cats can get out!"

def openGarage = garage.findAll { it?.latestValue("contact") == 'open' }
    def openDoor = door { it?.latestValue("contact") == 'open' }

   	if (openDoor && openGarage){
    	sendPush(openText)
	}

(Tim Slagle) #4

I got something for you. I’ll share in a bit


(Tim Slagle) #5

Give this a try. Didn’t test it myself so give it a test and let me know if it works or not :smile:

/**
 *  Left two open?
 *
 *  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: "Left two open?",
    namespace: "tslagle13",
    author: "Tim Slagle",
    description: "Checks two sets of doors to see if one or omre doors are left open from each set of doors.",
    category: "Safety & Security",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png"
)


preferences {
	section("Which mode changes trigger the check?") {
		input "newMode", "mode", title: "Which?", multiple: true, required: false
	}
    section("Which doors, windows, and locks should I check?"){
		input "contacts1", "capability.contactSensor", title: "1st set of doors?", multiple: true, required: true
        input "contacts2", "capability.contactSensor", title: "2nd set of doors?", multiple: true, required: false
    }
    section("Via a push notification and/or an SMS message"){
		input "phone", "phone", title: "Phone Number (for SMS, optional)", required: false
		input "pushAndPhone", "enum", title: "Both Push and SMS?", required: false, options: ["Yes","No"]
	}
    section("Settings"){
		input "sendPushUnsecure", "enum", title: "Send a SMS/push notification when home is unsecure?", metadata:[values:["Yes","No"]], required:true
        input "sendPushSecure", "enum", title: "Send a SMS/push notification when house is secure?", metadata:[values:["Yes","No"]], required:true
        input "lockAuto", "enum", title: "Lock door(s) automatically if found unsecure?", metadata:[values:["Yes","No"]], required:false
    }
    section(title: "More options", hidden: hideOptionsSection()) {
			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 installed() {
	log.debug "Installed with settings: ${settings}"
    initialize()
}

def updated() {
	log.debug "Updated with settings: ${settings}"
	unsubscribe()
    unschedule()
    initialize()
}

def initialize(){

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




def modeChangeHandler(evt) {
	log.debug "Mode change to: ${evt.value}"
    // Have to handle when they select one mode or multiple
    if (newMode.any{ it == evt.value } || newMode == evt.value) {
	def delay = (falseAlarmThreshold != null && falseAlarmThreshold != "") ? falseAlarmThreshold * 60 : 2 * 60 
    runIn(delay, "checkDoor")
    }
}

def checkDoor(evt) {
if(allOk){
log.debug("checkDoor")
    def openContacts1 = contacts1.findAll { it?.latestValue("contact") == 'open' }
    def openContacts2 = contacts2.findAll { it?.latestValue("contact") == 'open' }

   	if (openContacts1 && openContacts2){
    	if (openContacts && openLocks){
    		def message = "ALERT: ${openContacts.join(', ')} and ${openLocks.join(', ')} are open"
            sendUnsecure(message)
        }
    }

    else if (!openContacts && !openLocks){
    	def message = "Both sets of doors are closed"
        sendSecure(message)
   }    
}  
}

private sendSecure(msg) {
log.debug("checking push")
  if(sendPushSecure != "No"){
    if (!phone || pushAndPhone != "No") {
		log.debug "sending push"
		sendPush(msg)
	}
	if (phone) {
		log.debug "sending SMS"
		sendSms(phone, msg)
	}
  }
  
  else {
  log.debug("Home is secure but settings don't require push")
}
  log.debug(msg)
}

private sendUnsecure(msg) {
log.debug("checking push")
  if(sendPushUnsecure != "No") {
    log.debug("Sending push message")
    if (!phone || pushAndPhone != "No") {
		log.debug "sending push"
		sendPush(msg)
	}
	if (phone) {
		log.debug "sending SMS"
		sendSms(phone, msg)
	}
  }
  else {
  log.debug("Home is unseecure but settings don't require push")
  }
  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
}

#6

Wow! Thanks for the effort! Never expected anyone to go to such lengths. Unfortunately nothing happened. I left every door open for 6 minutes and nada.


(Tim Slagle) #7

This alerts on mode change. I just assumed that’s what you wanted. Let me know exactly what you want when you want it to alert and what the exact scenario is. The more detail the better.


#8

If I’m working in the yard I’ll have the garage door open to get at my tools and occasionally leave the door into the house open when I go inside to get something or grab a drink making it possible for my indoor cats to get outside. So I want a 1 or 2 minute alert that the house door and one of the garage doors are simultaneously open. Any good resources for learning more about Groovy? I’m really hoping to learn as I add devices and expand the capabilities of my home.


(Tim Slagle) #9

Got ya now. I’ll get something going :smile:


(James haywood) #10

Hi,

I can’t understand why this isnt natively supported by SmartThings?

Im trying to create a rule so that if I am out and a door opens it switches on a light.

How do I achieve this?!


#11

That is native. Just make sure when your out, you have a mode change to away. Then set an alert to turn on a light when the door sensor is opened, but only while in Away mode.


(Brice; SmartRulesApp.com) #12

Our SmartRules app, coming soon, will be able to do this simple and trigger, @Jhaywood, with no coding at all! The first version won’t be able to do the “this and (that or that)” from the original post, but we’ll think about how to work that into the next version. http://smartrulesapp.com


(Brice; SmartRulesApp.com) #13

Actually, you could do the original scenario, you’d just need to use two separate rules.


(James haywood) #14

@Qwertypo O.K I’ll set it up like that for the time being.

@obycode That sounds great, I’ll be sure to check it out when its available.