Checking in all the SmartThings apps; both official and third-party.
[smartapps.git] / third-party / Light-Alert-SmartApp.groovy
diff --git a/third-party/Light-Alert-SmartApp.groovy b/third-party/Light-Alert-SmartApp.groovy
new file mode 100755 (executable)
index 0000000..080ae13
--- /dev/null
@@ -0,0 +1,405 @@
+/**
+ *  Smart Bulb Notifier/Flasher
+ *
+ *  Copyright 2015 Scott Gibson
+ *
+ *  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:
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  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.
+ *
+ *  Many thanks to Eric Roberts for his virtual switch creator, which served as the template for creating child switch devices!
+ *
+ */
+definition(
+    name: "Smart Bulb Alert (Blink/Flash)",
+    namespace: "sticks18",
+    author: "Scott Gibson",
+    description: "Creates a virtual switch button that when turned on will trigger selected smart bulbs to blink or flash",
+    category: "My Apps",
+    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
+    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png"
+)
+
+preferences {
+       page(name: "basicInfo")
+       page(name: "configureBulbs")
+}
+
+def basicInfo(){
+       dynamicPage(name: "basicInfo", title: "First, name your trigger and select smart bulb types", nextPage: "configureBulbs", uninstall: true){
+               section("Create Virtual Momentary Button as Trigger") {
+                       input "switchLabel", "text", title: "Switch Button Label", multiple: false, required: true
+               }
+               section("Choose your Smart Bulbs") {
+                       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.",
+            title: "How to select your bulbs...", required: true
+                       input "geLinks", "capability.switch level", title: "Select GE Link Bulbs", required: false, multiple: true
+                       //input "creeCons", "capability.switch level", title: "Select Cree Connected Bulbs", required: false, multiple: true
+                       //input "hueHubs", "capability.switch level", title: "Select Hue Bulbs connected to Hue Hub", required: false, multiple: true
+                       //input "hueDirs", "capability.switch level", title: "Select Hue Bulbs directly connected to ST Hub", required: false, multiple: true
+                       //input "osramLs", "capability.switch level", title: "Select Osram Lightify Bulbs", required: false, multiple: true
+               }
+       }
+}
+
+def configureBulbs(){
+       dynamicPage(name: "configureBulbs", title: "Additional Configuration Options by Bulb Type", install: true, uninstall: true) {
+               section(title: "Auto-off for bulbs directly connected to SmartThings Hub") {
+                       input "autoOff", "bool", title: "Automatically stop the alert", required: false, submitOnChange: true
+                       input "offDelay", "number", title: "Turn off alert after X seconds (default = 5, max = 10)", required: false, submitOnChange: true
+               }
+               /*section(title: "Options for Hue Bulbs connected to Hue Bridge", hidden: hideHueHubBulbs(), hideable: true) {
+                       input "hBlink", "enum", title: "Select Blink for single flash or Breathe for 15 seconds continuous (default = Breathe)", multiple: false, required: false,
+                               options: ["Blink", "Breathe"]
+               }
+               section(title: "Options for Hue Bulbs connected directly to SmartThings Hub", hidden: hideHueDirBulbs(), hideable: true) {
+                       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", 
+                               multiple: false, required: false, options: ["Normal", "Blink", "Breathe", "Okay"] 
+               }
+               section(title: "Options for Osram Lightify Bulbs", hidden: hideOsramBulbs(), hideable: true) {
+                       input "osStyle", "enum", title: "Select alert style: Normal = Bulb will blink until stopped via auto-off or trigger", 
+                               multiple: false, required: false, options: ["Normal"] 
+               }*/
+       }
+}
+
+
+
+def installed() {
+       log.debug "Installed with settings: ${settings}"
+
+       initialize()
+}
+
+def updated() {
+       log.debug "Updated with settings: ${settings}"
+
+       unsubscribe()
+       initialize()
+}
+
+def initialize() {
+    
+    state.autoOff = offDelay
+   // state.hueHubOption = getHueHubOption()
+   // state.hueDirOption = getHueDirOption()
+   // state.osramOption = getOsramOption()
+   // state.onlyHueHub = getHueHubOnly()
+    
+    def deviceId = app.id + "SimulatedSwitch"
+    log.debug(deviceId)
+    def existing = getChildDevice(deviceId)
+    log.debug existing
+    if (!existing) {
+        log.debug "Add child"
+        def childDevice = addChildDevice("sticks18", "Smart Bulb Alert Switch", deviceId, null, [label: switchLabel])
+    }
+    
+}
+
+def uninstalled() {
+    removeChildDevices(getChildDevices())
+}
+
+private removeChildDevices(delete) {
+    delete.each {
+        deleteChildDevice(it.deviceNetworkId)
+    }
+}
+
+/* private getOffDelay() {
+       def result = 5
+    log.debug "autoOff is ${autoOff}"
+       if (autoOff) {
+        result = 5
+        log.debug "offDelay is ${offDelay}"
+               if(offDelay) {
+                       def offSec = Math.Min(offDelay, 10)
+                       offSec = Math.Max(offSec, 1)
+                       result = offSec
+               }
+       }
+       log.debug "off delay: ${result}"
+    return result
+}
+
+private getHueDirOption() {
+       def result = null
+    log.debug hueDirs
+       if (hueDirs) {
+               switch(hdStyle) {
+                       case "Normal":
+                               result = ""
+                               break
+                       case "Blink":
+                               result = "00"
+                               break
+                       case "Breathe":
+                               result = "01"
+                               break
+                       case "Okay":
+                               result = "02"
+                               break
+                       default:
+                               result = ""
+                               break
+               }
+       }
+    log.debug "hue dir option: ${result}"
+    return result
+}
+
+private getHueHubOnly() {
+       (creeCons || geLinks || osramLs || hueDirs) ? false : true
+}
+
+private getHueHubOption() {
+       def result = null
+       if (hueHubs) {
+               switch(hBlink) {
+                       case "Blink":
+                               result = "select"
+                               break
+                       case "Breathe":
+                               result = "lselect"
+                               break
+                       default:
+                               result = "lselect"
+                               break
+               }
+       }
+    log.debug "hue hub option: ${result}"
+    return result
+}
+
+private getOsramOption() {
+       def result = null
+       if (osramLs) {
+               switch(osStyle) {
+                       case "Normal":
+                               result = ""
+                               break
+                       case "Blink":
+                               result = "00"
+                               break
+                       case "Breathe":
+                               result = "01"
+                               break
+                       case "Okay":
+                               result = "02"
+                               break
+                       default:
+                               result = ""
+                               break
+               }
+       }
+    log.debug "osram option: ${result}"
+    return result
+}
+*/
+private hideHueHubBulbs() {
+       (hueHubs) ? false : true
+}
+
+private hideHueDirBulbs() {
+       (hueDirs) ? false : true
+}
+
+private hideOsramBulbs() {
+       (osramLs) ? false : true
+}
+
+private hex(value, width=4) {
+       def s = new BigInteger(Math.round(value).toString()).toString(16)
+       while (s.size() < width) {
+               s = "0" + s
+       }
+       s
+}
+
+private Integer convertHexToInt(hex) {
+       Integer.parseInt(hex,16)
+}
+
+private String swapEndianHex(String hex) {
+    reverseArray(hex.decodeHex()).encodeHex()
+}
+
+private byte[] reverseArray(byte[] array) {
+    int i = 0;
+    int j = array.length - 1;
+    byte tmp;
+    while (j > i) {
+        tmp = array[j];
+        array[j] = array[i];
+        array[i] = tmp;
+        j--;
+        i++;
+    }
+    return array
+}
+
+// Child device methods after this point. Instead of subscribing to child, have child directly call parent
+
+def on(childDevice) {
+       log.debug "Start alert"
+       if(state.autoOff != null) {
+               log.debug "Only alert for ${state.autoOff} seconds"
+               if(geLinks != null) {
+                       geLinks.each { bulb ->
+                               // bulb.setLevel(99, 1800)
+                bulb.alert(state.autoOff)
+                // childDevice.attWrite(bulb.deviceNetworkId, 1, 3, 0, "0x21", state.autoOff)
+                // childDevice.zigbeeCmd(bulb.deviceNetworkId, 1, 3, 0, "")
+                       }
+               }
+               /*if(creeCons != null) {
+                       creeCons.each { bulb ->
+                               childDevice.attWrite(bulb.deviceNetworkId, "10", "3", "0", "0x21", state.autoOff)
+                       }
+               }
+               if(state.hueDirOption != null) {
+                       if(state.hueDirOption == "") {
+                               hueDirs.each { bulb ->
+                                       childDevice.attWrite(bulb.deviceNetworkId, "0B", "3", "0", "0x21", state.autoOff)
+                               }
+                       }
+                       else {
+                               hueDirs.each { bulb ->
+                                       def payload = state.hueDirOption + " 00"
+                                       childDevice.zigbeeCmd(bulb.deviceNetworkId, "0B", "3", "0x40", payload)
+                               }
+                       }
+               }
+               if(state.osramOption != null) {
+                       if(state.osramOption == "") {
+                               osramLs.each { bulb ->
+                                       childDevice.attWrite(bulb.deviceNetworkId, "03", "3", "0", "0x21", state.autoOff)
+                               }
+                       }
+                       else {
+                               osramLs.each { bulb ->
+                                       def payload = state.osramOption + " 00"
+                                       childDevice.zigbeeCmd(bulb.deviceNetworkId, "03", "3", "0x40", payload)
+                               }
+                       }
+               } */
+               childDevice.justOff()
+               
+       } /*
+       else {
+               log.debug "Starting continous alert"
+               if(geLinks != null) {
+                       geLinks.each { bulb ->
+                               childDevice.zigbeeCmd(bulb.deviceNetworkId, "1", "3", "0", "")
+                       }
+               }
+               if(creeCons != null) {
+                       creeCons.each { bulb ->
+                               childDevice.zigbeeCmd(bulb.deviceNetworkId, "10", "3", "0", "")
+                       }
+               }
+               if(state.hueDirOption != null) {
+                       if(state.hueDirOption == "") {
+                               hueDirs.each { bulb ->
+                                       childDevice.zigbeeCmd(bulb.deviceNetworkId, "0B", "3", "0", "")
+                               }
+                       }
+                       else {
+                               hueDirs.each { bulb ->
+                                       def payload = state.hueDirOption + " 00"
+                                       childDevice.zigbeeCmd(bulb.deviceNetworkId, "0B", "3", "0x40", payload)
+                               }
+                       }
+               }
+               if(state.osramOption != null) {
+                       if(state.osramOption == "") {
+                               osramLs.each { bulb ->
+                                       childDevice.zigbeeCmd(bulb.deviceNetworkId, "03", "3", "0", "")
+                               }
+                       }
+                       else {
+                               osramLs.each { bulb ->
+                                       def payload = state.osramOption + " 00"
+                                       childDevice.zigbeeCmd(bulb.deviceNetworkId, "03", "3", "0x40", payload)
+                               }
+                       }
+               }       
+       }
+       if(state.hueHubOption != null) {
+               log.debug "Send planned alert to Hue Bulbs via Hue Bridge"
+               hueHubs.each { bulb ->
+                       def hue = bulb.currentValue("hue")
+                       def sat = bulb.currentValue("saturation")
+                       def alert = state.hueHubOption
+                       def value = [hue: hue, saturation: sat, alert: alert]
+                       bulb.setColor(value)
+               }
+               if(state.hueHubOnly) { childDevice.justOff() }
+       }*/
+       
+}
+
+def off(childDevice) {
+       log.debug "Stop Alert" /*
+       if(state.autoOff != null) {
+               childDevice.justOff()
+       }
+       else {
+               log.debug "Stopping continous alert"
+               if(geLinks != null) {
+                       geLinks.each { bulb ->
+                               childDevice.zigbeeCmd(bulb.deviceNetworkId, "1", "3", "0", "")
+                       }
+               }
+               if(creeCons != null) {
+                       creeCons.each { bulb ->
+                               childDevice.zigbeeCmd(bulb.deviceNetworkId, "10", "3", "0", "")
+                       }
+               }
+               if(state.hueDirOption != null) {
+                       if(state.hueDirOption == "") {
+                               hueDirs.each { bulb ->
+                                       childDevice.zigbeeCmd(bulb.deviceNetworkId, "0B", "3", "0", "")
+                               }
+                       }
+               }
+               if(state.osramOption != null) {
+                       if(state.osramOption == "") {
+                               osramLs.each { bulb ->
+                                       childDevice.zigbeeCmd(bulb.deviceNetworkId, "03", "3", "0", "")
+                               }
+                       }
+               }       
+       }
+       */
+}
+
+def allOff(childDevice) {
+       log.debug "Stopping alerts" /*
+       if(geLinks != null) {
+               geLinks.each { bulb ->
+                       childDevice.attWrite(bulb.deviceNetworkId, "1", "3", "0", "0x21", "0100")
+               }
+       }
+       if(creeCons != null) {
+               creeCons.each { bulb ->
+                       childDevice.attWrite(bulb.deviceNetworkId, "10", "3", "0", "0x21", "0100")
+               }
+       }
+       if(hueDirs != null) {
+               hueDirs.each { bulb ->
+                       childDevice.attWrite(bulb.deviceNetworkId, "0B", "3", "0", "0x21", "0100")
+               }
+       }
+       if(osramLs != null) {
+               osramLs.each { bulb ->
+                       childDevice.attWrite(bulb.deviceNetworkId, "03", "3", "0", "0x21", "0100")
+               }
+       } */
+}