From ab9d735cfdc383797e7a6807cf18882c6066f6c0 Mon Sep 17 00:00:00 2001 From: rtrimana Date: Fri, 20 Jul 2018 11:23:39 -0700 Subject: [PATCH] Adding more official apps gotten from https://github.com/SmartThingsCommunity/Code --- ...ights-and-locks-with-contact-sensor.groovy | 69 ++++++++ ...ontrol-devices-with-an-HTTP-request.groovy | 69 ++++++++ official/03-sms-to-hue.groovy | 115 +++++++++++++ official/04-weatherunderground-connect.groovy | 112 +++++++++++++ official/Contact_Activated_Lighting.groovy | 50 ++++++ official/Light_Rule.groovy | 110 +++++++++++++ .../control-switch-with-contact-sensor.groovy | 59 +++++++ official/grannys-faucet.groovy | 100 ++++++++++++ official/hue-minimote.groovy | 153 ++++++++++++++++++ official/page-params-by-href.groovy | 144 +++++++++++++++++ official/restful-switch.groovy | 119 ++++++++++++++ official/turn-on-at-sunset.groovy | 48 ++++++ official/turn-on-before-sunset.groovy | 70 ++++++++ official/turn-on-by-zip-code.groovy | 84 ++++++++++ official/tweet-to-hue.groovy | 134 +++++++++++++++ official/web-services-smartapp.groovy | 79 +++++++++ official/wunderground-pws-connect.groovy | 99 ++++++++++++ 17 files changed, 1614 insertions(+) create mode 100644 official/01-control-lights-and-locks-with-contact-sensor.groovy create mode 100644 official/02-control-devices-with-an-HTTP-request.groovy create mode 100644 official/03-sms-to-hue.groovy create mode 100644 official/04-weatherunderground-connect.groovy create mode 100644 official/Contact_Activated_Lighting.groovy create mode 100644 official/Light_Rule.groovy create mode 100644 official/control-switch-with-contact-sensor.groovy create mode 100644 official/grannys-faucet.groovy create mode 100644 official/hue-minimote.groovy create mode 100644 official/page-params-by-href.groovy create mode 100644 official/restful-switch.groovy create mode 100644 official/turn-on-at-sunset.groovy create mode 100644 official/turn-on-before-sunset.groovy create mode 100644 official/turn-on-by-zip-code.groovy create mode 100644 official/tweet-to-hue.groovy create mode 100644 official/web-services-smartapp.groovy create mode 100644 official/wunderground-pws-connect.groovy diff --git a/official/01-control-lights-and-locks-with-contact-sensor.groovy b/official/01-control-lights-and-locks-with-contact-sensor.groovy new file mode 100644 index 0000000..7099bcb --- /dev/null +++ b/official/01-control-lights-and-locks-with-contact-sensor.groovy @@ -0,0 +1,69 @@ +/** + * Example: Control a switch with a contact sensor + * + * Copyright 2014 Andrew Mager + * + * 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. + * + */ +definition( + name: "Example: Control a switch and lock with a contact sensor", + namespace: "com.smarthings.developers", + author: "Andrew Mager & Kris Schaller", + description: "Using a contact sensor, control a switch and a lock.", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png") + + +// This is where a user will select devices to be used by this SmartApp +preferences { + // You can create multiple sections to organize the configuration fields of your SmartApp + section(title: "Select Devices") { + // Inputs assign variables to a group of physical devices + input "contact", "capability.contactSensor", title: "Select a contact sensor", multiple: false + input "light", "capability.switch", title: "Select a light or outlet", required: true + } +} + +// This function runs when the SmartApp is installed +def installed() { + // This is a standard debug statement in Groovy + log.debug "Installed with settings: ${settings}" + initialize() +} + +// This function runs when the SmartApp has been updated +def updated() { + log.debug "Updated with settings: ${settings}" + // Notice that all event subscriptions are removed when a SmartApp is updated + unsubscribe() + initialize() +} + +// This function is where you initialize callbacks for event listeners +def initialize() { + // The subscribe function takes a input, a state, and a callback method + subscribe(contact, "contact.open", openHandler) + subscribe(contact, "contact.closed", closedHandler) +} + +// These are our callback methods +def openHandler(evt) { + log.debug "$evt.name: $evt.value" + // Turn the light on + light.on() +} + +def closedHandler(evt) { + log.debug "$evt.name: $evt.value" + // Turn the light off and lock the lock + light.off() +} diff --git a/official/02-control-devices-with-an-HTTP-request.groovy b/official/02-control-devices-with-an-HTTP-request.groovy new file mode 100644 index 0000000..4968621 --- /dev/null +++ b/official/02-control-devices-with-an-HTTP-request.groovy @@ -0,0 +1,69 @@ +/** + * Example: Control a switch with a contact sensor + * + * 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: + * + * 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. + * + */ +definition( + name: "Example: Control a device with an API call", + namespace: "com.smarthings.developers", + author: "Andrew Mager & Kris Schaller", + description: "Make an HTTP request to a SmartApp to control devices.", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png") + + +preferences { + section(title: "Select Devices") { + input "light", "capability.switch", title: "Select a light or outlet", required: true, multiple:false + } +} + +// Since the SmartApp doesn't have any dependencies when it's installed or updated, +// we don't need to worry about those states. +def installed() {} +def updated() {} + + +// This block defines an endpoint, and which functions will fire depending on which type +// of HTTP request you send +mappings { + // The path is appended to the endpoint to make requests + path("/switch") { + // These actions link HTTP verbs to specific callback functions in your SmartApp + action: [ + GET: "getSwitch", // "When an HTTP GET request is received, run getSwitch()" + PUT: "setSwitch" + ] + } +} + + +// Callback functions +def getSwitch() { + // This returns the current state of the switch in JSON + return light.currentState("switch") +} + +def setSwitch() { + switch(request.JSON.value) { + case "on": + light.on(); + break; + case "off": + light.off(); + break; + default: + break; + } +} diff --git a/official/03-sms-to-hue.groovy b/official/03-sms-to-hue.groovy new file mode 100644 index 0000000..f244b9c --- /dev/null +++ b/official/03-sms-to-hue.groovy @@ -0,0 +1,115 @@ +/** + * [Workshop Demo] SMS to Hue + * + * Copyright 2015 Andrew Mager + * + * 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. + * + */ +definition( + name: "[Workshop Demo] SMS to Hue", + namespace: "com.smartthings.dev", + author: "Andrew Mager", + description: "Change the color of Hue bulbs from an SMS.", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + oauth: true) + + +preferences { + section("Control these hue bulbs...") { + input "hues", "capability.colorControl", title: "Which Hue Bulbs?", required:false, multiple:true + } +} + + +// This block defines an endpoint, and which functions will fire depending on which type +// of HTTP request you send +mappings { + // The path is appended to the endpoint to make request + path("/hue") { + action: [ + PUT: "postHue" + ] + } +} + + +def installed() {} +def updated() {} + + + +/* + This function receives a JSON payload and parses out the color from a tweet. + For example, someone tweets, "@SmartThingsDev #IoTWorld2015 color=blue". Then it sends the + correct color as a string to setHueColor(). +*/ +def postHue() { + /* + "request.JSON?" checks to make sure that the object exists. And ".text" is the + key for the value that we're looking for. It's the body of the tweet. + */ + def color = (request.JSON?.value).toLowerCase() + + try { + // Finds the text "color=[colorname]" and parses out the color name + setHueColor(color) + } + catch (any) { + log.trace "Something went wrong." + } +} + + +// This function takes a String of text and associates it with an Integer value for the color. +private setHueColor(color) { + + // Initaliaze values for hue, saturation, and level + def hueColor = 0 + def saturation = 100 + def level = 100 + + switch(color) { + case "white": + hueColor = 52 + saturation = 19 + break; + case "blue": + hueColor = 70 + break; + case "green": + hueColor = 39 + break; + case "yellow": + hueColor = 25 + break; + case "orange": + hueColor = 10 + break; + case "purple": + hueColor = 75 + break; + case "pink": + hueColor = 83 + break; + case "red": + hueColor = 100 + break; + } + + // Set the new value of hue, saturation, and level + def newValue = [hue: hueColor, saturation: saturation, level: level] + + // Update each Hue bulb with the new values + hues*.setColor(newValue) +} diff --git a/official/04-weatherunderground-connect.groovy b/official/04-weatherunderground-connect.groovy new file mode 100644 index 0000000..f927708 --- /dev/null +++ b/official/04-weatherunderground-connect.groovy @@ -0,0 +1,112 @@ +/** + * Weather Underground PWS Connect + * + * Copyright 2015 Andrew Mager + * + * 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. + * + */ + +// This imports the Java class "DecimalFormat" +import java.text.DecimalFormat + +definition( + name: "Weather Underground PWS Connect", + namespace: "co.mager", + author: "Andrew Mager", + description: "Connect your SmartSense Temp/Humidity sensor to your Weather Underground Personal Weather Station.", + category: "Green Living", + iconUrl: "http://i.imgur.com/HU0ANBp.png", + iconX2Url: "http://i.imgur.com/HU0ANBp.png", + iconX3Url: "http://i.imgur.com/HU0ANBp.png", + oauth: true) + + +preferences { + section("Select a sensor") { + input "temp", "capability.temperatureMeasurement", title: "Temperature", required: true + input "humidity", "capability.relativeHumidityMeasurement", title: "Humidity", required: true + } + section("Configure your Weather Underground credentials") { + input "weatherID", "text", title: "Weather Station ID", required: true + input "password", "password", title: "Weather Underground password", required: true + } +} + +def installed() { + log.debug "Installed with settings: ${settings}" + initialize() +} + + +def updated() { + log.debug "Updated with settings: ${settings}" + unsubscribe() + initialize() +} + + +def initialize() { + + /* + Check to see if the sensor is reporting temperature, then run the updateCurrentWeather + every 10 minutes + */ + if (temp.currentTemperature) { + runEvery5Minutes(updateCurrentWeather) + } +} + + +/* + Updates the Weather Underground Personal Weather Station (PWS) Upload Protocol + Reference: http://wiki.wunderground.com/index.php/PWS_-_Upload_Protocol +*/ +def updateCurrentWeather() { + + // Logs of the current data from the sensor + log.trace "Temp: " + temp.currentTemperature + log.trace "Humidity: " + humidity.currentHumidity + log.trace "Dew Point: " + calculateDewPoint(temp.currentTemperature, humidity.currentHumidity) + + // Builds the URL that will be sent to Weather Underground to update your PWS + def params = [ + uri: "http://weatherstation.wunderground.com", + path: "/weatherstation/updateweatherstation.php", + query: [ + "ID": weatherID, + "PASSWORD": password, + "dateutc": "now", + "tempf": temp.currentTemperature, + "humidity": humidity.currentHumidity, + "dewptf": calculateDewPoint(temp.currentTemperature, humidity.currentHumidity), + "action": "updateraw", + "softwaretype": "SmartThings" + ] + ] + + try { + // Make the HTTP request using httpGet() + httpGet(params) { resp -> // This is how we define the "return data". Can also use $it. + log.debug "response data: ${resp.data}" + } + } catch (e) { + log.error "something went wrong: $e" + } + +} + +// Calculates dewpoint based on temperature and humidity +def calculateDewPoint(t, rh) { + def dp = 243.04 * ( Math.log(rh / 100) + ( (17.625 * t) / (243.04 + t) ) ) / (17.625 - Math.log(rh / 100) - ( (17.625 * t) / (243.04 + t) ) ) + // Format the response for Weather Underground + return new DecimalFormat("##.##").format(dp) +} + diff --git a/official/Contact_Activated_Lighting.groovy b/official/Contact_Activated_Lighting.groovy new file mode 100644 index 0000000..5e210ee --- /dev/null +++ b/official/Contact_Activated_Lighting.groovy @@ -0,0 +1,50 @@ +/** + * Contact Activated Lighting + * + * Copyright 2016 Tim Slagle + * + * 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. + * + */ +definition( + name: "Contact Activated Lighting", + namespace: "tslagle13", + author: "Tim Slagle", + description: "Create child apps that will use a contact sensor to turn on lights.", + category: "Convenience", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png") + + +preferences { + page(name: "mainPage", title: "Child Apps", install: true, uninstall: true) { + section { + app(name: "childRule", appName: "Light Rule", namespace: "tslagle13", title: "New Lighting Rule", multiple: true) + } + } +} + +def installed() { + log.debug "Installed with settings: ${settings}" + + initialize() +} + +def updated() { + log.debug "Updated with settings: ${settings}" + + unsubscribe() + initialize() +} + +def initialize() { + // TODO: subscribe to attributes, devices, locations, etc. +} \ No newline at end of file diff --git a/official/Light_Rule.groovy b/official/Light_Rule.groovy new file mode 100644 index 0000000..d9c090f --- /dev/null +++ b/official/Light_Rule.groovy @@ -0,0 +1,110 @@ +/** + * Light Rule + * + * Copyright 2016 Tim Slagle + * + * 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. + * + */ +definition( + name: "Light Rule", + namespace: "tslagle13", + author: "Tim Slagle", + description: "Light rule child app for \"Motion Activated Light\"", + category: "Convenience", + parent: "tslagle13:Contact Activated Lighting", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png") + + +preferences { + page name: "mainPage", title: "Automate Lights & Switches", install: false, uninstall: true, nextPage: "namePage" + page name: "namePage", title: "Automate Lights & Switches", install: true, uninstall: true +} + +def mainPage() { + dynamicPage(name: "mainPage") { + section("Which contact sensor?") { + input "contactSensor", "capability.contactSensor", title: "Which contact sensor(s)?", multiple: true + } + section("Which light would you like to turn on?") { + input "light", "capability.switch", title: "Which light?", multiple: true + } + section("Extras") { + input "contactInactive", "bool", title: "Turn off if contacts closes?", submitOnChange: true + if (contactInactive) { + input "delay", "number", title: "After how many seconds?", required: false + } + } + } +} + +def namePage() { + if (!overrideLabel) { + // if the user selects to not change the label, give a default label + def l = "$contactSensor turns on $light" + log.debug "will set default label of $l" + app.updateLabel(l) + } + dynamicPage(name: "namePage") { + if (overrideLabel) { + section("Automation name") { + label title: "Enter custom name", defaultValue: app.label, required: false + } + } else { + section("Automation name") { + paragraph app.label + } + } + section { + input "overrideLabel", "bool", title: "Edit automation name", defaultValue: "false", required: "false", submitOnChange: true + } + } +} + +def installed() { + log.debug "Installed with settings: ${settings}" + + initialize() +} + +def updated() { + log.debug "Updated with settings: ${settings}" + + unsubscribe() + initialize() +} + +def initialize() { + subscribe (contactSensor, "contact" , contactHandler) +} + +def contactHandler(evt){ + log.debug evt.name + log.debug evt.value + log.debug evt.date + log.debug evt.isStateChange() + + if (evt.value == "open") { + turnLightOn() + } + else if (contactInactive) { + runIn(delay , turnLightOff) + } +} + +def turnLightOn() { + light.on() +} + +def turnLightOff() { + light.off() +} diff --git a/official/control-switch-with-contact-sensor.groovy b/official/control-switch-with-contact-sensor.groovy new file mode 100644 index 0000000..e81d1a6 --- /dev/null +++ b/official/control-switch-with-contact-sensor.groovy @@ -0,0 +1,59 @@ +/** + * Example: Control a switch with a contact sensor + * + * Copyright 2015 Andrew Mager + * + * 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. + * + */ +definition( + name: "Example: Control a switch with a contact sensor", + namespace: "com.smarthings.dev", + author: "Andrew Mager", + description: "Using a contact sensor, control a switch.", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png") + + +preferences { + section("Select Devices") { + input "contact", "capability.contactSensor", title: "Select a contact sensor", multiple: false + input "light", "capability.switch", title: "Select a light or outlet" + } +} + +def installed() { + log.debug "Installed with settings: ${settings}" + initialize() +} + +def updated() { + log.debug "Updated with settings: ${settings}" + unsubscribe() + initialize() +} + +def initialize() { + subscribe contact, "contact.open", openHandler + subscribe contact, "contact.closed", closedHandler +} + +def openHandler(evt) { + log.debug "$evt.name: $evt.value" + light.on() +} + +def closedHandler(evt) { + log.debug "$evt.name: $evt.value" + light.off() +} + +// TODO: implement event handlers diff --git a/official/grannys-faucet.groovy b/official/grannys-faucet.groovy new file mode 100644 index 0000000..7307da9 --- /dev/null +++ b/official/grannys-faucet.groovy @@ -0,0 +1,100 @@ +/** + * Granny's Faucet + * Notifies you when Granny is up and running + * Let you know when she hasn't been around so you can check in on her + * + * Copyright 2015 SmartThings Hack + * + * 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. + * + */ +definition( + name: "Granny's Faucet", + namespace: "com.firstbuild", + author: "SmartThings Hack", + description: "Check to see if Granny used the faucet in a 24 hour period and send a notification if she does.", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png") + + +preferences { + section("Which Faucets?") { + input "faucet", "capability.accelerationSensor", title: "Which faucet?", required:true + } + section("Who to text") { + input "phone", "phone", title: "Phone number?", required: true + } + section("How often do you want grandma to check in?") { + input "minutes", "number", title: "Delay in minutes before we notify you", defaultValue: 1 + } +} + +def installed() { + log.trace "Installed with settings: ${settings}" + initialize() +} + +def updated() { + log.trace "Updated with settings: ${settings}" + state.lastOpened= [date:now()] // now() is ms time built into SmartApps + log.debug "Last Updated Date: $state.lastOpened.date" + + unsubscribe() + initialize() +} + +def initialize() { + subscribe(faucet, "acceleration.active", faucetActiveHandler) + subscribe(faucet, "acceleration.inactive", faucetInactiveHandler) +} + +def faucetInactiveHandler(evt) { + log.trace "#faucetClosedHandler#" + def inputSeconds = 60*minutes.toInteger() + log.debug "waiting...$inputSeconds" + runIn(inputSeconds, alertMe) +} + +def faucetActiveHandler(evt) { + // Don't send a continuous stream of text messages + def inputSeconds = 60*minutes.toInteger() + def deltaSeconds = inputSeconds + def timeAgo = new Date(now() - (1000 * deltaSeconds)) // 61 seconds ago + def recentEvents = faucet.eventsSince(timeAgo) + log.trace "Found ${recentEvents?.size() ?: 0} events in the last $deltaSeconds seconds" + log.debug "Recent Events $recentEvents.value" + def alreadySentSms = recentEvents.count { + it.value && it.value == "active" + } > 1 + + if (alreadySentSms) { + log.debug "SMS already sent to $phone1 within the last $minutes minute" + } else { + // + sendSms(phone, "Grandma opened faucet") + state.lastOpened.date = now() + log.debug "Grandma Opened Faucet: $state.lastOpened" + + } +} + +def alertMe() { + log.trace "#alerting...#" + def targetTime = state.lastOpened.date + minutes.toInteger()*60*1000 + log.debug "#alertMe: last: ${state.lastOpened.date} , now: ${now()}, targetTime: ${targetTime}} " + if ( now() > targetTime ){ + log.debug "Grandma needs water badly" + sendSms(phone, "Grandma needs water badly") + } else { + log.debug "Grandma's aight!" + } +} \ No newline at end of file diff --git a/official/hue-minimote.groovy b/official/hue-minimote.groovy new file mode 100644 index 0000000..5c46779 --- /dev/null +++ b/official/hue-minimote.groovy @@ -0,0 +1,153 @@ +/** + * My Living Room Lighting + * + * 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: + * + * 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. + * + */ + definition( + name: "My Living Room Lighting", + namespace: "smartthings", + author: "smartthings", + description: "allow a button controller to control my hue lamps, tv lights, and floor lamp", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png") + + + preferences { + section("Control which hue lamps?") { + input "hueLamps", "capability.colorControl", required: true, multiple: true + } + section("Control which TV lights?") { + input "tvLights", "capability.colorControl", required: false + } + section("Control other (non-hue) lamps?") { + input "otherLights", "capability.switch", required: false, multiple: true + } + section("Which button controller?") { + input "buttonDevice", "capability.button", required: true + } +} + +def installed() { + log.debug "Installed with settings: ${settings}" + initialize() +} + +def updated() { + log.debug "Updated with settings: ${settings}" + unsubscribe() + initialize() +} + +def initialize() { + subscribe(buttonDevice, "button", buttonEvent) + hueLamps.each { + log.debug "lamp ${it.displayName} hue: ${it.currentHue}" + log.debug "lamp ${it.displayName} saturation: ${it.currentSaturation}" + log.debug "lamp ${it.displayName} color ${it.currentColor}" + log.debug "lamp ${it.displayName} level ${it.currentLevel}" + } + + log.debug "tv hue: ${tvLights?.currentHue}" + log.debug "tv saturation: ${tvLights?.currentSaturation}" + log.debug "tv color ${tvLights?.currentColor}" + log.debug "tv level ${tvLights?.currentLevel}" +} + +def buttonEvent(evt) { + def buttonState = evt.value // "pushed" or "held" + def buttonNumber = parseJson(evt.data)?.buttonNumber + + log.debug "buttonState: $buttonState" + log.debug "buttonNumber: $buttonNumber" + + if (!(1..4).contains(buttonNumber)) { + log.error "This app only supports four buttons. Invalid buttonNumber: $buttonNumber" + } else if (!(buttonState == "pushed" || buttonState == "held")) { + log.error "This app only supports button pushed and held values. Invalid button state: $buttonState" + } else { + def meth = "handleButton" + buttonNumber + buttonState.capitalize() + log.debug "meth: $meth" + "$meth"() + } + } + +// normal "white" lighting +def handleButton1Pushed() { + log.debug "handle1Pushed" + + hueLamps.setColor(level: 100, hue: 20, saturation: 80) + + // notice the "?." operator - tvLights may not be set (required: false). + tvLights?.setColor(level: 100, hue: 100, saturation: 100) + otherLights?.on() +} + +// turn everything off +def handleButton1Held() { + log.debug "handleButton1Held" + + hueLamps.off() + tvLights?.off() + otherLights?.off() +} + +// soft, dim white light +def handleButton2Pushed() { + log.debug "handleButton2Pushed" + + hueLamps.setColor(level: 50, hue: 20, saturation: 80) + tvLights.setColor(level: 30, hue: 70, saturation: 70) + otherLights?.on() +} + +// set to what you want! +def handleButton2Held() { + log.debug "handleButton2Held" +} + +// dim red light +def handleButton3Pushed() { + hueLamps.setColor(level: 40, hue: 100, saturation: 100) + tvLights?.setColor(level: 30, hue: 100, saturation: 100) + otherLights?.off() +} + +// set to what you want! +def handleButton3Held() { + log.debug "handleButton3Held" +} + +// dim blue light +def handleButton4Pushed() { + log.debug "handleButton4Pushed" + + hueLamps.setColor(level: 10, hue: 70, saturation: 100) + tvLights?.setColor(level: 10, hue: 70, saturation: 100) + otherLights?.off() +} + +// debug information +def handleButton4Held() { + hueLamps.each { + log.debug "lamp ${it.displayName} hue: ${it.currentHue}" + log.debug "lamp ${it.displayName} saturation: ${it.currentSaturation}" + log.debug "lamp ${it.displayName} level ${it.currentLevel}" + } + + log.debug "tv hue: ${tvLights?.currentHue}" + log.debug "tv saturation: ${tvLights?.currentSaturation}" + log.debug "tv color ${tvLights?.currentColor}" + log.debug "tv level ${tvLights?.currentLevel}" +} diff --git a/official/page-params-by-href.groovy b/official/page-params-by-href.groovy new file mode 100644 index 0000000..5c187cb --- /dev/null +++ b/official/page-params-by-href.groovy @@ -0,0 +1,144 @@ +/** + * Example of passing params via href element to a dynamic page + * + * 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: + * + * 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. + * + */ +definition( + name: "href params example", + namespace: "smartthings", + author: "SmartThings", + description: "passing params via href element to a dynamic page", + category: "", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png") + + +// ======================================================== +// PAGES +// ======================================================== + +preferences { + page(name: "firstPage") + page(name: "secondPage") + page(name: "thirdPage") +} + +def firstPage() { + + def hrefParams = [ + foo: "bar", + thisIs: "totally working", + install: checkSomeCustomLogic(), + nextPage: "thirdPage" + ] + + dynamicPage(name: "firstPage", uninstall: true) { + /* + * The href element accepts a key of `params` and expects a `Map` as the value. + * Anything passed in `params` will be sent along with the request but will not be persisted in any way. + * The params will be used going to the next page but will not be available when backing out of that page. + * This, combined with the fact that pages refresh when navigating back to them, means that your params will not be + * available if your user hits the back button. + */ + section { + href( + name: "toSecondPage", + page: "secondPage", + params: hrefParams, + description: "includes params: ${hrefParams}", + state: hrefState() + ) + } + } +} + +def secondPage(params) { + /* + * firstPage included `params` in the href element that navigated to here. + * You must specify some variable name in the method declaration. (I used 'params' here, but it can be any variable name you want). + * If you do not specify a variable name, there is no way to get the params that you specified in your `href` element. + */ + + log.debug "params: ${params}" + + dynamicPage(name: "secondPage", uninstall: true, install: params?.install) { + if (params.nextPage) { + section { + href( + name: "toNextPage", + page: params.nextPage, + description: hrefState() ? "You've already been to the third page": "go checkout the third page", + state: hrefState() + ) + } + } else { + section { + paragraph "There were no params included when fetching this page." + } + } + } +} + +def thirdPage() { + + state.reachedThirdPage = true + + dynamicPage(name: "thirdPage") { + section { + image "https://placekitten.com/g/600/500" + } + } +} + +// ======================================================== +// HELPERS +// ======================================================== + + +def checkSomeCustomLogic() { + // ... + false +} + +def hrefState() { + /* + * `state: "complete"` makes the right side of the href green. + * It's a great way to show the user that they've already set up some stuff on that page. + * In other words, it's a great way to show state ;) + * If you're using hrefs, it's a good idea to set `state` when appropriate. + */ + state.reachedThirdPage ? "complete": "" +} + +// ======================================================== +// HANDLERS +// ======================================================== + + +def installed() { + log.debug "Installed with settings: ${settings}" + initialize() +} + +def updated() { + log.debug "Updated with settings: ${settings}" + unsubscribe() + initialize() +} + +def initialize() { + // TODO: subscribe to attributes, devices, locations, etc. +} + +// TODO: implement event handlers \ No newline at end of file diff --git a/official/restful-switch.groovy b/official/restful-switch.groovy new file mode 100644 index 0000000..dc0b768 --- /dev/null +++ b/official/restful-switch.groovy @@ -0,0 +1,119 @@ +/** + * Control a Switch with an API call + * + * 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: + * + * 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. + * + */ +definition( + name: "Control a Switch with an API call", + namespace: "smartthings", + author: "SmartThings", + description: "V2 of 'RESTful Switch' example. Trying to make OAuth work properly.", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + oauth: true) + +preferences { + section("which switches?") { + input "theSwitches", "capability.switch", multiple: true + } +} + +mappings { + path("/switches") { + // GET requests to /switches endpoint go to listSwitches. + // PUT requests go to updateSwitches + action: [ + GET: "getSwitches", + PUT: "updateSwitches" + ] + } + + // GET requests to endpoint /switches/ go to getSwitch + // PUT requests to endpoint /switches/ go to updateSwitch + path("/switches/:id") { + action: [ + GET: "getSwitch", + PUT: "updateSwitch" + ] + } +} + +// return a map in the form of [switchName, switchStatus] +// the returned value will be converted to JSON by the platform +def getSwitches() { + def status = [:] + theSwitches.each {theSwitch -> + log.trace "will populate status map" + log.trace "theSwitch id: ${theSwitch.id}" + status.put(theSwitch.displayName, theSwitch.currentSwitch) + } + + log.debug "listSwitches returning: $status" + return status +} + +def getSwitch() { + def theSwitch = theSwitches.find{it.id == params.id} + [theSwitch.displayName, theSwitch.currentSwitch] +} + +// execute the command specified in the request +// returns a 400 error if a non-supported command +// is specified (only on, off, or toggle supported) +// assumes request body with JSON in format {"command" : ""} +def updateSwitches() { + log.trace "updateSwitches: request: $request" + log.trace "updateSwitches: params: $params" + + theSwitches.each { + doCommand(it, request.JSON.command) + } +} + +// execute the command specified in the request +// return a 400 error if a non-supported command +// is specified (only on, off, or toggle supported) +// assumes request body with JSON in format {"command" : ""} +def updateSwitch() { + log.trace "updateSwitch: look for swithc with id ${params.id}" + def theSwitch = theSwitches.find{it.id == params.id} + doCommand(theSwitch, request.JSON.command) +} + +def doCommand(theSwitch, command) { + if (command == "toggle") { + if (theSwitch.currentSwitch == "on") { + log.debug "will try and turn switch ${theSwitch.displayName} on" + theSwitch.off() + } else { + log.debug "will try and turn switch ${theSwitch.displayName} off" + theSwitch.on() + } + } else if (command == "on" || command == "off") { + theSwitch."$command"() + } else { + httpError(400, "Unsupported command - only 'toggle', 'off', and 'on' supported") + } +} + +// called when SmartApp is installed +def installed() { + log.debug "Installed with settings: ${settings}" +} + +// called when any preferences are changed in this SmartApp. +def updated() { + log.debug "Updated with settings: ${settings}" + unsubscribe() +} diff --git a/official/turn-on-at-sunset.groovy b/official/turn-on-at-sunset.groovy new file mode 100644 index 0000000..ff2f100 --- /dev/null +++ b/official/turn-on-at-sunset.groovy @@ -0,0 +1,48 @@ +/** + * Turn on at Sunset + * + * 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: + * + * 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. + * + */ +definition( + name: "Turn on at Sunset", + namespace: "examples", + author: "SmartThings", + description: "Turn on lights at sunset, based on your location's geofence.", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/rise-and-shine.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/rise-and-shine@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/rise-and-shine@2x.png") + +preferences { + section("Lights") { + input "switches", "capability.switch", title: "Which lights to turn on?" + } +} + +def installed() { + initialize() +} + +def updated() { + unsubscribe() + initialize() +} + +def initialize() { + subscribe(location, "sunset", sunsetHandler) +} + +def sunsetHandler(evt) { + log.debug "turning on lights at sunset" + switches.on() +} diff --git a/official/turn-on-before-sunset.groovy b/official/turn-on-before-sunset.groovy new file mode 100644 index 0000000..a4ed25c --- /dev/null +++ b/official/turn-on-before-sunset.groovy @@ -0,0 +1,70 @@ +/** + * Turn on before Sunset + * + * 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: + * + * 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. + * + */ +definition( + name: "Turn on before Sunset", + namespace: "exmaples", + author: "SmartThings", + description: "Turn on lights a number of minutes before sunset, based on your location's geofence", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/rise-and-shine.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/rise-and-shine@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/rise-and-shine@2x.png") + +preferences { + section("Lights") { + input "switches", "capability.switch", title: "Which lights to turn on?" + input "offset", "number", title: "Turn on this many minutes before sunset" + } +} + +def installed() { + initialize() +} + +def updated() { + unsubscribe() + initialize() +} + +def initialize() { + subscribe(location, "sunsetTime", sunsetTimeHandler) + + //schedule it to run today too + scheduleTurnOn(location.currentValue("sunsetTime")) +} + +def sunsetTimeHandler(evt) { + //when I find out the sunset time, schedule the lights to turn on with an offset + scheduleTurnOn(evt.value) +} + +def scheduleTurnOn(sunsetString) { + //get the Date value for the string + def sunsetTime = Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", sunsetString) + + //calculate the offset + def timeBeforeSunset = new Date(sunsetTime.time - (offset * 60 * 1000)) + + log.debug "Scheduling for: $timeBeforeSunset (sunset is $sunsetTime)" + + //schedule this to run one time + runOnce(timeBeforeSunset, turnOn) +} + +def turnOn() { + log.debug "turning on lights" + switches.on() +} diff --git a/official/turn-on-by-zip-code.groovy b/official/turn-on-by-zip-code.groovy new file mode 100644 index 0000000..ac71ccb --- /dev/null +++ b/official/turn-on-by-zip-code.groovy @@ -0,0 +1,84 @@ +/** + * Turn on by ZIP code + * + * 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: + * + * 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. + * + */ +definition( + name: "Turn on by ZIP code", + namespace: "examples", + author: "SmartThings", + description: "Turn on lights based on ZIP code", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/rise-and-shine.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/rise-and-shine@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/rise-and-shine@2x.png") + +preferences { + section("Lights") { + input "switches", "capability.switch", title: "Which lights to turn on?" + } + section("Sunset offset (optional)...") { + input "sunsetOffsetValue", "text", title: "HH:MM", required: false + } + section("Zip code") { + input "zipCode", "text", required: false + } +} + +def installed() { + initialize() +} + +def updated() { + unsubscribe() + initialize() +} + +def initialize() { + scheduleNextSunset() +} + +def scheduleNextSunset(date = null) { + def s = getSunriseAndSunset(zipCode: zipCode, sunsetOffset: getSunsetOffset(), date: date) + def now = new Date() + def setTime = s.sunset + log.debug "setTime: $setTime" + + // use state to keep track of sunset times between executions + // if sunset time has changed, unschedule and reschedule handler with updated time + if(state.setTime != setTime.time) { + unschedule("sunsetHandler") + + if(setTime.before(now)) { + setTime = setTime.next() + } + + state.setTime = setTime.time + + log.info "scheduling sunset handler for $setTime" + schedule(setTime, sunsetHandler) + } +} + +def sunsetHandler() { + log.debug "turning on lights" + switches.on() + + // schedule for tomorrow + scheduleNextSunset(new Date() + 1) +} + +private getSunsetOffset() { + //if there is an offset, make negative since we only care about before + sunsetOffsetValue ? "-$sunsetOffsetValue" : null +} diff --git a/official/tweet-to-hue.groovy b/official/tweet-to-hue.groovy new file mode 100644 index 0000000..046bf4f --- /dev/null +++ b/official/tweet-to-hue.groovy @@ -0,0 +1,134 @@ +/** + * Tweet to Hue + * + * Copyright 2015 Andrew Mager & Kris Schaller + * + * 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. + * + */ +definition( + name: "Tweet to Hue", + namespace: "com.smartthings.dev", + author: "Andrew Mager & Kris Schaller", + description: "Update a Hue bulb's color based on a tweet.", + category: "Fun & Social", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + oauth: true) + + +preferences { + section("Control these hue bulbs...") { + input "hues", "capability.colorControl", title: "Which Hue Bulbs?", required:false, multiple:true + } +} + + +/* This block defines which functions will fire when you hit certain endpoints. */ + +mappings { + path("/hue") { + action: [ + PUT: "postHue" + ] + } +} + +def installed() { + log.debug "Installed with settings: ${settings}" + + initialize() +} + +def updated() { + log.debug "Updated with settings: ${settings}" + + unsubscribe() + initialize() +} + +def initialize() { + +} + +/** +* Body: { color=[yourcolor] } to change color +* Example: +* { +* "value" : " #smartthings is so color=blue" +* } +*/ + +def postHue() { + def tweetText = request.JSON.text + log.info "POST: $tweetText" + + try { + def tweetColor = (tweetText =~ /color=(\w+)/)[0][1].toLowerCase() + log.debug (tweetText =~ /color=(\w+)/) + setHueColor(tweetColor) + } + catch (any) { + log.trace "POST: Check Body (e.g: @RT: #smartthings color=red)" + } +} + +private setHueColor(color) { + + def hueColor = 0 + def saturation = 100 + + switch(color) { + case "white": + hueColor = 52 + saturation = 19 + break; + case "blue": + hueColor = 70 + break; + case "green": + hueColor = 39 + break; + case "yellow": + hueColor = 25 + break; + case "orange": + hueColor = 10 + break; + case "purple": + hueColor = 75 + break; + case "pink": + hueColor = 83 + break; + case "red": + hueColor = 100 + break; + } + + state.previous = [:] + + hues.each { + state.previous[it.id] = [ + "switch": it.currentValue("switch"), + "level" : it.currentValue("level"), + "hue": it.currentValue("hue"), + "saturation": it.currentValue("saturation") + ] + } + + log.debug "current values = $state.previous" + + def newValue = [hue: hueColor, saturation: saturation, level: 100] + log.debug "new value = $newValue" + + hues*.setColor(newValue) +} diff --git a/official/web-services-smartapp.groovy b/official/web-services-smartapp.groovy new file mode 100644 index 0000000..8c650f3 --- /dev/null +++ b/official/web-services-smartapp.groovy @@ -0,0 +1,79 @@ +/** + * Web Services Tutorial + * + * 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: + * + * 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. + * + */ +definition( + name: "Web Services Tutorial", + namespace: "smartthings", + author: "SmartThings", + description: "web services tutorial", + category: "", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png", + oauth: [displayName: "web services tutorial ", displayLink: "http://localhost:4567"]) + + +preferences { + section ("Allow external service to control these things...") { + input "switches", "capability.switch", multiple: true, required: true + } +} + +mappings { + path("/switches") { + action: [ + GET: "listSwitches" + ] + } + path("/switches/:command") { + action: [ + PUT: "updateSwitches" + ] + } +} + +// returns a list like +// [[name: "kitchen lamp", value: "off"], [name: "bathroom", value: "on"]] +def listSwitches() { + + def resp = [] + switches.each { + resp << [name: it.displayName, value: it.currentValue("switch")] + } + return resp +} + +void updateSwitches() { + // use the built-in request object to get the command parameter + def command = params.command + + // all switches have the comand + // execute the command on all switches + // (note we can do this on the array - the command will be invoked on every element + switch(command) { + case "on": + switches.on() + break + case "off": + switches.off() + break + default: + httpError(400, "$command is not a valid command for all switches specified") + } + +} +def installed() {} + +def updated() {} diff --git a/official/wunderground-pws-connect.groovy b/official/wunderground-pws-connect.groovy new file mode 100644 index 0000000..99eadaf --- /dev/null +++ b/official/wunderground-pws-connect.groovy @@ -0,0 +1,99 @@ +/** + * Weather Underground PWS Connect + * + * Copyright 2015 Andrew Mager + * + * 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. + * + */ + +import java.text.DecimalFormat + +definition( + name: "Weather Underground PWS Connect", + namespace: "co.mager", + author: "Andrew Mager", + description: "Connect your SmartSense Temp/Humidity sensor to your Weather Underground Personal Weather Station.", + category: "Green Living", + iconUrl: "http://i.imgur.com/HU0ANBp.png", + iconX2Url: "http://i.imgur.com/HU0ANBp.png", + iconX3Url: "http://i.imgur.com/HU0ANBp.png", + oauth: true) + + +preferences { + section("Select a sensor") { + input "temp", "capability.temperatureMeasurement", title: "Temperature", required: true + input "humidity", "capability.relativeHumidityMeasurement", title: "Humidity", required: true + } + section("Configure your Weather Underground credentials") { + input "weatherID", "text", title: "Weather Station ID", required: true + input "password", "password", title: "Weather Underground password", required: true + + } +} + +def installed() { + log.debug "Installed with settings: ${settings}" + initialize() +} + + +def updated() { + log.debug "Updated with settings: ${settings}" + initialize() +} + + +def initialize() { + + runEvery10Minutes(updateCurrentWeather) + + log.trace "Temp: " + temp.currentTemperature + log.trace "Humidity: " + humidity.currentHumidity + log.trace "Dew Point: " + calculateDewPoint(temp.currentTemperature, humidity.currentHumidity) + +} + + +def updateCurrentWeather() { + + def params = [ + uri: "http://weatherstation.wunderground.com", + path: "/weatherstation/updateweatherstation.php", + query: [ + "ID": weatherID, + "PASSWORD": password, + "dateutc": "now", + "tempf": temp.currentTemperature, + "humidity": humidity.currentHumidity, + "dewptf": calculateDewPoint(temp.currentTemperature, humidity.currentHumidity), + "action": "updateraw", + "softwaretype": "SmartThings" + ] + ] + + if (temp.currentTemperature) { + try { + httpGet(params) { resp -> + log.debug "response data: ${resp.data}" + } + } catch (e) { + log.error "something went wrong: $e" + } + } + +} + + +def calculateDewPoint(t, rh) { + def dp = 243.04 * ( Math.log(rh / 100) + ( (17.625 * t) / (243.04 + t) ) ) / (17.625 - Math.log(rh / 100) - ( (17.625 * t) / (243.04 + t) ) ) + return new DecimalFormat("##.##").format(dp) +} -- 2.34.1