/** * Garden Hue v 3.0 * by lg. kahn * * This SmartApp will turn on if enabled after sunset and run to * sunrise.. It will change the hue color of your garden hue every xx * minutes based on a schedule. * * Version 1.0: April 28, 2016 - Initial release * * Version 2.0: add app name to push messages. * also dont schedule anything if disabled is set. * clean up and remove some debugging. * add run every 5 minute option. * Turn off all hues when saving app. * * Version 2.1: * Add a switch/virtual switch option, which if selected the enable/disable of the app will follow. * * Version 3: * Add option to control each light separately, so each gets its own color. * Add Holiday Mode option where you can individually control what colors are enabled. * Related, Add options to turn on/off each color. * Add every 1 minute option. Use Sparingly can overload back end Scheduling * Added better logging, so in notification window you can see current color set. This is in order to help debug for when lights stop responding. * The latest version of this file can be found at * * * Vesion 3,1 : * Found bug in code when random was off it had a check xxxx = true instead of xxxx == true so it automatically controlled each light (if you have more than one) * individually even if you hadn't enabled that setting. * * v 4.0 oct 2022 fix requirement to make sure holiday works ( need random on). Turn on random if we have holiday mode on automatically. * Add fade in and fade out options in seconds. * Add new options for 10, 15, 30 etc seconds to schedule time. Also if the transitions are ?= schedule time, reset the schedule time to 2 minutes. * Note fade out only works if you dont separate the fixtures as we need to pause execution for the fade off time, else it would immediately turn off or on again the command * executes immeately even though the light will take the x numbers of seconds to finish the transtion, and without a pause execution the next turn on would happen * before the transition time has expired. * * Also be warned some lights do not work well or correctly with the setLevel(level,duration) command for fading. Namely the generic zigbee rgb switch does not, * but the advanced zigbee rgb bulb does. * * v 4.1 missing a line needed in the new code for non random rgbiv color changing mode to work correctly. Also figure how to add fade off with the suspendExecution * in the separate light fixture and random mode. I added it for all fixtures on once outside the separate fixture loop. * Also was missing code for the non-holiday, random, separated fixture case. * * https://github.com/lgkapps/SmartThingsPublic/gardenhue * * lgk v 4.2 add 4 custom color hsv templates. notes range not work so change range of colors 0-100 in intialize, also section titles not showing up in the * page so add paragraph for titles. * the custom colors only work in random mode as the non random is ROYGBIV that goes through the rainbow and wouldnt make sense to add a custom color in there. * * 4.3 fixed but with random mode and all colors on custom colors not kicking in.. missed one change of the hard coded 16 to maxColors variable. * v 4.4 slight change to fade off code for separate color for each fixture, random (ie holiday mode) there was an extra fade for each * fixture that was not removed.. all fixtures should have faded off at the same time instead it did that and then did an extra for each which * made them not come on with the new color at exactly the same time. (left over code artifact from before fade was implemented). * v 4.5 multitude of changes. * * 1. removed paragraph lines as hubitat now fixed the section headers to include the text which was previously not coming out on the page. * * 2. someone pointed out that color input box was now available since 2.3.x so I added that for the custom 1 -4 colors. * and removed the hardcoded hue and saturation fields.. Note if you previously set these you now need to RESET them * using the new color selections boxes. * * also related to this I used the custom level as well as hue and staturation which will override the default level you have set . * this may not work perfectly as some lights dont show colors well with low levels, if so let me know and i will remove this code. But by using this it will try to do the color exactly has you set it. * * My default colors took that into consideration and only have colors that work well with a level of close to 100% * * 4.6 change debug to log level, rewrite all logging, change many to info which didnt exist when this is written. levels are off, minimal, maximum, minimal corresponds to what * loging off previously was, maximum corresponds to what debugging on previously was. * * v 4.7 warning about using fade with govee lights.. will overwhelm the hub. as there is no internal fade up or down fx. * add 5 new pure random colors 1-100 as govee and other lights are true 16 million colors. * * v 4.8 also for govee only add 5 user selectable effects into the mix. * v 4.9 add slate blue color change random to generate a random sat. as well has hue.. but keep it above 30 as there are not many colors below that. * see https://www.chilliant.com/colournames.html * v 5.0 instead of generating array every change just generate max number for random and the color array once in init or updated. * v 5.1 add 5 optional named colors * v 5.2 missing named color code in non holiday random mode */ definition( name: "Garden Hue", namespace: "lgkapps", author: "lgkahn kahn-st@lgk.com", description: "Change hue color of lights based on schedule sunset to sunrise.", category: "Convenience", iconUrl: "http://mail.lgk.com/huetree1.png", iconX2Url:"http://mail.lgk.com/huetree2.png", iconX3Url: "http://mail.lgk.com/huetree2.png", ) import hubitat.helper.ColorUtils import groovy.transform.Field preferences { section("Choose hue lights you wish to control?") { input "hues", "capability.colorControl", title: "Which Color Changing Bulbs?", multiple:true, required: true input "brightnessLevel", "number", title: "Brightness Level (1-100)?", required:false, defaultValue:100 //Select brightness } section("Choose cycle time between color changes? ") { input "cycleTime", width: 5, "enum", title: "Cycle time?" , options: [ "10 seconds", "20 seconds", "30 seconds", "45 seconds", "1 minute", "2 minutes", "5 minutes", "10 minutes", "15 minutes", "30 minutes", "1 hour", "3 hours" ], required: true, defaultValue: "30 minutes" } section( "") { input "offset", "enum", title: "Turn Off How many hours before sunrise?", width : 5, options: ["0", "-1", "-2", "-3", "-4", "-5"], required: true, defaultValue: "0" } section( "Enabled/Disabled options?" ) { input "enabled","bool", title: "Enabled?", required: true, defaultValue: true input "enableswitch", "capability.switch", title: "Optional: Do you have a switch/virtual switch which the application enable/disable functionality should follow? If you do not want this feature leave blank.", multiple:false, required: false input("fadeOnTime", "enum", title: "Optional time to fade when turning on/setting color (do not use for Govee)?", width: 5, options: ["Off","5","10","15","20","30"], required: true, defaultValue: "Off") paragraph "" input("fadeOffTime", "enum", title: "Optional time to fade when turning off (does work if you separate fixtures)?", width: 5, options: ["Off","5","10","15","20","30"], required: true, defaultValue: "Off") input "randomMode","bool", title: "Enable Random Mode?", required: true, defaultValue: false input "individualControl","bool", title: "Control Each light Fixture Individually?", required: false, defaultValue: false } section ("Custom Colors - Optional (Enable in Next Section)?") { input "customColor1", "color", title: "Custom Color 1?", width: 2, required: false, defaultValue: "#750000" paragraph "" input "customColor2", "color", title: "Custom Color 2?", width: 2, required: false, defaultValue: "#007500" paragraph "" input "customColor3", "color", title: "Custom Color 3?", width: 2, required: false, defaultValue: "#000075" paragraph "" input "customColor4", "color", title: "Custom Color 4?", width: 2, required: false, defaultValue: "#750075" } section ("Effects - (Govee only) Optional (Enable in Next Section)?") { input "effect1", "number", width: 3, title: "Effect 1?", required: false, defaultValue: 101 paragraph "" input "effect2", "number", width: 3, title: "Effect 2?", required: false, defaultValue: 102 paragraph "" input "effect3", "number", width: 3, title: "Effect 3?", required: false, defaultValue: 103 paragraph "" input "effect4", "number", width: 3, title: "Effect 4?", required: false, defaultValue: 104 paragraph "" input "effect5", "number", width: 3, title: "Effect 5?", required: false, defaultValue: 105 } section ("Named Colors Optional (Enable in Next Section)?") { input "namedColor1", "enum", title: "Named Color 1", width: 20, required: false, options: ["Alice Blue","Antique White","Aqua","Aquamarine","Azure","Beige","Bisque","Black","Blanched Almond","Blue","Blue Violet","Brown","Burly Wood","Cadet Blue","Chartreuse","Chocolate","Coral","Cornflower Blue","Cornsilk","Crimson","Cyan","Dark Blue","Dark Cyan","Dark Goldenrod","Dark Gray","Dark Green","Dark Khaki","Dark Magenta","Dark Olive Green","Dark Orange","Dark Orchid","Dark Red","Dark Salmon","Dark Sea Green","Dark Slate Blue","Dark Slate Gray","Dark Turquoise","Dark Violet","Deep Pink","Deep Sky Blue","Dim Gray","Dodger Blue","Fire Brick","Floral White","Forest Green","Fuchsia","Gainsboro","Ghost White","Gold","Goldenrod","Gray","Green","Green Yellow","Honey Dew","Hot Pink","Indian Red","Indigo","Ivory","Khaki","Lavender","Lavender Blush","Lawn Green","Lemon Chiffon","Light Blue","Light Coral","Light Cyan","Light Goldenrod Yellow","Light Gray","Light Green","Light Pink","Light Salmon","Light SeaGreen","Light SkyBlue","Light SlateGray","Light SteelBlue","Light Yellow","Lime","LimeGreen","Linen","Magenta","Maroon","Medium Aqua Marine","Medium Blue","Medium Orchid","Medium Purple","Medium Sea Green","Medium Slate Blue","Medium Spring Green","Medium Turquoise","Medium Violet Red","Midnight Blue","Mint Cream","Misty Rose","Moccasin","Navajo White","Navy","Old Lace","Olive","Olive Drab","Orange","Orange Red","Orchid","Pale Goldenrod","Pale Green","Pale Turquoise","Pale Violet Red","Papaya Whip","Peach Puff","Peru","Pink","Plum","Powder Blue","Purple","Red","Rosy Brown","Royal Blue","Saddle Brown","Salmon","Sandy Brown","Sea Green","Seashell","Sienna","Silver","Sky Blue","Slate Blue","Slate Gray","Snow","Spring Green","Steel Blue","Tan","Teal","Thistle","Tomato","Turquoise","Violet","Wheat","White","White Smoke","Yellow","Yellow Green"] paragraph "" input "namedColor2", "enum", title: "Named Color 2", width: 20, required: false, options: ["Alice Blue","Antique White","Aqua","Aquamarine","Azure","Beige","Bisque","Black","Blanched Almond","Blue","Blue Violet","Brown","Burly Wood","Cadet Blue","Chartreuse","Chocolate","Coral","Cornflower Blue","Cornsilk","Crimson","Cyan","Dark Blue","Dark Cyan","Dark Goldenrod","Dark Gray","Dark Green","Dark Khaki","Dark Magenta","Dark Olive Green","Dark Orange","Dark Orchid","Dark Red","Dark Salmon","Dark Sea Green","Dark Slate Blue","Dark Slate Gray","Dark Turquoise","Dark Violet","Deep Pink","Deep Sky Blue","Dim Gray","Dodger Blue","Fire Brick","Floral White","Forest Green","Fuchsia","Gainsboro","Ghost White","Gold","Goldenrod","Gray","Green","Green Yellow","Honey Dew","Hot Pink","Indian Red","Indigo","Ivory","Khaki","Lavender","Lavender Blush","Lawn Green","Lemon Chiffon","Light Blue","Light Coral","Light Cyan","Light Goldenrod Yellow","Light Gray","Light Green","Light Pink","Light Salmon","Light SeaGreen","Light SkyBlue","Light SlateGray","Light SteelBlue","Light Yellow","Lime","LimeGreen","Linen","Magenta","Maroon","Medium Aqua Marine","Medium Blue","Medium Orchid","Medium Purple","Medium Sea Green","Medium Slate Blue","Medium Spring Green","Medium Turquoise","Medium Violet Red","Midnight Blue","Mint Cream","Misty Rose","Moccasin","Navajo White","Navy","Old Lace","Olive","Olive Drab","Orange","Orange Red","Orchid","Pale Goldenrod","Pale Green","Pale Turquoise","Pale Violet Red","Papaya Whip","Peach Puff","Peru","Pink","Plum","Powder Blue","Purple","Red","Rosy Brown","Royal Blue","Saddle Brown","Salmon","Sandy Brown","Sea Green","Seashell","Sienna","Silver","Sky Blue","Slate Blue","Slate Gray","Snow","Spring Green","Steel Blue","Tan","Teal","Thistle","Tomato","Turquoise","Violet","Wheat","White","White Smoke","Yellow","Yellow Green"] paragraph "" input "namedColor3", "enum", title: "Named Color 3", width: 20, required: false, options: ["Alice Blue","Antique White","Aqua","Aquamarine","Azure","Beige","Bisque","Black","Blanched Almond","Blue","Blue Violet","Brown","Burly Wood","Cadet Blue","Chartreuse","Chocolate","Coral","Cornflower Blue","Cornsilk","Crimson","Cyan","Dark Blue","Dark Cyan","Dark Goldenrod","Dark Gray","Dark Green","Dark Khaki","Dark Magenta","Dark Olive Green","Dark Orange","Dark Orchid","Dark Red","Dark Salmon","Dark Sea Green","Dark Slate Blue","Dark Slate Gray","Dark Turquoise","Dark Violet","Deep Pink","Deep Sky Blue","Dim Gray","Dodger Blue","Fire Brick","Floral White","Forest Green","Fuchsia","Gainsboro","Ghost White","Gold","Goldenrod","Gray","Green","Green Yellow","Honey Dew","Hot Pink","Indian Red","Indigo","Ivory","Khaki","Lavender","Lavender Blush","Lawn Green","Lemon Chiffon","Light Blue","Light Coral","Light Cyan","Light Goldenrod Yellow","Light Gray","Light Green","Light Pink","Light Salmon","Light SeaGreen","Light SkyBlue","Light SlateGray","Light SteelBlue","Light Yellow","Lime","LimeGreen","Linen","Magenta","Maroon","Medium Aqua Marine","Medium Blue","Medium Orchid","Medium Purple","Medium Sea Green","Medium Slate Blue","Medium Spring Green","Medium Turquoise","Medium Violet Red","Midnight Blue","Mint Cream","Misty Rose","Moccasin","Navajo White","Navy","Old Lace","Olive","Olive Drab","Orange","Orange Red","Orchid","Pale Goldenrod","Pale Green","Pale Turquoise","Pale Violet Red","Papaya Whip","Peach Puff","Peru","Pink","Plum","Powder Blue","Purple","Red","Rosy Brown","Royal Blue","Saddle Brown","Salmon","Sandy Brown","Sea Green","Seashell","Sienna","Silver","Sky Blue","Slate Blue","Slate Gray","Snow","Spring Green","Steel Blue","Tan","Teal","Thistle","Tomato","Turquoise","Violet","Wheat","White","White Smoke","Yellow","Yellow Green"] paragraph "" input "namedColor4", "enum", title: "Named Color 4", width: 20, required: false, options: ["Alice Blue","Antique White","Aqua","Aquamarine","Azure","Beige","Bisque","Black","Blanched Almond","Blue","Blue Violet","Brown","Burly Wood","Cadet Blue","Chartreuse","Chocolate","Coral","Cornflower Blue","Cornsilk","Crimson","Cyan","Dark Blue","Dark Cyan","Dark Goldenrod","Dark Gray","Dark Green","Dark Khaki","Dark Magenta","Dark Olive Green","Dark Orange","Dark Orchid","Dark Red","Dark Salmon","Dark Sea Green","Dark Slate Blue","Dark Slate Gray","Dark Turquoise","Dark Violet","Deep Pink","Deep Sky Blue","Dim Gray","Dodger Blue","Fire Brick","Floral White","Forest Green","Fuchsia","Gainsboro","Ghost White","Gold","Goldenrod","Gray","Green","Green Yellow","Honey Dew","Hot Pink","Indian Red","Indigo","Ivory","Khaki","Lavender","Lavender Blush","Lawn Green","Lemon Chiffon","Light Blue","Light Coral","Light Cyan","Light Goldenrod Yellow","Light Gray","Light Green","Light Pink","Light Salmon","Light SeaGreen","Light SkyBlue","Light SlateGray","Light SteelBlue","Light Yellow","Lime","LimeGreen","Linen","Magenta","Maroon","Medium Aqua Marine","Medium Blue","Medium Orchid","Medium Purple","Medium Sea Green","Medium Slate Blue","Medium Spring Green","Medium Turquoise","Medium Violet Red","Midnight Blue","Mint Cream","Misty Rose","Moccasin","Navajo White","Navy","Old Lace","Olive","Olive Drab","Orange","Orange Red","Orchid","Pale Goldenrod","Pale Green","Pale Turquoise","Pale Violet Red","Papaya Whip","Peach Puff","Peru","Pink","Plum","Powder Blue","Purple","Red","Rosy Brown","Royal Blue","Saddle Brown","Salmon","Sandy Brown","Sea Green","Seashell","Sienna","Silver","Sky Blue","Slate Blue","Slate Gray","Snow","Spring Green","Steel Blue","Tan","Teal","Thistle","Tomato","Turquoise","Violet","Wheat","White","White Smoke","Yellow","Yellow Green"] paragraph "" input "namedColor5", "enum", title: "Named Color 5", width: 20, required: false, options: ["Alice Blue","Antique White","Aqua","Aquamarine","Azure","Beige","Bisque","Black","Blanched Almond","Blue","Blue Violet","Brown","Burly Wood","Cadet Blue","Chartreuse","Chocolate","Coral","Cornflower Blue","Cornsilk","Crimson","Cyan","Dark Blue","Dark Cyan","Dark Goldenrod","Dark Gray","Dark Green","Dark Khaki","Dark Magenta","Dark Olive Green","Dark Orange","Dark Orchid","Dark Red","Dark Salmon","Dark Sea Green","Dark Slate Blue","Dark Slate Gray","Dark Turquoise","Dark Violet","Deep Pink","Deep Sky Blue","Dim Gray","Dodger Blue","Fire Brick","Floral White","Forest Green","Fuchsia","Gainsboro","Ghost White","Gold","Goldenrod","Gray","Green","Green Yellow","Honey Dew","Hot Pink","Indian Red","Indigo","Ivory","Khaki","Lavender","Lavender Blush","Lawn Green","Lemon Chiffon","Light Blue","Light Coral","Light Cyan","Light Goldenrod Yellow","Light Gray","Light Green","Light Pink","Light Salmon","Light SeaGreen","Light SkyBlue","Light SlateGray","Light SteelBlue","Light Yellow","Lime","LimeGreen","Linen","Magenta","Maroon","Medium Aqua Marine","Medium Blue","Medium Orchid","Medium Purple","Medium Sea Green","Medium Slate Blue","Medium Spring Green","Medium Turquoise","Medium Violet Red","Midnight Blue","Mint Cream","Misty Rose","Moccasin","Navajo White","Navy","Old Lace","Olive","Olive Drab","Orange","Orange Red","Orchid","Pale Goldenrod","Pale Green","Pale Turquoise","Pale Violet Red","Papaya Whip","Peach Puff","Peru","Pink","Plum","Powder Blue","Purple","Red","Rosy Brown","Royal Blue","Saddle Brown","Salmon","Sandy Brown","Sea Green","Seashell","Sienna","Silver","Sky Blue","Slate Blue","Slate Gray","Snow","Spring Green","Steel Blue","Tan","Teal","Thistle","Tomato","Turquoise","Violet","Wheat","White","White Smoke","Yellow","Yellow Green"] } section ("Custom Colors Enabled - Only used in non ROYGBIV mode") { input "custom1Enabled", "bool", title: "Enable Custom Color 1?", required: false, defaultValue: false input "custom2Enabled", "bool", title: "Enable Custom Color 2?", required: false, defaultValue: false input "custom3Enabled", "bool", title: "Enable Custom Color 3?", required: false, defaultValue: false input "custom4Enabled", "bool", title: "Enable Custom Color 4?", required: false, defaultValue: false input "random1Enabled", "bool", title: "Enable Random Color 1?", required: false, defaultValue: false input "random2Enabled", "bool", title: "Enable Random Color 2?", required: false, defaultValue: false input "random3Enabled", "bool", title: "Enable Random Color 3?", required: false, defaultValue: false input "random4Enabled", "bool", title: "Enable Random Color 4?", required: false, defaultValue: false input "random5Enabled", "bool", title: "Enable Random Color 5?", required: false, defaultValue: false input "effect1Enabled", "bool", title: "Enable Effect Number 1 (Govee)?", required: false, defaultValue: false input "effect2Enabled", "bool", title: "Enable Effect Number 2 (Govee)?", required: false, defaultValue: false input "effect3Enabled", "bool", title: "Enable Effect Number 3 (Govee)?", required: false, defaultValue: false input "effect4Enabled", "bool", title: "Enable Effect Number 4 (Govee)?", required: false, defaultValue: false input "effect5Enabled", "bool", title: "Enable Effect Number 5 (Govee)?", required: false, defaultValue: false input "namedColor1Enabled", "bool", title: "Enable Named Color 1?", required: false, defaultValue: false input "namedColor2Enabled", "bool", title: "Enable Named Color 2?", required: false, defaultValue: false input "namedColor3Enabled", "bool", title: "Enable Named Color 3?", required: false, defaultValue: false input "namedColor4Enabled", "bool", title: "Enable Named Color 4?", required: false, defaultValue: false input "namedColor5Enabled", "bool", title: "Enable Named Color 5?", required: false, defaultValue: false } section ("Colors Enabled?") { input "holidayMode","bool", title: "Allow Enable/Disable for Each Color/Holiday Mode?", required: false, defaultValue: false input "redEnabled", "bool", title: "Enable Red?", required: false, defaultValue: true input "brickRedEnabled", "bool", title: "Enable Brick Red?", required: false, defaultValue: true input "safetyOrangeEnabled", "bool", title: "Enable Safety Orange?", required: false, defaultValue: true input "orangeEnabled", "bool", title: "Enable Orange?", required: false, defaultValue: true input "amberEnabled", "bool", title: "Enable Amber?", required: false, defaultValue: true input "yellowEnabled", "bool", title: "Enable Yellow?", required: false, defaultValue: true input "greenEnabled", "bool", title: "Enable Green?", required: false, defaultValue: true input "turquoiseEnabled", "bool", title: "Enable Turquoise?", required: false, defaultValue: true input "aquaEnabled", "bool", title: "Enable Aqua?", required: false, defaultValue: true input "navyBlueEnabled", "bool", title: "Enable Navy Blue?", required: false, defaultValue: true input "blueEnabled", "bool", title: "Enable Blue?", required: false, defaultValue: true input "indigoEnabled", "bool", title: "Enable Indigo?", required: false, defaultValue: true input "purpleEnabled", "bool", title: "Enable Purple?", required: false, defaultValue: true input "pinkEnabled", "bool", title: "Enable Pink?", required: false, defaultValue: true input "rasberryEnabled", "bool", title: "Enable Rasberry?", required: false, defaultValue: true input "whiteEnabled", "bool", title: "Enable White?", required: false, defaultValue: true input "slateBlueEnabled", "bool", title: "Enable Slate Blue?", required: false, defaultValue: true } section( "Notification options?" ) { input "sendPushMessage", "capability.notification", title: "Notification Devices: Hubitat PhoneApp or Pushover", multiple: true, required: false input("logLevel", "enum", title: "Logging Level (off,minimial,maximum) ?", options: ["off","minimal", "maximum"], required: true, defaultValue: "minimal") } } int getCycleTimeinSeconds() { def ctime = 1800 // default if not found 30 minutes if (settings.cycleTime != null) { switch(settings.cycleTime) { case "10 seconds": ctime = 10 break; case "20 seconds": ctime = 20 break; case "30 seconds": ctime = 30 break; case "45 seconds": ctime = 45 break; case "1 minute": ctime = 60 break; case "2 minutes": ctime = 120 break; case "5 minutes": ctime = 300 break; case "10 minutes": ctime = 600 break; case "15 minutes": ctime = 900 break; case "30 minutes": ctime = 1800 break; case "1 hour": ctime = 3600 break; case "3 hours": ctime = 10800 break; default: ctime = 1800 break; } // now check for problems in time and if so override def time1 = 0 def time2 = 0 if (settings.fadeOnTime != "Off") time1 = settings.fadeOnTime.toInteger() if (settings.fadeOffTime != "Off") time2 = settings.fadeOffTime.toInteger() if (ctime <= (time1 + time2)) { log.warn "Error in settings, the cycle Time of $settings.cycleTime is less than your total fade times of ${time1 + time2}!" log.warn "Overriding cycle time to the default 2 minutes!" app.updateSetting("cycleTime", [value:"2 minutes", type:"enum"]) state.cycleTime = ctime ctime = 120 } } return ctime } def installed() { unsubscribe() unschedule() if (hues) { TurnOff() } if (settings.enabled == true) { initialize() } // do event listening on switch whether enabled or not if ((enableswitch) && (hues)) { subscribe(enableswitch,"switch",EnableSwitchHandler) } } def updated() { unsubscribe() unschedule() if (hues) { // must always turn off here even if disabled, because this gets called when the switch disables and turns stuff off. TurnOffAlways() runIn(10,"TurnOffAlways") } if (settings.enabled == true) { initialize() } // do event listening on switch whether enabled or not if ((enableswitch) && (hues)) { subscribe(enableswitch,"switch",EnableSwitchHandler) } if (hues) { def currSwitches = hues.currentSwitch def onHues = currSwitches.findAll { switchVal -> switchVal == "on" ? true : false } def numberon = onHues.size(); def onstr = numberon.toString() if (getloglevel() > 1) log.debug "in updated on = $onstr" } } def EnableSwitchHandler(evt) { if (getloglevel() > 0) log.info "In Switch Handler: Switch changed state to: ${evt.value}" if (evt.value == "on") { if (getloglevel() > 0) log.info "Enabling App!" settings.enabled = true updated() // updated turns off so need to turn back on when switch tripped.. but also need to renable scheduling. TurnOn() } else { if (getloglevel() > o) "Disabling App!" settings.enabled = false updated() } } private def initialize() { state.version = "5.2" if (getloglevel() > 0) log.info(" in initialize() (app version ${state.version} for $app.label with settings: ${settings}") // for holiday. mode to work random must be on so if no turn on. if ((settings.holidayMode == true) && (settings.randomMode == false)) { if (getloglevel() > 0) log.info "Overriding and turning on random mode so holiday mode works correctly!" app.updateSetting("randomMode", [value:true, type:"bool"]) } unschedule() if(hues) { subscribe(hues, "switch.on", changeHandler) subscribe(location, "sunset", SunsetHandler) subscribe(location, "sunrise", SunriseHandler) // uses the run every instead of direct schedule to take load off of fixed times on hub def ct = getCycleTimeinSeconds() if (getloglevel() > 1) log.info "Cycle Time is ${settings.cycleTime}, ($ct)" switch (ct) { case "10": schedule("0/10 * * * * ? *", "changeHandler") break; case "15": if (getloglevel() > 0) log.info "Switching color every 15 seconds." schedule("0/15 * * * * ? *", "changeHandler") break; case "20": if (getloglevel() > 0) log.info "Switching color every 20 seconds." schedule("0/20 * * * * ? *", "changeHandler") break; case "30": if (getloglevel() > 0) log.info "Switching color every 3 seconds." schedule("0/30 * * * * ? *", "changeHandler") break; case "45": if (getloglevel() > 0) log.info "Switching color every 45 seconds." schedule("0/45 * * * * ? *", "changeHandler") break; case "60": if (getloglevel() > 0) log.info "Switching color every minute." schedule("0 */1 * * * ? *","changeHandler") break; case "120": if (getloglevel() > 0) log.info "Switching color every 2 minutes." schedule("0 */2 * * * ? *","changeHandler") break; case "300": if (getloglevel() > 0) log.info "Switching color every 5 minutes." runEvery5Minutes("changeHandler") break; case "600": if (getloglevel() > 0) log.info "Switching color every 10 minutes." runEvery10Minutes("changeHandler") break; case "900": if (getloglevel() > 0) log.info "Switching color every 15 minutes." runEvery15Minutes("changeHandler") break; case "1800": if (getloglevel() > 0) log.info "Switching color every 30 minutes." runEvery30Minutes("changeHandler") break; case "3600": if (getloglevel() > 0) log.info "Switching color every hour." runEvery1Hour("changeHandler") break; case "10800": if (getloglevel() > 0) log.info "Switching color every 3 hours" runEvery3Hours("changeHandler") break; default: if (getloglevel() > 0) log.info "Switching color every 30 minutes." runEvery30Minutes("changeHandler") break; } def colorList1 = hubitat.helper.ColorUtils.rgbToHSV(hubitat.helper.ColorUtils.hexToRGB(customColor1)) def colorList2 = hubitat.helper.ColorUtils.rgbToHSV(hubitat.helper.ColorUtils.hexToRGB(customColor2)) def colorList3 = hubitat.helper.ColorUtils.rgbToHSV(hubitat.helper.ColorUtils.hexToRGB(customColor3)) def colorList4 = hubitat.helper.ColorUtils.rgbToHSV(hubitat.helper.ColorUtils.hexToRGB(customColor4)) if (getloglevel() > 0) { log.info "Custom Color 1 - ${colorList1}" log.info "Custom Color 2 - ${colorList2}" log.info "Custom Color 3 - ${colorList3}" log.info "Custom Color 4 - ${colorList4}" } state.custom1Hue = colorList1.get(0) state.custom1Saturation = colorList1.get(1) state.custom1Level = colorList1.get(2) state.custom2Hue = colorList2.get(0) state.custom2Saturation = colorList2.get(1) state.custom2Level = colorList2.get(2) state.custom3Hue = colorList3.get(0) state.custom3Saturation = colorList3.get(1) state.custom3Level = colorList3.get(2) state.custom4Hue = colorList4.get(0) state.custom4Saturation = colorList4.get(1) state.custom4Level = colorList4.get(2) state.effect1 = effect1 state.effect2 = effect2 state.effect3 = effect3 state.effect4 = effect4 state.effect5 = effect5 // handle named colors similiarly if (namedColor1 && namedColor1Enabled) { def namedList1 = getRGBfromName(namedColor1) state.named1Color = namedColor1 state.named1Hue = namedList1.get(0) state.named1Saturation = namedList1.get(1) state.named1Level = namedList1.get(2) if (getloglevel() > 0) log.info "Named Color 1 ${namedColor1} - ${namedList1}" } if (namedColor2 && namedColor2Enabled) { def namedList2 = getRGBfromName(namedColor2) state.named2Color = namedColor2 state.named2Hue = namedList2.get(0) state.named2Saturation = namedList2.get(1) state.named2Level = namedList2.get(2) if (getloglevel() > 0) log.info "Named Color 2 ${namedColor2} - ${namedList2}" } if (namedColor3 && namedColor3Enabled) { def namedList3 = getRGBfromName(namedColor3) state.named3Color = namedColor3 state.named3Hue = namedList3.get(0) state.named3Saturation = namedList3.get(1) state.named3Level = namedList3.get(2) if (getloglevel() > 0) log.info "Named Color 3 ${namedColor3} - ${namedList3}" } if (namedColor4 && namedColor4Enabled) { def namedList4 = getRGBfromName(namedColor4) state.named4Color = namedColor4 state.named4Hue = namedList4.get(0) state.named4Saturation = namedList4.get(1) state.named4Level = namedList4.get(2) if (getloglevel() > 0) log.info "Named Color 4 ${namedColor4} - ${namedList4}" } if (namedColor5 && namedColor5Enabled) { def namedList5 = getRGBfromName(namedColor5) state.named5Color = namedColor5 state.named5Hue = namedList5.get(0) state.named5Saturation = namedList5.get(1) state.named5Level = namedList5.get(2) if (getloglevel() > 0) log.info "Named Color 5 ${namedColor5} - ${namedList5}" } subscribe(app,changeHandler) state.nextOnTime = 0 state.nextOffTime = 0 // subscribe(location, "sunsetTime", scheduleNextSunset) // sunset handled automaticall need next sunrise to handle offset subscribe(location, "sunriseTime", scheduleNextSunrise) scheduleNextSunrise() // rather than schedule a cron entry, fire a status update a little bit in the future recursively // scheduleNext() state.currentColor = "None" state.colorsEnabled = 0 state.colorArray = [:] // now initialize the color array and random value initColorArray() } } def SunriseHandler(evt) { TurnOff() scheduleNextSunrise() } def SunsetHandler(evt) { TurnOn() scheduleNextSunrise() } def TurnOffAgain() { hues.off() } def TurnOff() { if (getloglevel() > 0) log.info "In turn off" if (settings.enabled == true) { def appLabel = app.getLabel() mysend("$appLabel: Turning Off!") } hues.off() // incase light was in a cycle of dimming or brightening the turn off can be ignored schedule again in case runIn(30,"TurnOffAgain") } def TurnOffAlways() { def appLabel = app.getLabel() mysend("$appLabel: Turning Off!") hues.off() // incase light was in a cycle of dimming or brightening the turn off can be ignored schedule again in case runIn(30,"TurnOffAgain") } def TurnOn() { if (getloglevel() > 0) log.info "In turn on" if (settings.enabled == true) { def appLabel = app.getLabel() mysend("$appLabel: Turning On!") hues.on() } } def scheduleNextSunrise(evt) { if (getloglevel() > 1) log.debug "In schedule next sunrise" def int sunriseoffset = settings.offset.toInteger() if (getloglevel() > 1) log.debug "got sunrise offset = $sunriseoffset" // get sunrise and sunset times def sunRiseSet = getSunriseAndSunset() def sunriseTime = sunRiseSet.sunrise def sunsetTime = sunRiseSet.sunset if (getloglevel() > 0) { log.info "sunrise time ${sunriseTime}" log.info "sunset time ${sunsetTime}" } //get the Date value for the string //def sunriseTime = Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", sunriseTime) // sunrise returns today so double check we are not getting todays time but tomarrow // if we are before sunset time we are too early // bug in get sunrise time somethigs shows todays even though we are passed it.. sometimes // shows the next one.. Think it has to do with timezone offset.. so compare to local time to see // which case we have and if we need to add 24 hours or not def currentTime = new Date(now()) // if current time is greater than sunsirse we are today no tomorrow so add 24 hours. if(currentTime.time > sunriseTime.time) { if (getloglevel() > 1) log.info "Adding a day as sunrise time is still today!" sunriseTime = new Date(sunriseTime.time + (24 * 60 * 60 * 1000)) } //calculate the offset def timeBeforeSunrise = new Date(sunriseTime.time + (sunriseoffset * 60 * 60 * 1000)) if (getloglevel() > 0) log.info "Scheduling for: $timeBeforeSunrise (sunrise is $sunriseTime)" //schedule this to run one time if (state.nextOffTime != timeBeforeSunrise) { if (getloglevel() > 1) log.debug "Scheduling it!" runOnce(timeBeforeSunrise, TurnOff) state.nextOffTime = timeBeforeSunrise } } def changeHandler(evt) { //log.debug "in change handler" // only do stuff if either switch is on (turns off at sunrise) or turned on manually if (hues) { def currSwitches = hues.currentSwitch def onHues = currSwitches.findAll { switchVal -> switchVal == "on" ? true : false } def numberon = onHues.size(); def onstr = numberon.toString() if ((getloglevel() > 1) && (settings.enabled == true)) log.debug "found $onstr that were on!" if (getloglevel() > 1) { log.debug "holiday mode = $settings.holidayMode" log.debug "Random mode = $settings.randomMode" } if ((numberon > 0) && (settings.enabled == true)) { def newColor = "" if (settings.randomMode == true) { // lgk define alternate color array if holiday mode enabled if (settings.holidayMode == true) { if (getloglevel() > 1) log.debug "Holiday Mode = On, Random On, getting count of colors Enabled." // now define new array def enabledColorArray = state.colorArray def int colorsEnabled = state.colorsEnabled if (getloglevel() > 1) { log.debug "Enabled Color Count = $colorsEnabled" log.debug "Enabled Color Array = $enabledColorArray" } if ((numberon > 1) && (settings.individualControl == true)) { // this needs to be done here outside the loop and not in the individual fixture loop becuase of the pauseExecution otherwise fixtures // will be out of sync. if (settings.fadeOffTime != "Off") { def fOffTime = settings.fadeOffTime.toInteger() if (getloglevel() > 1) log.debug "Fading off in $fOffTime seconds before changing color." hues*.setLevel(1,fOffTime) pauseExecution(fOffTime*1000) } for (def i=0; i 1) log.debug "Colors Enabled: $colorsEnabled, Hue: $i, Random Number = $nextValue" newColor = enabledColorArray[nextValue] def rv = sendcolor(newColor,i) if (getloglevel() > 0) { if (rv == "NA") log.info("$app.label: Hue:$i - Setting Color to $newColor") else log.info("$app.label: Hue:$i - Setting Color to $newColor ($rv)") } } } // do each individually else { def int nextValue = new Random().nextInt(colorsEnabled) if (getloglevel() > 1) log.debug "Colors Enabled: $colorsEnabled, Random Number = $nextValue" newColor = enabledColorArray[nextValue] //hues.on() def rv = sendcolor(newColor) if (getloglevel() > 0) { if (rv == "NA") log.info("$app.label: Setting Color to $newColor") else log.info("$app.label: Setting Color to $newColor ($rv)") } } } // holiday mode on else { // not holiday mode but random if ((numberon > 1) && (settings.individualControl == true)) { if (getloglevel() > 1) log.debug "Non Holiday, Random, Separated case" // this needs to be done here outside the loop and not in the individual fixture loop becuase of the pauseExecution otherwise fixtures // will be out of sync. if (settings.fadeOffTime != "Off") { def fOffTime = settings.fadeOffTime.toInteger() if (getloglevel() > 1) log.debug "Fading off in $fOffTime seconds before changing color." hues*.setLevel(1,fOffTime) pauseExecution(fOffTime*1000) } for (def i=0; i 1) log.debug "Hue: $i, Random Number = $nextValue" newColor = colorArray[nextValue] def rv = sendcolor(newColor,i) if (getloglevel() > 0) { if (rv == "NA") log.info("$app.label: Hue:$i - Setting Color to $newColor") else log.info("$app.label: Hue:$i - Setting Color to $newColor ($rv)") } } } // do each individually else { def colorArray = state.colorArray def maxColors = state.colorsEnabled if (getloglevel() > 1) log.debug "Holiday mode is not on." if (getloglevel() > 1) log.debug "$colorArray $maxColors" def int nextValue = new Random().nextInt(maxColors) if (getloglevel() > 1) log.debug "Random Number = $nextValue" newColor = colorArray[nextValue] //hues.on() def rv = sendcolor(newColor) if (getloglevel() > 0) { if (rv == "NA") log.info("$app.label: Setting Color to $newColor") else log.info("$app.label: Setting Color to $newColor ($rv)") } } } } else { // not random // note custom colors not used in raindbow ie not random mode.2 def currentColor = state.currentColor if (getloglevel() > 1) log.debug " in changeHandler non-random case, got current color = $currentColor" switch(currentColor) { case "Red": newColor="Brick Red" break; case "Brick Red": newColor = "Safety Orange" break; case "Safety Orange": newColor = "Orange" break; case "Orange": newColor = "Amber" break; case "Amber": newColor = "Yellow" break; case "Yellow": newColor = "Green" break; case "Green": newColor = "Turquoise" break; case "Turquoise": newColor = "Aqua" break; case "Aqua": newColor = "Navy Blue" break; case "Navy Blue": newColor = "Blue" break; case "Blue": newColor = "Indigo" break; case "Indigo": newColor = "Purple" break; case "Purple": newColor = "Pink" break; case "Pink": newColor = "Rasberry" break; case "Rasberry": newColor = "White" break; case "White": newColor = "Red" break; default: if (getloglevel() > 1) log.debug "in default" newColor = "Red" break; } if (getloglevel() > 1) log.debug "After Check new color = $newColor" //hues.on() sendcolor(newColor) } // end random or not } } } def sendcolor(color) { //log.debug "In send color" //Initialize the hue and saturation def hueColor = 0 def saturation = 100 def doEffect = false def effect = 101 def rv = "NA" //Use the user specified brightness level. If they exceeded the min or max values, overwrite the brightness with the actual min/max if (brightnessLevel<1) { brightnessLevel=1 } else if (brightnessLevel>100) { brightnessLevel=100 } blevel = brightnessLevel //Set the hue and saturation for the specified color. switch(color) { case "White": hueColor = 0 saturation = 0 break; case "Daylight": hueColor = 53 saturation = 91 break; case "Soft White": hueColor = 23 saturation = 56 break; case "Warm White": hueColor = 20 saturation = 80 break; case "Navy Blue": hueColor = 61 break; case "Blue": hueColor = 65 break; case "Green": hueColor = 35 break; case "Turquoise": hueColor = 47 break; case "Aqua": hueColor = 50 break; case "Amber": hueColor = 13 break; case "Yellow": //hueColor = 25 hueColor = 17 break; case "Safety Orange": hueColor = 7 break; case "Orange": hueColor = 10 break; case "Indigo": hueColor = 73 break; case "Purple": hueColor = 82 saturation = 100 break; case "Pink": hueColor = 90.78 saturation = 67.84 break; case "Rasberry": hueColor = 94 break; case "Red": hueColor = 0 break; case "Brick Red": hueColor = 4 break; case "Slate Blue": hueColor = 69 saturation = 39 break; case "Custom1": hueColor = state.custom1Hue saturation = state.custom1Saturation blevel = state.custom1Level rv = "[" + hueColor.toString() + ", " + saturation.toString() + ", " + blevel.toString() + "]" break; case "Custom2": hueColor = state.custom2Hue saturation = state.custom2Saturation blevel = state.custom2Level rv = "[" + hueColor.toString() + ", " + saturation.toString() + ", " + blevel.toString() + "]" break; case "Custom3": hueColor = state.custom3Hue saturation = state.custom3Saturation blevel = state.custom3Level rv = "[" + hueColor.toString() + ", " + saturation.toString() + ", " + blevel.toString() + "]" break; case "Custom4": hueColor = state.custom4Hue saturation = state.custom4Saturation blevel = state.custom4Level rv = "[" + hueColor.toString() + ", " + saturation.toString() + ", " + blevel.toString() + "]" break; case "NamedColor1": hueColor = state.named1Hue saturation = state.named1Saturation blevel = state.named1Level rv = state.named1Color break; case "NamedColor2": hueColor = state.named2Hue saturation = state.named2Saturation blevel = state.named2Level rv = state.named2Color break; case "NamedColor3": hueColor = state.named3Hue saturation = state.named3Saturation blevel = state.named3Level rv = state.named3Color break; case "NamedColor4": hueColor = state.named4Hue saturation = state.named4Saturation blevel = state.named4Level rv = state.named4Color break; case "NamedColor5": hueColor = state.named5Hue saturation = state.named5Saturation blevel = state.named5Level rv = state.named5Color break; case "Random1": case "Random2": case "Random3": case "Random4": case "Random5": // get true random hue 1- 100 def int rnum = new Random().nextInt(100) def int snum = new Random().nextInt(70)+30 // most colors have a sat. above 30 so dont do lower. if (getloglevel() > 1) log.debug "Generated Random hue: $rnum, saturation: $snum" hueColor = rnum saturation = snum blevel = 100 rv = "[" + rnum.toString() + ", " + snum.toString() + ", 100]" break; case "Effect1": effect = state.effect1 doEffect = true rv = effect.toString() break; case "Effect2": effect = state.effect2 doEffect = true rv = effect.toString() break; case "Effect3": effect = state.effect3 doEffect = true rv = effect.toString() break; case "Effect4": effect = state.effect4 doEffect = true rv = effect.toString() break; case "Effect5": effect = state.effect5 doEffect = true rv = effect.toString() break; } //Change the color of the light if (blevel == null) { log.warn "Error: brightness level was 0 reseting to 100" blevel = 100 } if (settings.fadeOnTime == "Off") { if (settings.fadeOffTime != "Off") { // case with only fade off.. def fOffTime = settings.fadeOffTime.toInteger() if (getloglevel() > 1) log.debug "Fading off in $fOffTime seconds before changing color." hues*.setLevel(1,fOffTime) pauseExecution(fOffTime*1000) } if (doEffect == true) { if (getloglevel() > 1) log.info "Effect: $effect" hues*.setEffect(effect) } else { def newValue = [hue: hueColor, saturation: saturation, level: blevel] hues*.setColor(newValue) state.currentColor = color mysend("$app.label: Setting Color = $color") if (getloglevel() > 1) log.debug "$app.label: Setting Color = $color" } } else { if (settings.fadeOffTime != "Off") { // fade out first before changing color if enabled def fOffTime = settings.fadeOffTime.toInteger() if (getloglevel() > 1) log.debug "Fading off in $fOffTime seconds before changing color." hues*.setLevel(1,fOffTime) pauseExecution(fOffTime*1000) } else { if (settings.fadeOnTime != "Off") hues*.setLevel(1,0) } if (doEffect == true) { if (getloglevel() > 1) log.info "Effect: $effect" hues*.setEffect(effect) } else { // now turn on at level 1 and fade up def fOnTime = settings.fadeOnTime.toInteger() if (getloglevel() > 1) { log.debug "Turning on at level 1, then fading up to $blevel in $fOnTime seconds." log.debug "new hue: $hueColor, new staturation: $saturation, new Level: $blevel" } def newValue = [hue: hueColor, saturation: saturation, level: 1] state.currentColor = color hues*.setColor(newValue) hues*.setLevel(blevel,fOnTime) } } return rv } def sendcolor(color,which) { if (getloglevel() > 1) log.debug "In send color for hue $which" //Initialize the hue and saturation def hueColor = 0 def saturation = 100 def doEffect = false def effect = 101 def rv = "NA" //Use the user specified brightness level. If they exceeded the min or max values, overwrite the brightness with the actual min/max if (brightnessLevel<1) { brightnessLevel=1 } else if (brightnessLevel>100) { brightnessLevel=100 } blevel = brightnessLevel //Set the hue and saturation for the specified color. switch(color) { case "White": hueColor = 0 saturation = 0 break; case "Daylight": hueColor = 53 saturation = 91 break; case "Soft White": hueColor = 23 saturation = 56 break; case "Warm White": hueColor = 20 saturation = 80 break; case "Navy Blue": hueColor = 61 break; case "Blue": hueColor = 65 break; case "Green": hueColor = 33 break; case "Turquoise": hueColor = 47 break; case "Aqua": hueColor = 50 break; case "Amber": hueColor = 13 break; case "Yellow": //hueColor = 25 hueColor = 17 break; case "Safety Orange": hueColor = 7 break; case "Orange": hueColor = 10 break; case "Indigo": hueColor = 73 break; case "Purple": hueColor = 82 saturation = 100 break; case "Pink": hueColor = 90.78 saturation = 67.84 break; case "Rasberry": hueColor = 94 break; case "Red": hueColor = 0 break; case "Brick Red": hueColor = 4 break; case "Slate Blue": hueColor = 69 saturation = 39 break; case "Custom1": hueColor = state.custom1Hue saturation = state.custom1Saturation blevel = state.custom1Level rv = "[" + hueColor.toString() + ", " + saturation.toString() + ", " + blevel.toString() + "]" break; case "Custom2": hueColor = state.custom2Hue saturation = state.custom2Saturation blevel = state.custom2Level rv = "[" + hueColor.toString() + ", " + saturation.toString() + ", " + blevel.toString() + "]" break; case "Custom3": hueColor = state.custom3Hue saturation = state.custom3Saturation blevel = state.custom3Level rv = "[" + hueColor.toString() + ", " + saturation.toString() + ", " + blevel.toString() + "]" break; case "Custom4": hueColor = state.custom4Hue saturation = state.custom4Saturation blevel = state.custom4Level rv = "[" + hueColor.toString() + ", " + saturation.toString() + ", " + blevel.toString() + "]" break; case "NamedColor1": hueColor = state.named1Hue saturation = state.named1Saturation blevel = state.named1Level rv = state.named1Color break; case "NamedColor2": hueColor = state.named2Hue saturation = state.named2Saturation blevel = state.named2Level rv = state.named2Color break; case "NamedColor3": hueColor = state.named3Hue saturation = state.named3Saturation blevel = state.named3Level rv = state.named3Color break; case "NamedColor4": hueColor = state.named4Hue saturation = state.named4Saturation blevel = state.named4Level rv = state.named4Color break; case "NamedColor5": hueColor = state.named5Hue saturation = state.named5Saturation blevel = state.named5Level rv = state.named5Color break; case "Random1": case "Random2": case "Random3": case "Random4": case "Random5": // get true random hue 1- 100 def int rnum = new Random().nextInt(100) def int snum = new Random().nextInt(70)+30 // most colors have a sat. above 30 so dont do lower. if (getloglevel() > 1) log.debug "Generated Random hue: $rnum, saturation: $snum" hueColor = rnum saturation = snum blevel = 100 rv = "[" + rnum.toString() + ", " + snum.toString() + ", 100]" break; case "Effect1": effect = state.effect1 doEffect = true rv = effect.toString() break; case "Effect2": effect = state.effect2 doEffect = true rv = effect.toString() break; case "Effect3": effect = state.effect3 doEffect = true rv = effect.toString() break; case "Effect4": effect = state.effect4 doEffect = true rv = effect.toString() break; case "Effect5": effect = state.effect5 doEffect = true rv = effect.toString() break; } if (blevel == null) { log.warn "Error: brlighnes level was 0 reseting to 100" blevel = 100 } if (settings.fadeOnTime == "Off") { if (doEffect == true) { if (getloglevel() > 1) log.info "Effect: $effect" hues*.setEffect(effect) } else { //Change the color of the light def newValue = [hue: hueColor, saturation: saturation, level: blevel] hues[which].setColor(newValue) state.currentColor = color mysend("$app.label: hue: $which, Setting Color = $color") if (getloglevel() > 1) log.info "$app.label: hue: $which Setting Color = $color" } } else { //cannot do fade off here as we need to pause execution for the fade off time before turning back on the other color and with each fixture being separate // this is done prior to the call for all fixtures if necessary not here in the looop // if (settings.fadeOnTime != "Off") hues[which].setLevel(1,0) // now turn on at level 1 and fade up def fOnTime = settings.fadeOnTime.toInteger() if (getloglevel() > 1) { log.debug "Turning fixture $which on at level 1, then fading up to $blevel in $fOnTime seconds." log.debug "new hue: $hueColor, new staturation: $saturation, new Level: $blevel" } if (doEffect == true) { if (getloglevel() > 1) log.info "Effect: $effect" hues*.setEffect(effect) } else { def newValue = [hue: hueColor, saturation: saturation, level: 1] hues[which].setColor(newValue) hues[which].setLevel(blevel,fOnTime) } } return rv } private mysend(msg) { // check that contact book is enabled and recipients selected if (location.contactBookEnabled && recipients) { if (getloglevel() > 1) log.info("sending notifications to: ${recipients?.size()}") sendNotificationToContacts(msg, recipients) } else { if (sendPushMessage) { if (getloglevel() > 1) log.info("Sending Push Notification...") sendPushMessage.deviceNotification(msg) } } } def initColorArray() { if (getloglevel() > 1) log.debug "In initColorArray" if (settings.holidayMode == true) { if (getloglevel() > 1) log.debug "Holiday Mode = On, getting count of colors Enabled." // now define new array def enabledColorArray = [] if (redEnabled == true) enabledColorArray << "Red" if (brickRedEnabled == true) enabledColorArray << "Brick Red" if (safetyOrangeEnabled == true) enabledColorArray << "Safety Orange" if (orangeEnabled == true) enabledColorArray << "Orange" if (amberEnabled == true) enabledColorArray << "Amber" if (yellowEnabled == true) enabledColorArray << "Yellow" if (greenEnabled == true) enabledColorArray << "Green" if (turquoiseEnabled == true) enabledColorArray << "Turquoise" if (aquaEnabled == true) enabledColorArray << "Aqua" if (navyBlueEnabled == true) enabledColorArray << "Navy Blue" if (blueEnabled == true) enabledColorArray << "Blue" if (indigoEnabled == true) enabledColorArray << "Indigo" if (purpleEnabled == true) enabledColorArray << "Purple" if (pinkEnabled == true) enabledColorArray << "Pink" if (rasberryEnabled == true) enabledColorArray << "Rasberry" if (whiteEnabled == true) enabledColorArray << "White" if (slateBlueEnabled == true) enabledColorArray << "Slate Blue" if (custom1Enabled == true) enabledColorArray << "Custom1" if (custom2Enabled == true) enabledColorArray << "Custom2" if (custom3Enabled == true) enabledColorArray << "Custom3" if (custom4Enabled == true) enabledColorArray << "Custom4" if (random1Enabled == true) enabledColorArray << "Random1" if (random2Enabled == true) enabledColorArray << "Random2" if (random3Enabled == true) enabledColorArray << "Random3" if (random4Enabled == true) enabledColorArray << "Random4" if (random5Enabled == true) enabledColorArray << "Random5" if (effect1Enabled == true) enabledColorArray << "Effect1" if (effect2Enabled == true) enabledColorArray << "Effect2" if (effect3Enabled == true) enabledColorArray << "Effect3" if (effect4Enabled == true) enabledColorArray << "Effect4" if (effect5Enabled == true) enabledColorArray << "Effect5" if ((namedColor1Enabled == true) && (namedColor1 != null)) enabledColorArray << "NamedColor1" if ((namedColor2Enabled == true) && (namedColor2 != null)) enabledColorArray << "NamedColor2" if ((namedColor3Enabled == true) && (namedColor3 != null)) enabledColorArray << "NamedColor3" if ((namedColor4Enabled == true) && (namedColor4 != null)) enabledColorArray << "NamedColor4" if ((namedColor5Enabled == true) && (namedColor5 != null)) enabledColorArray << "NamedColor5" def int colorsEnabled = enabledColorArray.size if (getloglevel() > 1) { log.debug "Enabled Color Count = $colorsEnabled" log.debug "Enabled Color Array = $enabledColorArray" } state.colorsEnabled = colorsEnabled state.colorArray = enabledColorArray if (getloglevel() == 1) log.debug "Color array = $enabledColorArray, maxColors = $colorsEnabled" } // holiday mode else { if (getloglevel() > 1) log.debug "Holiday Mode = On, getting count of colors Enabled." def maxColors = 17 def colorArray = ["Red","Brick Red","Safety Orange","Orange","Amber","Yellow","Green","Turquoise","Aqua","Navy Blue","Blue","Indigo","Purple","Pink","Rasberry","White","Slate Blue"] if (custom1Enabled == true) { ++maxColors colorArray[maxColors-1] = "Custom1" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (custom2Enabled == true) { ++maxColors colorArray[maxColors-1] = "Custom2" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (custom3Enabled == true) { ++maxColors colorArray[maxColors-1] = "Custom3" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (custom4Enabled == true) { ++maxColors colorArray[maxColors-1] = "Custom4" if (getloglevel() > 1) log.debug "color arrary = $colorArray, maxColors = $maxColors" } if (random1Enabled == true) { ++maxColors colorArray[maxColors-1] = "Random1" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (random2Enabled == true) { ++maxColors colorArray[maxColors-1] = "Random2" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (random3Enabled == true) { ++maxColors colorArray[maxColors-1] = "Random3" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (random4Enabled == true) { ++maxColors colorArray[maxColors-1] = "Random4" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (random5Enabled == true) { ++maxColors colorArray[maxColors-1] = "Random5" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (effect1Enabled == true) { ++maxColors colorArray[maxColors-1] = "Effect1" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (effect2Enabled == true) { ++maxColors colorArray[maxColors-1] = "Effect2" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (effect3Enabled == true) { ++maxColors colorArray[maxColors-1] = "Effect3" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (effect4Enabled == true) { ++maxColors colorArray[maxColors-1] = "Effect4" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if (effect5Enabled == true) { ++maxColors colorArray[maxColors-1] = "Effect5" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if ((namedColor1Enabled == true) && (namedColor1 != null)) { ++maxColors colorArray[maxColors-1] = "NamedColor1" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if ((namedColor2Enabled == true) && (namedColor2 != null)) { ++maxColors colorArray[maxColors-1] = "NamedColor2" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" if ((namedColor3Enabled == true) && (namedColor3 != null)) { ++maxColors colorArray[maxColors-1] = "NamedColor3" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if ((namedColor4Enabled == true) && (namedColor4 != null)) { ++maxColors colorArray[maxColors-1] = "NamedColor4" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } if ((namedColor5Enabled == true) && (namedColor5 != null)) { ++maxColors colorArray[maxColors-1] = "NamedColor5" if (getloglevel() > 1) log.debug "color array = $colorArray, maxColors = $maxColors" } } // else state.colorsEnabled = maxColors state.colorArray = colorArray if (getloglevel() == 1) log.debug "Color array = $colorArray, maxColors = $maxColors" } } def getloglevel() { if (logLevel == "off") return(0) else if (logLevel == "minimal") return(1) else return(2) } @Field static List colorNames = [ [name:"Alice Blue", r:0xF0, g:0xF8, b:0xFF], [name:"Antique White", r:0xFA, g:0xEB, b:0xD7], [name:"Aqua", r:0x00, g:0xFF, b:0xFF], // Matter Spec 11.1.4.2 [name:"Aquamarine", r:0x7F, g:0xFF, b:0xD4], [name:"Azure", r:0xF0, g:0xFF, b:0xFF], [name:"Beige", r:0xF5, g:0xF5, b:0xDC], [name:"Bisque", r:0xFF, g:0xE4, b:0xC4], [name:"Black", r:0x00, g:0x00, b:0x00], // Matter Spec 11.1.4.2 [name:"Blanched Almond", r:0xFF, g:0xEB, b:0xCD], [name:"Blue", r:0x00, g:0x00, b:0xFF], // Matter Spec 11.1.4.2 [name:"Blue Violet", r:0x8A, g:0x2B, b:0xE2], [name:"Brown", r:0xA5, g:0x2A, b:0x2A], [name:"Burly Wood", r:0xDE, g:0xB8, b:0x87], [name:"Cadet Blue", r:0x5F, g:0x9E, b:0xA0], [name:"Chartreuse", r:0x7F, g:0xFF, b:0x00], [name:"Chocolate", r:0xD2, g:0x69, b:0x1E], [name:"Coral", r:0xFF, g:0x7F, b:0x50], [name:"Cornflower Blue", r:0x64, g:0x95, b:0xED], [name:"Cornsilk", r:0xFF, g:0xF8, b:0xDC], [name:"Crimson", r:0xDC, g:0x14, b:0x3C], [name:"Cyan", r:0x00, g:0xFF, b:0xFF], [name:"Dark Blue", r:0x00, g:0x00, b:0x8B], [name:"Dark Cyan", r:0x00, g:0x8B, b:0x8B], [name:"Dark Goldenrod", r:0xB8, g:0x86, b:0x0B], [name:"Dark Gray", r:0xA9, g:0xA9, b:0xA9], [name:"Dark Green", r:0x00, g:0x64, b:0x00], [name:"Dark Khaki", r:0xBD, g:0xB7, b:0x6B], [name:"Dark Magenta", r:0x8B, g:0x00, b:0x8B], [name:"Dark Olive Green", r:0x55, g:0x6B, b:0x2F], [name:"Dark Orange", r:0xFF, g:0x8C, b:0x00], [name:"Dark Orchid", r:0x99, g:0x32, b:0xCC], [name:"Dark Red", r:0x8B, g:0x00, b:0x00], [name:"Dark Salmon", r:0xE9, g:0x96, b:0x7A], [name:"Dark Sea Green", r:0x8F, g:0xBC, b:0x8F], [name:"Dark Slate Blue", r:0x48, g:0x3D, b:0x8B], [name:"Dark Slate Gray", r:0x2F, g:0x4F, b:0x4F], [name:"Dark Turquoise", r:0x00, g:0xCE, b:0xD1], [name:"Dark Violet", r:0x94, g:0x00, b:0xD3], [name:"Deep Pink", r:0xFF, g:0x14, b:0x93], [name:"Deep Sky Blue", r:0x00, g:0xBF, b:0xFF], [name:"Dim Gray", r:0x69, g:0x69, b:0x69], [name:"Dodger Blue", r:0x1E, g:0x90, b:0xFF], [name:"Fire Brick", r:0xB2, g:0x22, b:0x22], [name:"Floral White", r:0xFF, g:0xFA, b:0xF0], [name:"Forest Green", r:0x22, g:0x8B, b:0x22], [name:"Fuchsia", r:0xFF, g:0x00, b:0xFF], // Matter Spec 11.1.4.2 [name:"Gainsboro", r:0xDC, g:0xDC, b:0xDC], [name:"Ghost White", r:0xF8, g:0xF8, b:0xFF], [name:"Gold", r:0xFF, g:0xD7, b:0x00], [name:"Goldenrod", r:0xDA, g:0xA5, b:0x20], [name:"Gray", r:0x80, g:0x80, b:0x80], // Matter Spec 11.1.4.2 [name:"Green", r:0x00, g:0x80, b:0x00], // Matter Spec 11.1.4.2 [name:"Green Yellow", r:0xAD, g:0xFF, b:0x2F], [name:"Honey Dew", r:0xF0, g:0xFF, b:0xF0], [name:"Hot Pink", r:0xFF, g:0x69, b:0xB4], [name:"Indian Red", r:0xCD, g:0x5C, b:0x5C], [name:"Indigo", r:0x4B, g:0x00, b:0x82], [name:"Ivory", r:0xFF, g:0xFF, b:0xF0], [name:"Khaki", r:0xF0, g:0xE6, b:0x8C], [name:"Lavender", r:0xE6, g:0xE6, b:0xFA], [name:"Lavender Blush", r:0xFF, g:0xF0, b:0xF5], [name:"Lawn Green", r:0x7C, g:0xFC, b:0x00], [name:"Lemon Chiffon", r:0xFF, g:0xFA, b:0xCD], [name:"Light Blue", r:0xAD, g:0xD8, b:0xE6], [name:"Light Coral", r:0xF0, g:0x80, b:0x80], [name:"Light Cyan", r:0xE0, g:0xFF, b:0xFF], [name:"Light Goldenrod Yellow", r:0xFA, g:0xFA, b:0xD2], [name:"Light Gray", r:0xD3, g:0xD3, b:0xD3], [name:"Light Green", r:0x90, g:0xEE, b:0x90], [name:"Light Pink", r:0xFF, g:0xB6, b:0xC1], [name:"Light Salmon", r:0xFF, g:0xA0, b:0x7A], [name:"Light SeaGreen", r:0x20, g:0xB2, b:0xAA], [name:"Light SkyBlue", r:0x87, g:0xCE, b:0xFA], [name:"Light SlateGray", r:0x77, g:0x88, b:0x99], [name:"Light SteelBlue", r:0xB0, g:0xC4, b:0xDE], [name:"Light Yellow", r:0xFF, g:0xFF, b:0xE0], [name:"Lime", r:0x00, g:0xFF, b:0x00], // Matter Spec 11.1.4.2 [name:"LimeGreen", r:0x32, g:0xCD, b:0x32], [name:"Linen", r:0xFA, g:0xF0, b:0xE6], [name:"Magenta", r:0xFF, g:0x00, b:0xFF], [name:"Maroon", r:0x80, g:0x00, b:0x00], // Matter Spec 11.1.4.2 - Error in Matter Spec. 1.2 - Purple / Maroon are set the same in the spec! Value here is correct! [name:"Medium Aqua Marine", r:0x66, g:0xCD, b:0xAA], [name:"Medium Blue", r:0x00, g:0x00, b:0xCD], [name:"Medium Orchid", r:0xBA, g:0x55, b:0xD3], [name:"Medium Purple", r:0x93, g:0x70, b:0xDB], [name:"Medium Sea Green", r:0x3C, g:0xB3, b:0x71], [name:"Medium Slate Blue", r:0x7B, g:0x68, b:0xEE], [name:"Medium Spring Green", r:0x00, g:0xFA, b:0x9A], [name:"Medium Turquoise", r:0x48, g:0xD1, b:0xCC], [name:"Medium Violet Red", r:0xC7, g:0x15, b:0x85], [name:"Midnight Blue", r:0x19, g:0x19, b:0x70], [name:"Mint Cream", r:0xF5, g:0xFF, b:0xFA], [name:"Misty Rose", r:0xFF, g:0xE4, b:0xE1], [name:"Moccasin", r:0xFF, g:0xE4, b:0xB5], [name:"Navajo White", r:0xFF, g:0xDE, b:0xAD], [name:"Navy", r:0x00, g:0x00, b:0x00], // Matter Spec 11.1.4.2 [name:"Old Lace", r:0xFD, g:0xF5, b:0xE6], [name:"Olive", r:0x80, g:0x80, b:0x00], // Matter Spec 11.1.4.2 [name:"Olive Drab", r:0x6B, g:0x8E, b:0x23], [name:"Orange", r:0xFF, g:0xA5, b:0x00], [name:"Orange Red", r:0xFF, g:0x45, b:0x00], [name:"Orchid", r:0xDA, g:0x70, b:0xD6], [name:"Pale Goldenrod", r:0xEE, g:0xE8, b:0xAA], [name:"Pale Green", r:0x98, g:0xFB, b:0x98], [name:"Pale Turquoise", r:0xAF, g:0xEE, b:0xEE], [name:"Pale Violet Red", r:0xDB, g:0x70, b:0x93], [name:"Papaya Whip", r:0xFF, g:0xEF, b:0xD5], [name:"Peach Puff", r:0xFF, g:0xDA, b:0xB9], [name:"Peru", r:0xCD, g:0x85, b:0x3F], [name:"Pink", r:0xFF, g:0xC0, b:0xCB], [name:"Plum", r:0xDD, g:0xA0, b:0xDD], [name:"Powder Blue", r:0xB0, g:0xE0, b:0xE6], [name:"Purple", r:0x80, g:0x00, b:0x80], // Matter Spec 11.1.4.2 [name:"Red", r:0xFF, g:0x00, b:0x00], // Matter Spec 11.1.4.2 [name:"Rosy Brown", r:0xBC, g:0x8F, b:0x8F], [name:"Royal Blue", r:0x41, g:0x69, b:0xE1], [name:"Saddle Brown", r:0x8B, g:0x45, b:0x13], [name:"Salmon", r:0xFA, g:0x80, b:0x72], [name:"Sandy Brown", r:0xF4, g:0xA4, b:0x60], [name:"Sea Green", r:0x2E, g:0x8B, b:0x57], [name:"Seashell", r:0xFF, g:0xF5, b:0xEE], [name:"Sienna", r:0xA0, g:0x52, b:0x2D], [name:"Silver", r:0xC0, g:0xC0, b:0xC0], [name:"Sky Blue", r:0x87, g:0xCE, b:0xEB], [name:"Slate Blue", r:0x6A, g:0x5A, b:0xCD], [name:"Slate Gray", r:0x70, g:0x80, b:0x90], [name:"Snow", r:0xFF, g:0xFA, b:0xFA], [name:"Spring Green", r:0x00, g:0xFF, b:0x7F], [name:"Steel Blue", r:0x46, g:0x82, b:0xB4], [name:"Tan", r:0xD2, g:0xB4, b:0x8C], [name:"Teal", r:0x00, g:0x80, b:0x80], // Matter Spec 11.1.4.2 [name:"Thistle", r:0xD8, g:0xBF, b:0xD8], [name:"Tomato", r:0xFF, g:0x63, b:0x47], [name:"Turquoise", r:0x40, g:0xE0, b:0xD0], [name:"Violet", r:0xEE, g:0x82, b:0xEE], [name:"Wheat", r:0xF5, g:0xDE, b:0xB3], [name:"White", r:0xFF, g:0xFF, b:0xFF], // Matter Spec 11.1.4.2 [name:"White Smoke", r:0xF5, g:0xF5, b:0xF5], [name:"Yellow", r:0xFF, g:0xFF, b:0x00], // Matter Spec 11.1.4.2 [name:"Yellow Green", r:0x9A, g:0xCD, b:0x32], ] def getRGBfromName(n) { def s = colorNames.size() for (def i=0; i