Merge branch 'master' of ssh://plrg.eecs.uci.edu/home/git/smartthings-infrastructure
[smartthings-infrastructure.git] / Extractor / App1 / App1.groovy
index 0d4c97e23b7b623f0b2f8fd0f4e82e5a8fd2d23f..718d69ef7448d4cbd969f398b17485fc205676e9 100644 (file)
-
 /**
- *  Auto Lock Door
+ *  Copyright 2015 SmartThings
+ *
+ *  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:
  *
- *  Author: Chris Sader (@csader)
- *  Collaborators: @chrisb
- *  Date: 2013-08-21
- *  URL: http://www.github.com/smartthings-users/smartapp.auto-lock-door
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (C) 2013 Chris Sader.
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this
- * software and associated documentation files (the "Software"), to deal in the Software
- * without restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to the following
- * conditions: The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
+ *  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.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
- * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *  Make it So
+ *
+ *  Author: SmartThings
+ *  Date: 2013-03-06
  */
+definition(
+    name: "Make It So",
+    namespace: "smartthings",
+    author: "SmartThings",
+    description: "Saves the states of a specified set switches and thermostat setpoints and restores them at each mode change. To use 1) Set the mode, 2) Change switches and setpoint to where you want them for that mode, and 3) Install or update the app. Changing to that mode or touching the app will set the devices to the saved state.",
+    category: "Convenience",
+    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/light_thermo-switch.png",
+    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/light_thermo-switch@2x.png"
+)
 
-preferences
-{
-    section("When a door unlocks...") {
-        input "lock1", "capability.lock"
-    }
-    section("Lock it how many minutes later?") {
-        input "minutesLater", "number", title: "When?"
-    }
-    section("Lock it only when this door is closed") {
-        input "openSensor", "capability.contactSensor", title: "Where?"
-    }
+preferences {
+       section("Switches") {
+               input "switches", "capability.switch", multiple: true, required: false
+       }
+       section("Thermostats") {
+               input "thermostats", "capability.thermostat", multiple: true, required: false
+       }
+       section("Locks") {
+               input "locks", "capability.lock", multiple: true, required: false
+       }
 }
 
-def installed()
-{
-    log.debug "Auto Lock Door installed. (URL: http://www.github.com/smartthings-users/smartapp.auto-lock-door)"
-    initialize()
+def installed() {
+       subscribe(location, changedLocationMode)
+       subscribe(app, appTouch)
+       saveState()
 }
 
-def updated()
-{
-    unsubscribe()
-    unschedule()
-    log.debug "Auto Lock Door updated."
-    initialize()
+def updated() {
+       unsubscribe()
+       subscribe(location, changedLocationMode)
+       subscribe(app, appTouch)
+       saveState()
 }
 
-def initialize()
+def appTouch(evt)
 {
-    log.debug "Settings: ${settings}"
-    subscribe(lock1, "lock", doorHandler)
-    subscribe(openSensor, "contact.closed", doorClosed)
-    subscribe(openSensor, "contact.open", doorOpen)
+       restoreState(currentMode)
 }
 
-def lockDoor()
+def changedLocationMode(evt)
 {
-    log.debug "Locking Door if Closed"
-    if((openSensor.latestValue("contact") == "closed")){
-       log.debug "Door Closed"
-       lock1.lock()
-    } else {
-       if ((openSensor.latestValue("contact") == "open")) {
-        def delay = minutesLater * 60
-        log.debug "Door open will try again in $minutesLater minutes"
-        runIn( delay, lockDoor )
-        }
-    }
+       restoreState(evt.value)
 }
 
-def doorOpen(evt) {
-    log.debug "Door open reset previous lock task..."
-    unschedule( lockDoor )
-    def delay = minutesLater * 60
-    runIn( delay, lockDoor )
-}
+private restoreState(mode)
+{
+       log.info "restoring state for mode '$mode'"
+       def map = state[mode] ?: [:]
+       switches?.each {
+               def value = map[it.id]
+               if (value?.switch == "on") {
+                       def level = value.level
+                       if (level) {
+                               log.debug "setting $it.label level to $level"
+                               it.setLevel(level)
+                       }
+                       else {
+                               log.debug "turning $it.label on"
+                               it.on()
+                       }
+               }
+               else if (value?.switch == "off") {
+                       log.debug "turning $it.label off"
+                       it.off()
+               }
+       }
 
-def doorClosed(evt) {
-    log.debug "Door Closed"
+       thermostats?.each {
+               def value = map[it.id]
+               if (value?.coolingSetpoint) {
+                       log.debug "coolingSetpoint = $value.coolingSetpoint"
+                       it.setCoolingSetpoint(value.coolingSetpoint)
+               }
+               if (value?.heatingSetpoint) {
+                       log.debug "heatingSetpoint = $value.heatingSetpoint"
+                       it.setHeatingSetpoint(value.heatingSetpoint)
+               }
+       }
+
+       locks?.each {
+               def value = map[it.id]
+               if (value) {
+                       if (value?.locked) {
+                               it.lock()
+                       }
+                       else {
+                               it.unlock()
+                       }
+               }
+       }
 }
 
-def doorHandler(evt)
+
+private saveState()
 {
-    log.debug "Door ${openSensor.latestValue}"
-    log.debug "Lock ${evt.name} is ${evt.value}."
+       def mode = currentMode
+       def map = state[mode] ?: [:]
+
+       switches?.each {
+               map[it.id] = [switch: it.currentSwitch, level: it.currentLevel]
+       }
+
+       thermostats?.each {
+               map[it.id] = [coolingSetpoint: it.currentCoolingSetpoint, heatingSetpoint: it.currentHeatingSetpoint]
+       }
 
-    if (evt.value == "locked") {                  // If the human locks the door then...
-        log.debug "Cancelling previous lock task..."
-        unschedule( lockDoor )                  // ...we don't need to lock it later.
-    }
-    else {                                      // If the door is unlocked then...
-        def delay = minutesLater * 60          // runIn uses seconds
-        log.debug "Re-arming lock in ${minutesLater} minutes (${delay}s)."
-        runIn( delay, lockDoor )                // ...schedule to lock in x minutes.
-    }
+       locks?.each {
+               map[it.id] = [locked: it.currentLock == "locked"]
+       }
+
+       state[mode] = map
+       log.debug "saved state for mode ${mode}: ${state[mode]}"
+       log.debug "state: $state"
+}
+
+private getCurrentMode()
+{
+       location.mode ?: "_none_"
 }