Modified Ridiculously Automated Garage Door App Debugging


(Marc) #1

Hi - newbie to coding. I am looking to utilize some of the intelligence from the Smart Garage Door app. I want to automatically close my garage door when I manually open it and open and then close my interior garage door. I removed all of the presence/car code, but it doesn’t seem to be working. Nothing shows up in logs either. Code is below. Can anyone see what I am doing wrong?

preferences {

	section("Garage door") {
		input "doorSensor", "capability.contactSensor", title: "Which sensor?"
		input "doorSwitch", "capability.switch", title: "Which switch?"
		input "openThreshold", "number", title: "Warn when open longer than (optional)",description: "Number of minutes", required: false
		input "phone", "phone", title: "Warn with text message (optional)", description: "Phone Number", required: false
	}
	section("Interior door (optional)") {
		input "interiorDoorSensor", "capability.contactSensor", title: "Contact sensor?", required: false
	}
	section("False alarm threshold (defaults to 10 min)") {
		input "falseAlarmThreshold", "number", title: "Number of minutes", required: false
	}
}

def installed() {
	log.trace "installed()"
	subscribe()
}

def updated() {
	log.trace "updated()"
	unsubscribe()
	subscribe()
}

def subscribe() {
	subscribe(doorSensor, "contact", garageDoorContact)

}

	if (interiorDoorSensor) {
		subscribe(interiorDoorSensor, "contact.closed", interiorDoorClosed)
	}

def doorOpenCheck()
{
	final thresholdMinutes = openThreshold
	if (thresholdMinutes) {
		def currentState = doorSensor.contactState
		log.debug "doorOpenCheck"
		if (currentState?.value == "open") {
			log.debug "open for ${now() - currentState.date.time}, openDoorNotificationSent: ${state.openDoorNotificationSent}"
			if (!state.openDoorNotificationSent && now() - currentState.date.time > thresholdMinutes * 60 *1000) {
				def msg = "${doorSwitch.displayName} was been open for ${thresholdMinutes} minutes"
				log.info msg
				sendPush msg
				if (phone) {
					sendSms phone, msg
				}
				state.openDoorNotificationSent = true
			}
		}
		else {
			state.openDoorNotificationSent = false
		}
	}
}


def garageDoorContact(evt)
{
	log.info "garageDoorContact, $evt.name: $evt.value"
	if (evt.value == "open") {
		schedule("0 * * * * ?", "doorOpenCheck")
	}
	else {
		unschedule("doorOpenCheck")
	}
}


def interiorDoorClosed(evt)
{
	log.info "interiorContact, $evt.name: $evt.value"

	// time during which closing the interior door will shut the garage door, if the app opened it
	final threshold = 15 * 60 * 1000
	if (state.appOpenedDoor && now() - state.appOpenedDoor < threshold) {
		state.appOpenedDoor = 0
		closeDoor()
	}
	else {
		log.debug "app didn't open door"
	}
}

private openDoor()
{
	if (doorSensor.currentContact == "closed") {
		log.debug "opening door"
		doorSwitch.on()
	}
}

private closeDoor()
{
	if (doorSensor.currentContact == "open") {
		log.debug "closing door"
		doorSwitch.off()
	}
}

(Chrisb) #2

Okay, the big issue I see is that there isn’t a trigger. You need to subscribe to event from a sensor/device. Then you need to perform a procedure when that event happens.

Do this for me, start a new app and then check out the shared apps. Look for a program called Wireless 3-way in the convenience section. Paste that into your new app. Now, this app is a much simpler app than the Garage Door one, but I really tried to heavily document everything I did in it so it should give you a good idea of the basic parts of an app.


(Marc) #3

Thanks @chrisb . I am struggling to find out where I am going wrong, even after reviewing your documentation and sample app.

I am subscribing to my interior garage door sensor and my garage door sensor:

def subscribe() {
    	subscribe(doorSensor, "contact", garageDoorContact)
    	subscribe(interiorDoorSensor, "contact.closed", interiorDoorClosed)
    }*

I am then checking to see if the interior garage door is opened and if it is, run the close door program which closes the garage door.

def interiorDoorClosed(evt)
{
	log.info "interiorContact, $evt.name: $evt.value"
	// time during which closing the interior door will shut the garage door, if the app opened it
	final threshold = 15 * 60 * 1000
	if (state.appOpenedDoor && now() - state.appOpenedDoor < threshold) {
		state.appOpenedDoor = 0
		closeDoor()
	}
	else {
		log.debug "app didn't open door"
	}
}
private closeDoor()
{
	if (doorSensor.currentContact == "open") {
		log.debug "closing door"
		doorSwitch.off()
	}
}

(Chrisb) #4

It might be this part here:

I want to automatically close my garage door when I manually open it and open and then close my interior garage door.

The problem is that part of that ‘door close procedure’ is this line:

if (state.appOpenedDoor && now() - state.appOpenedDoor < threshold) {
state.appOpenedDoor = 0
closeDoor()
}

I think part of the app you removed was the part that sets the value of the variable state.appOpenedDoor. The app is designed to only work when it opens the door to prevent it from closing the garage door anytime the interior door is opened and closed.

For example, if I’m cutting the lawn, but I’m really hot. So I stop, go in through my garage, open the interior door to get a glass of cool and refreshing lemonade, then go back out and close the door, I don’t want the garage to close on me then! I only want the interior door to trigger the garage door to close if I just came home.

It sounds like you DO want the garage to close in my above situation. You want the interior door closing to always close the garage door. This means that if statement will need to be reworked to remove the flag that checks if the app opened the door.

Unfortunately I’m not 100% sure of exactly what’s going on in that if statement. The variable state.appOpenedDoor seems to be a time frame. I’d have to look back at the original problem to get a better idea. It might be as easy as adding a new procedure to runs whenever the garage door is opened and plugs in the time that that happened as state.appOpenedDoor.


(Marc) #5

Thanks @chrisb. Interesting. I noticed in some of the code I cut out below that basically it is initializing state.appOpenedDoor = now. This is because the Garage Door opened and now its starting the timer for when to check for the interior garage door being opened:

if (doorSensor.currentContact == "closed") {
				openDoor()
				sendPush "Opening garage door due to arrival of ${car.displayName}"
				state.appOpenedDoor = now()
			}
			else {
				log.debug "door already open"
			}
		}

I think by adding state.appOpenedDoor = now() this might work. I have to wait home to see. Thoughts?

def interiorDoorClosed(evt)
{
	log.info "interiorContact, $evt.name: $evt.value"
	// time during which closing the interior door will shut the garage door, if the app opened it
	state.appOpenedDoor = now()
    final threshold = 15 * 60 * 1000
	if (state.appOpenedDoor && now() - state.appOpenedDoor < threshold) {
		state.appOpenedDoor = 0
		closeDoor()
	}
	else {
		log.debug "app didn't open door"
	}
}

(Chrisb) #6

That could work. There’s the whole threshold think in there, but if you’re not using the threshold for anything, it’d be much simpler to just get rid of all that stuff completely. You wouldn’t need the if statement even. You could cut that out along with any reference to state.appOpenedDoor. Your procedure could be a simple as:

def interiorDoorClosed(evt)
{
log.info "interiorContact, $evt.name: $evt.value"
closeDoor()
}

In plain English: If my interior door closes, run the ‘closeDoor()’ procedure.

Now, if you do still want to use the threshold stuff, then you can’t put that “state.appOpenedDoor = now()” in this procedure because doing that will just start the timer when the interior door closes, not when the garage door opened. If you do want to use the threshold (which would actually, help with my example above. If the garage door was left open for more than the threshold, going in and out of the interior door would not close the garage door), then we need to start the time when the garage door is opened. That will be a different procedure.


(Chrisb) #7

Also, just noticed this… in your code you have:

def subscribe() {
	subscribe(doorSensor, "contact", garageDoorContact)
    }
   	if (interiorDoorSensor) {
		subscribe(interiorDoorSensor, "contact.closed", interiorDoorClosed)
	}

That’s not the right syntax. You’ve got some nested stuff going on there with the braces and I think it’s excluding the app from even subscribing to the interior door action. It should be this I think:

def subscribe() {
    	subscribe(doorSensor, "contact", garageDoorContact)
    	if (interiorDoorSensor) {
    		subscribe(interiorDoorSensor, "contact.closed", interiorDoorClosed)
    	}
}

In Plain English:
Line 1: we’re defining the procedure subscribe. The { starts the definition of the procedure
Line 2: we’re subscribing to the action of the garage door sensor open or closing.
Line 3: If the user entered an interior door, then do what ever comes after the {
Line 4: we’re subscribing to the action of the interior door closing.
Line 5: the } closes the ‘If’ statement from line 3.
Line 6: the } closes the procedure definition started in line 1.


(Marc) #8

Thx, this I actually noticed too and fixed to:

def subscribe() {
	subscribe(doorSensor, "contact", garageDoorContact)
	subscribe(interiorDoorSensor, "contact.closed", interiorDoorClosed)
}

(Marc) #9

Thanks. I will give this a shot. I see your point about running in for a quick second and then leaving. Unfortunately, I cannot use a presence sensor to decide I just came home because 90% of the time, my other garage door where I park my car is used and that is tied to my presence sensor.


(Marc) #11

@chrisb So I got it working partially. The only time it seems to close my garage door is if I manually refresh the status of my door in the ST app after it’s been opened. It’s almost as if the app doesn’t auto-refresh and get the door status appropriately. Any ideas?

preferences {
section(“TWhich Garage Door and Interior Garage Door?”){ // Whatever is in the quotes will be displayed to the user.
input “doorSensor”, “capability.contactSensor”, title: "Which Garage sensor?"
input “doorSwitch”, “capability.switch”, title: "Which Garage switch?"
input “openThreshold”, “number”, title: “Warn when open longer than (optional)”,description: “Number of minutes”, required: false
input “interiorDoorSensor”, “capability.contactSensor”, title: “Interior Garage Door?”
}
}

def installed()
{

log.trace "installed()"

subscribe()
}

def updated()
{
log.trace "updated()"
unsubscribe()
subscribe()

}

def subscribe() {
subscribe(doorSensor, “contact”, garageDoorContact)
subscribe(interiorDoorSensor, “contact.closed”, interiorDoorClosed)
}

def garageDoorContact(evt)
{
log.info "garageDoorContact, $evt.name: $evt.value"
if (evt.value == “open”) {
schedule(“0 * * * * ?”, “doorOpenCheck”)
}
else {
unschedule(“doorOpenCheck”)
}
}

def doorOpenCheck()
{
final thresholdMinutes = openThreshold
if (thresholdMinutes) {
def currentState = doorSensor.contactState
log.debug "doorOpenCheck"
if (currentState?.value == “open”) {
log.debug "open for ${now() - currentState.date.time}, openDoorNotificationSent: ${state.openDoorNotificationSent}"
if (!state.openDoorNotificationSent && now() - currentState.date.time > thresholdMinutes * 60 *1000) {
def msg = "${doorSwitch.displayName} was been open for ${thresholdMinutes} minutes"
log.info msg
sendPush msg
if (phone) {
sendSms phone, msg
}
state.openDoorNotificationSent = true
}
}
else {
state.openDoorNotificationSent = false
}
}
}

def interiorDoorClosed(evt)
{
log.info "interiorContact, $evt.name: $evt.value"
if (interiorDoorSensor.currentContact == “closed”) {
closeDoor()
}
}

private closeDoor()
{
if (doorSensor.currentContact == “open”) {
doorSwitch.off()
log.debug "Closing ${doorSwitch.displayName}"
sendPush(“Closing ${doorSwitch.displayName}”)
}
}


(Chrisb) #12
def interiorDoorClosed(evt)
{
log.info "interiorContact, $evt.name: $evt.value"
if (interiorDoorSensor.currentContact == "closed") {
closeDoor()
}
}

Try removing the If-statement in this procedure. You don’t need it because this procedure is only running if the door is closed, so we don’t need to do a current Contact check to see if it’s closed.

It’s possible that this is performing the check before SmartThings is updating the currentContact status and that’s why it doesn’t run the closeDoor() procedure.


MyQ Garage Door Device Type
(Marc) #13

@chrisb Unfortunately that didn’t work either. It actually does run the Door Close procedure, just doesn’t evaluate the current contact sensor as Open. I tried this:

def interiorDoorClosed(evt)
{
    log.info "interiorContact, $evt.name: $evt.value"
    closeDoor()
}

(Chrisb) #14

Okay, I think I misunderstood. Are you saying that it’s tripping the relay to the Garage Door regardless of whether the door is open or closed?


(Art Longoria) #17

Hi, Can anyone help me, I just want the app to open the garage door when I arrive. I installed the original app but it closed and opened at odd times, and I dont want that. I just want it to open when I arrive and know not to open it while im home. Is that possible? Thanks in advance.


#18

Did you ever find what your looking for?