459ac6e610d96c60dfacee9adcada100d80f70fe
[smartapps.git] / official / single-button-controller.groovy
1 /**
2  *   Button Controller
3  *
4  *  Copyright 2014 SmartThings
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7  *  in compliance with the License. You may obtain a copy of the License at:
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
12  *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
13  *  for the specific language governing permissions and limitations under the License.
14  *
15  */
16 definition(name: "Single Button Controller",
17     namespace: "smartthings",
18     author: "SmartThings",
19     description: "Use your Aeon Panic Button to setup events when the button is used",
20     iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
21     iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
22     category: "Reviewers")
23
24 preferences {
25         page(name: "selectButton")
26 }
27
28 def selectButton() {
29         dynamicPage(name: "selectButton", title: "First, select your button device", install: true) {
30                 section {
31                         input "buttonDevice", "device.aeonKeyFob", title: "Button", multiple: false, required: true
32                 }
33         section("Lights") {
34                         input "lights_1_pushed", "capability.switch", title: "Pushed", multiple: true, required: false
35                         input "lights_1_held", "capability.switch", title: "Held", multiple: true, required: false
36                 }
37                 section("Locks") {
38                         input "locks_1_pushed", "capability.lock", title: "Pushed", multiple: true, required: false
39                         input "locks_1_held", "capability.lock", title: "Held", multiple: true, required: false
40                 }
41                 section("Sonos") {
42                         input "sonos_1_pushed", "capability.musicPlayer", title: "Pushed", multiple: true, required: false
43                         input "sonos_1_held", "capability.musicPlayer", title: "Held", multiple: true, required: false
44                 }
45                 section("Modes") {
46                         input "mode_1_pushed", "mode", title: "Pushed", required: false
47                         input "mode_1_held", "mode", title: "Held", required: false
48                 }
49                 def phrases = location.helloHome?.getPhrases()*.label
50                 if (phrases) {
51                         section("Hello Home Actions") {
52                                 log.trace phrases
53                                 input "phrase_1_pushed", "enum", title: "Pushed", required: false, options: phrases
54                                 input "phrase_1_held", "enum", title: "Held", required: false, options: phrases
55                         }
56                 }
57         }
58 }
59
60 def installed() {
61         initialize()
62 }
63
64 def updated() {
65         unsubscribe()
66         initialize()
67 }
68
69 def initialize() {
70         subscribe(buttonDevice, "button", buttonEvent)
71 }
72
73 def configured() {
74         return buttonDevice || buttonConfigured(1)
75 }
76
77 def buttonConfigured(idx) {
78         return settings["lights_$idx_pushed"] ||
79                 settings["locks_$idx_pushed"] ||
80                 settings["sonos_$idx_pushed"] ||
81                 settings["mode_$idx_pushed"]
82 }
83
84 def buttonEvent(evt){
85         def buttonNumber = evt.data // why doesn't jsonData work? always returning [:]
86         def value = evt.value
87         log.debug "buttonEvent: $evt.name = $evt.value ($evt.data)"
88         log.debug "button: $buttonNumber, value: $value"
89
90         def recentEvents = buttonDevice.eventsSince(new Date(now() - 3000)).findAll{it.value == evt.value}
91         log.debug "Found ${recentEvents.size()?:0} events in past 3 seconds"
92
93         executeHandlers(1, value)
94 }
95
96 def executeHandlers(buttonNumber, value) {
97         log.debug "executeHandlers: $buttonNumber - $value"
98
99         def lights = find('lights', buttonNumber, value)
100         if (lights != null) toggle(lights)
101
102         def locks = find('locks', buttonNumber, value)
103         if (locks != null) toggle(locks)
104
105         def sonos = find('sonos', buttonNumber, value)
106         if (sonos != null) toggle(sonos)
107
108         def mode = find('mode', buttonNumber, value)
109         if (mode != null) changeMode(mode)
110
111         def phrase = find('phrase', buttonNumber, value)
112         if (phrase != null) location.helloHome.execute(phrase)
113 }
114
115 def find(type, buttonNumber, value) {
116         def preferenceName = type + "_" + buttonNumber + "_" + value
117         def pref = settings[preferenceName]
118         if(pref != null) {
119                 log.debug "Found: $pref for $preferenceName"
120         }
121
122         return pref
123 }
124
125 def toggle(devices) {
126         log.debug "toggle: $devices = ${devices*.currentValue('switch')}"
127
128         if (devices*.currentValue('switch').contains('on')) {
129                 devices.off()
130         }
131         else if (devices*.currentValue('switch').contains('off')) {
132                 devices.on()
133         }
134         else if (devices*.currentValue('lock').contains('locked')) {
135                 devices.unlock()
136         }
137         else if (devices*.currentValue('lock').contains('unlocked')) {
138                 devices.lock()
139         }
140         else {
141                 devices.on()
142         }
143 }
144
145 def changeMode(mode) {
146         log.debug "changeMode: $mode, location.mode = $location.mode, location.modes = $location.modes"
147
148         if (location.mode != mode && location.modes?.find { it.name == mode }) {
149                 setLocationMode(mode)
150         }
151 }