You Left It Open SmartApp

Tempted to name it “You Left It Open SmartA$$”

I know some people were tinkering with an app that would notify you if you changed modes and a contact sensor (door or window) was left open. I didn’t see any finished code based on mode, so I finished it myself. Let me know what you guys think.

@brianlees
@chrisb
@lobo5519
@625alex & @gbronzer thanks for getting me close

3 Likes

Just finished this today…

/**
 *  Is my home secure?
 *
 *  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: "Is my home secure?",
    namespace: "tslagle13",
    author: "Tim Slagle",
    description: "Check a set of doors, windows, and locks to see if your home is secure at a certain time or when mode changes.",
    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("When should I check? (once per day)") {
    	input "timeToCheck", "time", title: "When?(Optional)", required: false
    }
    section("Vacation mode: Check every X hours. (minimum every 5 hours)") {
    	input "timeToCheckVacation", "number", title: "How often? (Optional)", required: false
    }
    section("Which doors, windows, and locks should I check?"){
		input "contacts", "capability.contactSensor", title: "Which door(s)?", multiple: true, required: true
        input "locks", "capability.lock", title: "Which lock?", multiple: true, required: false
    }
    section("Notification delay... (defaults to 2 min") {
    	input "falseAlarmThreshold", "decimal", title: "Number of minutes", 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
    }

}



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)
    }
    if (timeToCheck != null) {
    	schedule(timeToCheck, checkDoor)
    }
initializeVacation()
schedule(timeToCheck, checkDoor)    
}

def initializeVacation() {
if (timeToCheckVacation){
    if (timeToCheckVacation > 4)
        // Schedule polling daemon to run every N minutes
        schedule("0 0 0/${timeToCheckVacation} * * ?", checkDoor)
}    
}


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) {
log.debug("checkDoor")
    def openContacts = contacts.findAll { it?.latestValue("contact") == 'open' }
    def openLocks = locks.findAll { it?.latestValue("lock") == 'unlocked' }

   	if (openContacts || openLocks){
    	if (openContacts && openLocks){
    		def message = "ALERT: ${openContacts.join(', ')} and ${openLocks.join(', ')} are unsecure!"
            sendUnsecure(message)

            if (lockAuto != "No"){
            	lockDoors()
            }
        }
        else {
    		def message = "ALERT: ${openContacts.join(', ')} ${openLocks.join(', ')} unsecure!"
            sendUnsecure(message)

            if (lockAuto != "No"){
            	lockDoors()
            }    

        }
    }

    else if (!openContacts && !openLocks){
    	def message = "All doors, windows, and locks are secure"
        sendSecure(message)
   }    
}  

def lockDoors(){
	if (lockAuto == "Yes"){
		locks?.lock()
        if(sendPushUnsecure != "No") {
    		log.debug("Sending push message")
    		if (!phone || pushAndPhone != "No") {
				log.debug "sending push"
				sendPush("${openLocks.join(', ')} now locked.  You're welcome.  Enjoy your day.")
			}
			if (phone) {
				log.debug "sending SMS"
				sendSms(phone, "${openLocks.join(', ')} now locked.  You're welcome.  Enjoy your day.")
			}
        }    
  	}
}    

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

Brian,

Saw your app. I am not by any means a developer, and beoynd cutting and pasting, this is all over my head…

Over the winter, I installed a ST multi sensor, configured it via the Graph website, and changed the device type. I cannot locate the link to recall what I changed it to.

The bottom line was that after that config change on the site, I had the ability to alert me if the garage door was open, and CONTINUE to alert me UNTILL it was closed. ST support must think I lost my mind, as they cannot see any app that does that. It was very similar to the Extreme temp smart app, allowing an interval to be entered in which to alert of the door being open.

Is there any way your app can be tweaked to provide that functionality, which , apparently has been removed since last winter?

THanks,

Brian

I saw an existing app by Gabriele Nizzoli, that worked like a charm. I wonder why ST took this feature out of the stock smart app.

Things like repeated loops and continuous notifications were some of the things that “bogged” down the system. This is why they were removed. For increased stability.

You can imagine it like this. If you were getting one phone call an hour, on your cell, that’d be ok right? You could handle that. Might be a little annoying, but you could handle it. But if you were getting a call on your cell every 32 seconds you’d need to leave some calls unanswered right? Similar idea with a server. The more stuff that comes in the more chance there is for failure.

Makes perfect sense. Thanks for the information. ST tech apparently was unaware of this change in the smart app. This community is great!

1 Like

You could direct this SMS through IFTTT and so some additional notification there perhaps

1 Like