I’m working on a simple SmartApp that just tells me if I left a door open by checking a contact sensor and sending a notification (or two) to my phone. Here’s the code:
/**
* Door Open Too Long
* Send a notification if a door (contact sensor) has been left open for too long,
* followed by an optional second notification.
*
* Author: Joe Angell
*/
preferences {
section("When it opens..."){
input "contact1", "capability.contactSensor"
}
section("For this amount of time...") {
input name: "minutes1", title: "Minutes", type: "number"
}
section("Send second notification after... (optional)") {
input name: "minutes2", title: "Minutes", type: "number", required: false
}
section("Then send this message in a push notification"){
input "messageText", "text", title: "Message Text"
}
section("And as text message to this number (optional)"){
input "phone", "phone", title: "Phone Number", required: false
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
subscribe(contact1, "contact.open", contactOpenHandler)
subscribe(contact1, "contact.closed", contactClosedHandler)
}
def updated(settings) {
log.debug "Updated with settings: ${settings}"
unsubscribe()
subscribe(contact1, "contact.open", contactOpenHandler)
subscribe(contact1, "contact.closed", contactClosedHandler)
}
def contactOpenHandler(evt) {
log.debug "$evt.name: $evt.value: Arming notification for $minutes1 minutes"
unschedule("doNotification1")
unschedule("doNotification2")
runIn(minutes1 * 60, "doNotification1")
}
def contactClosedHandler(evt) {
log.debug "$evt.name: $evt.value: Canceling notification"
unschedule("doNotification1")
unschedule("doNotification2")
}
def sendNotification() {
sendPush(messageText)
if (phone) {
sendSms(phone, messageText)
}
}
def doNotification1(evt) {
log.debug "First notification: $contact1.contact, event $evt"
sendNotification()
unschedule("doNotification1") // Temporary work-around to scheduling bug
if (minutes2) {
log.debug "$evt.name: $evt.value: Arming second notification for $minutes2 minutes"
runIn(minutes2 * 60, "doNotification2")
}
}
def doNotification2(evt) {
log.debug "Second notification: $contact1.contact, event $evt"
sendNotification()
unschedule("doNotification2") // Temporary work-around to scheduling bug
}
I used the Curling Iron and Notify Me When examples to test it.
When run in the simulator with “minutes1” set to 1 with a virtual contact sensor, it seems to take a much longer than one minute for the task to run. It actually takes a really long time for anything to happen (tens of seconds to over a minute), such as registering that I flipped the virtual contact sensor to “closed” and back to “open”.
Here’s the output from a test run. You can see that it took 10 minutes from when runIn() was armed (the “Scheduling ‘doNotification1’” bit) to when it actually triggered (the “First Notification” bit), even though it should have only been 60 seconds. (As an aside, I’m not sure what the “error” at the top of the log is complaining about, exactly.)
12:14:32 PM EDT: error Cannot get property 'name' on null object
12:14:21 PM EDT: trace Deleting scheduled job 'doNotification1' for InstalledSmartApp: 8a68b42c3f434b98013f4d8ecef12ba2
12:14:20 PM EDT: debug First notification: physicalgraph.app.AttributeWrapper@1f006e5d, event null
12:04:43 PM EDT: trace Scheduling 'doNotification1' for InstalledSmartApp: 8a68b42c3f434b98013f4d8ecef12ba2
12:04:35 PM EDT: trace Deleting scheduled job 'doNotification2' for InstalledSmartApp: 8a68b42c3f434b98013f4d8ecef12ba2
12:04:28 PM EDT: trace Deleting scheduled job 'doNotification1' for InstalledSmartApp: 8a68b42c3f434b98013f4d8ecef12ba2
12:04:28 PM EDT: debug contact: open: Arming notification for 1 minutes
12:04:28 PM EDT: trace Deleting scheduled job 'doNotification2' for InstalledSmartApp: 8a68b42c3f434b98013f4d8ecef12ba2
12:04:22 PM EDT: trace Deleting scheduled job 'doNotification1' for InstalledSmartApp: 8a68b42c3f434b98013f4d8ecef12ba2
12:04:22 PM EDT: debug contact: closed: Canceling notification
12:04:16 PM EDT: trace contact.closed from contact1 was provided with contactClosedHandler...creating subscription
12:04:16 PM EDT: trace contact.open from contact1 was provided with contactOpenHandler...creating subscription
12:04:16 PM EDT: trace Door Open Too Long is attempting to unsubscribe from all events
12:04:16 PM EDT: debug Updated with settings: null
Note that timing-related events seem much be much more accurate when installed as an app from my phone, although I didn’t use a stopwatch to see how accurate it is or anything like that. It seems to be an issue specific to the simulator, which makes it difficult to test timing-based code.
I also had some problems with triggering notifications sent from the simulator. It seems to be working OK at the moment, and works fine when the app is running in the real word, but from the simulator it seemed unreliable. I’m going to chalk that up to a problem with an earlier version of my code for now.
Thanks!
– Joe