Updated version that:
- Uses the OSRAM Lightify RGBW LED Strips
- Sets the color based on local forecast temperature in the morning
- Sets the color to a default after that, or to holiday colors when near certain holidays. For some holidays, the colors alternate between two options every time the light turns off (such as red and green for Christmas).
The actual turning on and off of the lights is controlled by Smart Lighting or other separate SmartApps.
/**
* WeatherAndHolidayLights
*
* Copyright 2016 Mykines
*
* 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: "WeatherAndHolidayLights",
namespace: "Mykines",
author: "Mykines",
description: "Turn an OSRAM color bulb colors to indicate how different from normal today's temperature will be.",
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 {
section("Where..."){
input "zipcode", "text", title: "Zipcode?", required: true // ask instead of
}
section("Devices") {
input "thebulb", "capability.colorControl", title: "Pick a bulb", required: true, multiple: false
}
section("Settings") {
input(name: "defaultColor", type: "number", title: "What Default Hue?", description: "0", required: true, defaultValue: 0)
}
section("When...") {
input "startforecastTime", "time", title: "Start Forecast Mode at what time?", required: true
input "endForecastTime", "time", title: "End Forecast Mode at what time?", required: true
}
// section("testing...") {
// input(name: "monthNumb", type: "number", title: "monthNumb", description: "0", required: true, defaultValue: 0)
// input(name: "dateNumb", type: "number", title: "dateNumb", description: "0", required: true, defaultValue: 0)
// }
}
def installed() {
schedule(startforecastTime, "setForecastColor")
schedule(endForecastTime, "setHolidayColor")
subscribeToCommand(thebulb, "off", uponOffCommand)
state.colorToggle = 0
log.debug "Installed with settings: ${settings}"
thebulb.setSaturation(100)
}
def updated() {
unsubscribe()
unschedule()
schedule(startforecastTime, "setForecastColor")
schedule(endForecastTime, "setHolidayColor")
subscribeToCommand(thebulb, "off", uponOffCommand)
state.colorToggle = 0
log.debug "Updated with settings: ${settings}"
thebulb.setSaturation(100)
}
def setForecastColor() {
log.debug "in setForecastColor"
def forecastInput = getWeatherFeature("forecast", zipcode)
// log.debug "day forecastInput: $forecastInput"
def forecastHighString = forecastInput?.forecast?.simpleforecast?.forecastday?.high[0].fahrenheit
def forecastHigh = forecastHighString.toInteger()
log.debug "day forecastData: $forecastHigh"
// Get this stuff from the wunderground API: https://www.wunderground.com/weather/api/d/docs?d=data/index&MR=1
def response = getWeatherFeature("almanac", zipcode)
def almanacData = response?.values()
// log.debug "almanac: $almanacData"
def aveHighString = response?.almanac?.temp_high.normal.F
def aveHigh = aveHighString.toInteger()
log.debug "aveHigh: $aveHigh"
def temperatureDelta = forecastHigh - aveHigh
log.debug "temperatureDelta: $temperatureDelta"
def bulbColorText = "unknown"
def bulbColor = 22 // icky yellow-green hue, should always be overridden
if(temperatureDelta>9) {
bulbColorText = "Red"
bulbColor = 0
} else if(temperatureDelta>5) {
bulbColorText = "Orange"
bulbColor = 1.25
} else if(temperatureDelta>2) {
bulbColorText = "Yellow"
bulbColor = 6.5
} else if(temperatureDelta>-3) {
bulbColorText = "Green"
bulbColor = 33
} else if(temperatureDelta>-6) {
bulbColorText = "Light Blue"
bulbColor = 60
} else if(temperatureDelta>-10) {
bulbColorText = "Indigo"
bulbColor = 66
} else {
bulbColorText = "Purple"
bulbColor = 79
}
log.debug "bulbColor: $bulbColor"
log.debug "Weather Forecast Changed the color to $bulbColorText"
thebulb.setHue(bulbColor)
thebulb.setSaturation(100)
}
def uponOffCommand(evt) {
log.debug "in onOffCommand"
def time = now()
def dateInfo = new Date(time + location.timeZone.getOffset(time))
def thisHour = dateInfo.hours
def thisMinutes = dateInfo.minutes
def currentTimeValue = thisHour.toInteger() * 60 + thisMinutes.toInteger()
log.debug "currentTimeValue: $currentTimeValue"
def readyTime = timeToday(endForecastTime, location.timeZone)
def readyHour = readyTime.format("H",location.timeZone)
def readyMinutes = readyTime.format("m",location.timeZone)
def endTimeValue = readyHour.toInteger() * 60 + readyMinutes.toInteger()
log.debug "endTimeValue: $endTimeValue"
if (currentTimeValue >= endTimeValue) {
if(state.colorToggle == 0) { // Toggle color back and forth every time it turns off
state.colorToggle = 1
} else {
state.colorToggle = 0
}
log.debug "state.colorToggleReady: $state.colorToggle"
setHolidayColor()
}
}
def setHolidayColor() {
log.debug "in setHolidayColor"
// def defaultColor = 55 // Light Bluish
def todaysColor = null
def valentinesStartMonth = 2
def valentinesStartDate = 10
def valentinesColor = 89 // Pink
def valentinesEndMonth = 2
def valentinesEndDate = 15
def easterStartMonth = 3 // April
def easterStartDate = 9
def easterColor1 = 6.5 // Yellow
def easterColor2 = 79 // Purple
def easterEndMonth = 3
def easterEndDate = 17 // April 16 is Easter 2017
def indepStartMonth = 6 // June
def indepStartDate = 28
def indepColor1 = 66 // Blue
def indepColor2 = 0 // Red
def indepEndMonth = 7 // July
def indepEndDate = 5
def halloweenStartMonth = 10 // Oct
def halloweenStartDate = 1
def halloweenColor1 = 1.25 // Orange
def halloweenColor2 = 79 // Purple
def halloweenEndMonth = 11 // Oct
def halloweenEndDate = 1
def tgivingStartMonth = 11 // Nov
def tgivingStartDate = 15
def tgivingColor = 6.5 // Yellow
def tgivingEndMonth = 11 // Nov
def tgivingEndDate = 25 // Nov 24 is Thanksgiving 2016
def christmasStartMonth = 12 // Dec
def christmasStartDate = 1
def christmasColor1 = 0 // Red
def christmasColor2 = 33 // Green
def christmasEndMonth = 12 // Dec
def christmasEndDate = 26
def time = now()
def dateInfo = new Date(time + location.timeZone.getOffset(time))
def thisMonth = dateInfo.month + 1 // Have to add one as the month number stupidly starts at 0. Why does anyone start counting at 0?
def thisDate = dateInfo.date
def todayIndex = getDateIndex(thisMonth, thisDate)
// def todayIndex = getDateIndex(monthNumb, dateNumb) // For testing only
log.debug "todayIndex: $todayIndex"
if (todayIndex >= getDateIndex(christmasEndMonth,christmasEndDate)) {
todaysColor = defaultColor
} else if (todayIndex >= getDateIndex(christmasStartMonth,christmasStartDate)) {
if(state.colorToggle == 0) { // Toggle color back and forth every day
todaysColor = christmasColor1
} else {
todaysColor = christmasColor2
}
} else if (todayIndex >= getDateIndex(tgivingEndMonth,tgivingEndDate)) {
todaysColor = defaultColor
} else if (todayIndex >= getDateIndex(tgivingStartMonth,tgivingStartDate)) {
todaysColor = tgivingColor
} else if (todayIndex >= getDateIndex(halloweenEndMonth,halloweenEndDate)) {
todaysColor = defaultColor
} else if (todayIndex >= getDateIndex(halloweenStartMonth,halloweenStartDate)) {
if(state.colorToggle == 0) { // Toggle color back and forth every day
todaysColor = halloweenColor1
} else {
todaysColor = halloweenColor2
}
} else if (todayIndex >= getDateIndex(indepEndMonth,indepEndDate)) {
todaysColor = defaultColor
} else if (todayIndex >= getDateIndex(indepStartMonth,indepStartDate)) {
if(state.colorToggle == 0) { // Toggle color back and forth every day
todaysColor = indepColor1
} else {
todaysColor = indepColor2
}
} else if (todayIndex >= getDateIndex(easterEndMonth,easterEndDate)) {
todaysColor = defaultColor
} else if (todayIndex >= getDateIndex(easterStartMonth,easterStartDate)) {
if(state.colorToggle == 0) { // Toggle color back and forth every day
todaysColor = easterColor1
} else {
todaysColor = easterColor2
}
} else if (todayIndex >= getDateIndex(valentinesEndMonth,valentinesEndDate)) {
todaysColor = defaultColor
} else if (todayIndex >= getDateIndex(valentinesStartMonth,valentinesStartDate)) {
todaysColor = valentinesColor
} else {
todaysColor = defaultColor
}
log.debug "todaysColor: $todaysColor"
thebulb.setHue(todaysColor)
thebulb.setSaturation(100)
}
def getDateIndex(inputMonth, inputDate) {
// log.debug "inputMonth: $inputMonth inputDate: $inputDate"
def result = (inputMonth-1) * 31 + inputDate // Rough day of the year calc, wrong as all months dont have 31 days, but it doesn't matter
return result
}