Update gentle-wake-up.groovy
[smartapps.git] / third-party / Light-Alert-SmartApp.groovy
1 /**
2  *  Smart Bulb Notifier/Flasher
3  *
4  *  Copyright 2015 Scott Gibson
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  *  Many thanks to Eric Roberts for his virtual switch creator, which served as the template for creating child switch devices!
16  *
17  */
18 definition(
19     name: "Smart Bulb Alert (Blink/Flash)",
20     namespace: "sticks18",
21     author: "Scott Gibson",
22     description: "Creates a virtual switch button that when turned on will trigger selected smart bulbs to blink or flash",
23     category: "My Apps",
24     iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
25     iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png"
26 )
27
28 preferences {
29         page(name: "basicInfo")
30         page(name: "configureBulbs")
31 }
32
33 def basicInfo(){
34         dynamicPage(name: "basicInfo", title: "First, name your trigger and select smart bulb types", nextPage: "configureBulbs", uninstall: true){
35                 section("Create Virtual Momentary Button as Trigger") {
36                         input "switchLabel", "text", title: "Switch Button Label", multiple: false, required: true
37                 }
38                 section("Choose your Smart Bulbs") {
39                         paragraph "This SmartApp will work with most zigbee bulbs by directly calling the Identify function built into the hardware. This function is generally run when you first pair a bulb to the hub to let you know it was successful. Different bulbs have different capabilities and/or endpoints to address, so they must be selected separately in this SmartApp. If expanded functionality exists for a particular bulb type, you will be given additional options to select. Caveats: Non-Hue bulbs connected to the Hue Bridge, such as GE Link or Cree Connected, will not work because the Hue API is not designed for them.",
40             title: "How to select your bulbs...", required: true
41                         input "geLinks", "capability.switch level", title: "Select GE Link Bulbs", required: false, multiple: true
42                         //input "creeCons", "capability.switch level", title: "Select Cree Connected Bulbs", required: false, multiple: true
43                         //input "hueHubs", "capability.switch level", title: "Select Hue Bulbs connected to Hue Hub", required: false, multiple: true
44                         //input "hueDirs", "capability.switch level", title: "Select Hue Bulbs directly connected to ST Hub", required: false, multiple: true
45                         //input "osramLs", "capability.switch level", title: "Select Osram Lightify Bulbs", required: false, multiple: true
46                 }
47         }
48 }
49
50 def configureBulbs(){
51         dynamicPage(name: "configureBulbs", title: "Additional Configuration Options by Bulb Type", install: true, uninstall: true) {
52                 section(title: "Auto-off for bulbs directly connected to SmartThings Hub") {
53                         input "autoOff", "bool", title: "Automatically stop the alert", required: false, submitOnChange: true
54                         input "offDelay", "number", title: "Turn off alert after X seconds (default = 5, max = 10)", required: false, submitOnChange: true
55                 }
56                 /*section(title: "Options for Hue Bulbs connected to Hue Bridge", hidden: hideHueHubBulbs(), hideable: true) {
57                         input "hBlink", "enum", title: "Select Blink for single flash or Breathe for 15 seconds continuous (default = Breathe)", multiple: false, required: false,
58                                 options: ["Blink", "Breathe"]
59                 }
60                 section(title: "Options for Hue Bulbs connected directly to SmartThings Hub", hidden: hideHueDirBulbs(), hideable: true) {
61                         input "hdStyle", "enum", title: "Select alert style: Normal = Bulb will blink until stopped via auto-off or trigger, Blink = Single flash, Breathe = Mult Flash for 15 seconds, Okay = Bulb turn green for 2 seconds", 
62                                 multiple: false, required: false, options: ["Normal", "Blink", "Breathe", "Okay"] 
63                 }
64                 section(title: "Options for Osram Lightify Bulbs", hidden: hideOsramBulbs(), hideable: true) {
65                         input "osStyle", "enum", title: "Select alert style: Normal = Bulb will blink until stopped via auto-off or trigger", 
66                                 multiple: false, required: false, options: ["Normal"] 
67                 }*/
68         }
69 }
70
71
72
73 def installed() {
74         log.debug "Installed with settings: ${settings}"
75
76         initialize()
77 }
78
79 def updated() {
80         log.debug "Updated with settings: ${settings}"
81
82         unsubscribe()
83         initialize()
84 }
85
86 def initialize() {
87     
88     state.autoOff = offDelay
89    // state.hueHubOption = getHueHubOption()
90    // state.hueDirOption = getHueDirOption()
91    // state.osramOption = getOsramOption()
92    // state.onlyHueHub = getHueHubOnly()
93     
94     def deviceId = app.id + "SimulatedSwitch"
95     log.debug(deviceId)
96     def existing = getChildDevice(deviceId)
97     log.debug existing
98     if (!existing) {
99         log.debug "Add child"
100         def childDevice = addChildDevice("sticks18", "Smart Bulb Alert Switch", deviceId, null, [label: switchLabel])
101     }
102     
103 }
104
105 def uninstalled() {
106     removeChildDevices(getChildDevices())
107 }
108
109 private removeChildDevices(delete) {
110     delete.each {
111         deleteChildDevice(it.deviceNetworkId)
112     }
113 }
114
115 /* private getOffDelay() {
116         def result = 5
117     log.debug "autoOff is ${autoOff}"
118         if (autoOff) {
119         result = 5
120         log.debug "offDelay is ${offDelay}"
121                 if(offDelay) {
122                         def offSec = Math.Min(offDelay, 10)
123                         offSec = Math.Max(offSec, 1)
124                         result = offSec
125                 }
126         }
127         log.debug "off delay: ${result}"
128     return result
129 }
130
131 private getHueDirOption() {
132         def result = null
133     log.debug hueDirs
134         if (hueDirs) {
135                 switch(hdStyle) {
136                         case "Normal":
137                                 result = ""
138                                 break
139                         case "Blink":
140                                 result = "00"
141                                 break
142                         case "Breathe":
143                                 result = "01"
144                                 break
145                         case "Okay":
146                                 result = "02"
147                                 break
148                         default:
149                                 result = ""
150                                 break
151                 }
152         }
153     log.debug "hue dir option: ${result}"
154     return result
155 }
156
157 private getHueHubOnly() {
158         (creeCons || geLinks || osramLs || hueDirs) ? false : true
159 }
160
161 private getHueHubOption() {
162         def result = null
163         if (hueHubs) {
164                 switch(hBlink) {
165                         case "Blink":
166                                 result = "select"
167                                 break
168                         case "Breathe":
169                                 result = "lselect"
170                                 break
171                         default:
172                                 result = "lselect"
173                                 break
174                 }
175         }
176     log.debug "hue hub option: ${result}"
177     return result
178 }
179
180 private getOsramOption() {
181         def result = null
182         if (osramLs) {
183                 switch(osStyle) {
184                         case "Normal":
185                                 result = ""
186                                 break
187                         case "Blink":
188                                 result = "00"
189                                 break
190                         case "Breathe":
191                                 result = "01"
192                                 break
193                         case "Okay":
194                                 result = "02"
195                                 break
196                         default:
197                                 result = ""
198                                 break
199                 }
200         }
201     log.debug "osram option: ${result}"
202     return result
203 }
204 */
205 private hideHueHubBulbs() {
206         (hueHubs) ? false : true
207 }
208
209 private hideHueDirBulbs() {
210         (hueDirs) ? false : true
211 }
212
213 private hideOsramBulbs() {
214         (osramLs) ? false : true
215 }
216
217 private hex(value, width=4) {
218         def s = new BigInteger(Math.round(value).toString()).toString(16)
219         while (s.size() < width) {
220                 s = "0" + s
221         }
222         s
223 }
224
225 private Integer convertHexToInt(hex) {
226         Integer.parseInt(hex,16)
227 }
228
229 private String swapEndianHex(String hex) {
230     reverseArray(hex.decodeHex()).encodeHex()
231 }
232
233 private byte[] reverseArray(byte[] array) {
234     int i = 0;
235     int j = array.length - 1;
236     byte tmp;
237     while (j > i) {
238         tmp = array[j];
239         array[j] = array[i];
240         array[i] = tmp;
241         j--;
242         i++;
243     }
244     return array
245 }
246
247 // Child device methods after this point. Instead of subscribing to child, have child directly call parent
248
249 def on(childDevice) {
250         log.debug "Start alert"
251         if(state.autoOff != null) {
252                 log.debug "Only alert for ${state.autoOff} seconds"
253                 if(geLinks != null) {
254                         geLinks.each { bulb ->
255                                 // bulb.setLevel(99, 1800)
256                 bulb.alert(state.autoOff)
257                 // childDevice.attWrite(bulb.deviceNetworkId, 1, 3, 0, "0x21", state.autoOff)
258                 // childDevice.zigbeeCmd(bulb.deviceNetworkId, 1, 3, 0, "")
259                         }
260                 }
261                 /*if(creeCons != null) {
262                         creeCons.each { bulb ->
263                                 childDevice.attWrite(bulb.deviceNetworkId, "10", "3", "0", "0x21", state.autoOff)
264                         }
265                 }
266                 if(state.hueDirOption != null) {
267                         if(state.hueDirOption == "") {
268                                 hueDirs.each { bulb ->
269                                         childDevice.attWrite(bulb.deviceNetworkId, "0B", "3", "0", "0x21", state.autoOff)
270                                 }
271                         }
272                         else {
273                                 hueDirs.each { bulb ->
274                                         def payload = state.hueDirOption + " 00"
275                                         childDevice.zigbeeCmd(bulb.deviceNetworkId, "0B", "3", "0x40", payload)
276                                 }
277                         }
278                 }
279                 if(state.osramOption != null) {
280                         if(state.osramOption == "") {
281                                 osramLs.each { bulb ->
282                                         childDevice.attWrite(bulb.deviceNetworkId, "03", "3", "0", "0x21", state.autoOff)
283                                 }
284                         }
285                         else {
286                                 osramLs.each { bulb ->
287                                         def payload = state.osramOption + " 00"
288                                         childDevice.zigbeeCmd(bulb.deviceNetworkId, "03", "3", "0x40", payload)
289                                 }
290                         }
291                 } */
292                 childDevice.justOff()
293                 
294         } /*
295         else {
296                 log.debug "Starting continous alert"
297                 if(geLinks != null) {
298                         geLinks.each { bulb ->
299                                 childDevice.zigbeeCmd(bulb.deviceNetworkId, "1", "3", "0", "")
300                         }
301                 }
302                 if(creeCons != null) {
303                         creeCons.each { bulb ->
304                                 childDevice.zigbeeCmd(bulb.deviceNetworkId, "10", "3", "0", "")
305                         }
306                 }
307                 if(state.hueDirOption != null) {
308                         if(state.hueDirOption == "") {
309                                 hueDirs.each { bulb ->
310                                         childDevice.zigbeeCmd(bulb.deviceNetworkId, "0B", "3", "0", "")
311                                 }
312                         }
313                         else {
314                                 hueDirs.each { bulb ->
315                                         def payload = state.hueDirOption + " 00"
316                                         childDevice.zigbeeCmd(bulb.deviceNetworkId, "0B", "3", "0x40", payload)
317                                 }
318                         }
319                 }
320                 if(state.osramOption != null) {
321                         if(state.osramOption == "") {
322                                 osramLs.each { bulb ->
323                                         childDevice.zigbeeCmd(bulb.deviceNetworkId, "03", "3", "0", "")
324                                 }
325                         }
326                         else {
327                                 osramLs.each { bulb ->
328                                         def payload = state.osramOption + " 00"
329                                         childDevice.zigbeeCmd(bulb.deviceNetworkId, "03", "3", "0x40", payload)
330                                 }
331                         }
332                 }       
333         }
334         if(state.hueHubOption != null) {
335                 log.debug "Send planned alert to Hue Bulbs via Hue Bridge"
336                 hueHubs.each { bulb ->
337                         def hue = bulb.currentValue("hue")
338                         def sat = bulb.currentValue("saturation")
339                         def alert = state.hueHubOption
340                         def value = [hue: hue, saturation: sat, alert: alert]
341                         bulb.setColor(value)
342                 }
343                 if(state.hueHubOnly) { childDevice.justOff() }
344         }*/
345         
346 }
347
348 def off(childDevice) {
349         log.debug "Stop Alert" /*
350         if(state.autoOff != null) {
351                 childDevice.justOff()
352         }
353         else {
354                 log.debug "Stopping continous alert"
355                 if(geLinks != null) {
356                         geLinks.each { bulb ->
357                                 childDevice.zigbeeCmd(bulb.deviceNetworkId, "1", "3", "0", "")
358                         }
359                 }
360                 if(creeCons != null) {
361                         creeCons.each { bulb ->
362                                 childDevice.zigbeeCmd(bulb.deviceNetworkId, "10", "3", "0", "")
363                         }
364                 }
365                 if(state.hueDirOption != null) {
366                         if(state.hueDirOption == "") {
367                                 hueDirs.each { bulb ->
368                                         childDevice.zigbeeCmd(bulb.deviceNetworkId, "0B", "3", "0", "")
369                                 }
370                         }
371                 }
372                 if(state.osramOption != null) {
373                         if(state.osramOption == "") {
374                                 osramLs.each { bulb ->
375                                         childDevice.zigbeeCmd(bulb.deviceNetworkId, "03", "3", "0", "")
376                                 }
377                         }
378                 }       
379         }
380         */
381 }
382
383 def allOff(childDevice) {
384         log.debug "Stopping alerts" /*
385         if(geLinks != null) {
386                 geLinks.each { bulb ->
387                         childDevice.attWrite(bulb.deviceNetworkId, "1", "3", "0", "0x21", "0100")
388                 }
389         }
390         if(creeCons != null) {
391                 creeCons.each { bulb ->
392                         childDevice.attWrite(bulb.deviceNetworkId, "10", "3", "0", "0x21", "0100")
393                 }
394         }
395         if(hueDirs != null) {
396                 hueDirs.each { bulb ->
397                         childDevice.attWrite(bulb.deviceNetworkId, "0B", "3", "0", "0x21", "0100")
398                 }
399         }
400         if(osramLs != null) {
401                 osramLs.each { bulb ->
402                         childDevice.attWrite(bulb.deviceNetworkId, "03", "3", "0", "0x21", "0100")
403                 }
404         } */
405