From 83c7b2dd421c0bbd7800525fadce2ca9408ee73f Mon Sep 17 00:00:00 2001 From: Samsung DA Date: Thu, 14 Jan 2016 23:06:29 -0600 Subject: [PATCH] MSA-809: I've updated the code. MSA-785: SleepSense Automation # 424 --- .../smart-sleep-automation.groovy | 1486 +++++++++++++++++ .../smart-sleep.src/smart-sleep.groovy | 101 ++ 2 files changed, 1587 insertions(+) create mode 100644 smartapps/smartsolutionsv2/sleeping/smart-sleep-automation.src/smart-sleep-automation.groovy create mode 100644 smartapps/smartsolutionsv2/sleeping/smart-sleep.src/smart-sleep.groovy diff --git a/smartapps/smartsolutionsv2/sleeping/smart-sleep-automation.src/smart-sleep-automation.groovy b/smartapps/smartsolutionsv2/sleeping/smart-sleep-automation.src/smart-sleep-automation.groovy new file mode 100644 index 0000000..611e9ce --- /dev/null +++ b/smartapps/smartsolutionsv2/sleeping/smart-sleep-automation.src/smart-sleep-automation.groovy @@ -0,0 +1,1486 @@ +/** + * Sleep Rules + * + * 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. + * + */ + +import java.text.DecimalFormat + +definition( + name: "Smart Sleep Automation", + namespace: "smartsolutionsv2/sleeping", + parent: "smartsolutionsv2/sleeping:Smart Sleep", + author: "SmartThings", + description: "Sleeping automation rule.", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/Cat-ModeMagic.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/Cat-ModeMagic@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/Cat-ModeMagic@3x.png" +) + + +preferences { + page(name: "mainPage", title: getLabel("str_MainPageTitle"), install: false, uninstall: true, nextPage: "namePage"); + page(name: "namePage", title: getLabel("str_NamePageTitle"), install: true, uninstall: true); + page(name: "timeIntervalInput", title: getLabel("str_TimeSet")); +} + +def mainPage() { + dynamicPage(name: "mainPage") { + section { + sleepSensorInput(); + triggerInput(); + } + controlType(); + controlledInput(); + otherInputs(); + } +} + +//Sleep sensor input +def sleepSensorInput() { + input(name: "sleepSensor", type: "capability.sleepSensor", title: getLabel("str_SelectSense"), multiple: false, submitOnChange: true); +} + + +//Sleep sensor action to trigger event +private actionMap() { + state.sleepActionMap = ["sleeping": getLabel("str_sleep"), "not sleeping": getLabel("str_wake")]; + if(sleepSensor.find{it.hasAttribute("bedstate")} != null) { + state.sleepActionMap.put("in bed", getLabel("str_inbed")); + state.sleepActionMap.put("out of bed", getLabel("str_outofbed")); + } + return state.sleepActionMap; +} + +private actionOptions() { + actionMap().collect{[(it.key): it.value]} +} + +def triggerInput() { + def requiredInput = androidClient() || iosClient("1.7.0.RC1"); + if(sleepSensor) { + input(name: "trigger", type: "enum", title: getLabel("str_SelectSleepTrigger"), options: actionOptions(), required: true, submitOnChange: true); + } +} + +// What type should be controlled +private controlType() { + def requiredInput = androidClient() || iosClient("1.7.0.RC1"); + def mapControlTypes + if(clientLocale?.language == "ko") + { + mapControlTypes = [device: "${location.name}${getLabel("str_HubofDevice")}", homeWatch: getLabel("str_HubofHomeWatch"), mode: "${location.name}${getLabel("str_HubofMode")}", routine: "${location.name}${getLabel("str_HubofRoutines")}"]; + } + else + { + mapControlTypes = [device: "${getLabel("str_HubofDevice")}${location.name}", homeWatch: getLabel("str_HubofHomeWatch"), mode: "${getLabel("str_HubofMode")}${location.name}", routine: "${getLabel("str_HubofRoutines")}${location.name}"]; + } + + + + if(settings.trigger) { + section() { + input(name: "controlType", type: "enum", title: getLabel("str_SelectLocation"), options: mapControlTypes, required: requiredInput, submitOnChange: true); + } + } +} + +//Device to control with sleep sensor input +private lightMap() { + def lightActionMap = [on: getLabel("str_DeviceTurnOn"), off: getLabel("str_DeviceTurnOff")]; + if (controlledDevice.find{it.hasCapability("Switch Level")} != null) { + lightActionMap.level = getLabel("str_DeviceLevel") + } + if (controlledDevice.find{it.hasCapability("Color Control")} != null) { + lightActionMap.color = getLabel("str_DeviceColor") + } + return lightActionMap; +} + +private lightOptions() { + lightMap().collect{[(it.key): it.value]} +} + +def controlledInput() { + def requiredInput = androidClient() || iosClient("1.7.0.RC1"); + def mapControlledDeivces = [switch: getLabel("str_DeviceSwitch"), imageCapture: getLabel("str_DeviceCameras"), lock: getLabel("str_DeviceLocks"), thermostat: getLabel("str_DeviceThermostats"), alarm: getLabel("str_DeviceAlarms"), musicPlayer: getLabel("str_DeviceSpeaker")]; + + log.debug "control type ${settings.controlType}"; + + if(settings.controlType && settings.controlType == "device") { + section(getLabel("str_DeviceTitle")) { + input(name: "controlledDeviceType", type: "enum", title: getLabel("str_DeviceSelect"), options: mapControlledDeivces, required: requiredInput, submitOnChange: true); + } + + if(controlledDeviceType) { + def deviceType; + + section() { + input(name: "controlledDevice", type: "capability.${controlledDeviceType}", required: true, multiple: true, submitOnChange: true); + } + + if(controlledDevice) { + def label = controlledDevice.size() == 1? "${controlledDevice[0].label !=null ? controlledDevice[0].label : controlledDevice[0]} Control" : "${controlledDevice[0].label != null ? controlledDevice[0].label : controlledDevice[0]}, etc Control"; + section("${label}") { + switch(controlledDeviceType) { + case "switch": + input(name: "actionsLights", type: "enum", title: getLabel("str_DeviceLightsTitle"), options: lightOptions(), multiple: false, required: requiredInput, submitOnChange: true); + if(actionsLights == "color") { + input(name: "color", type: "enum", title: "Color", required: true, multiple: false, options: [ + ["Soft White":"Soft White - Default"], + ["White":"White - Concentrate"], + ["Daylight":"Daylight - Energize"], + ["Warm White":"Warm White - Relax"], + "Red","Green","Blue","Yellow","Orange","Purple","Pink"]); + } + if(actionsLights == "level") { + input(name: "level", type: "number", title: "Dimmer Level", defaultValue: 50, required: true, submitOnChange: true); + } + + def nonDimmableLights = ""; + def nonColorControlLights = ""; + def isareLevel = ""; + def hasSwitchLevel = false; + def hasColorControl = false; + controlledDevice.eachWithIndex { item, index -> + if(item.hasCapability("Switch Level") == null) { + if(nonDimmableLights == "") { + nonDimmableLights += "${item.label != null ? item.label : item}" ; + isareLevel = "is"; + } else { + nonDimmableLights += ", ${item.label != null ? item.label : item}"; + if(isareLevel == "is") { + isareLevel = "are"; + } + } + } else { + hasSwitchLevel = true; + } + if(item.hasCapability("Color Control") == null) { + if(nonColorControlLights == "") { + nonColorControlLights += "${item.label != null ? item.label : item}"; + } else { + nonColorControlLights += ", ${item.label != null ? item.label : item}"; + } + } else { + hasColorControl = true; + } + } + + if(hasSwitchLevel && nonDimmableLights != "") { + paragraph "${nonDimmableLights} ${isareLevel} not dimmable. These will be turned on to 100%."; + } + + if(hasColorControl && nonColorControlLights != "") { + paragraph "${nonColorControlLights} cannot set color."; + } + + break; + case "imageCapture": + input(name: "imageCaptureAction", type: "enum", title: getLabel("str_CameraTitle"), options: [take: getLabel("str_CameraTake")], multiple: false, required:true, submitOnChange: true); + break; + case "lock": + input(name: "lockAction", type: "enum", title: getLabel("str_LocksTitle"), options: [lock: getLabel("str_LocksLock"), unlock: getLabel("str_LocksUnLock")], multiple: false, required: true, submitOnChange: true); + break; + case "thermostat": + input(name: "thermostatMode", type: "enum", title: getLabel("str_DeviceThermostatTitle"), options: [modeCool: getLabel("str_DeviceThermostatCool"), modeHeat: getLabel("str_DeviceThermostatHeat"), off: getLabel("str_DeviceTurnOff")], required: requiredInput, multiple: false, submitOnChange: true); + + switch(thermostatMode) { + case "modeCool": + input(name: "thermostatCoolTemp", type: "number", title: getLabel("str_DeviceThermostatCoolSet"), defaultValue: 76, required: true, submitOnChange: true); + break; + case "modeHeat": + input(name: "thermostatHeatTemp", type: "number", title: getLabel("str_DeviceThermostatHeatSet"), defaultValue: 86, required: true, submitOnChange: true); + break; + } + break; + case "alarm": + input(name: "alarmAction", type: "enum", title: getLabel("str_AlarmWill"), options: [strobe: "Strobe the lights", siren: "Sound the siren", both: "Strobe the lights & sound the alarm", off: "turn Off"], multiple: false, required: true, submitOnChange: true); + break; + case "musicPlayer": + input(name: "musicPlayerAction", type: "enum", title: getLabel("str_DeviceSpeakerTitle"), options: [play: getLabel("str_DeviceSpeakerPlae"), pause: getLabel("str_DeviceSpeakerPause"), stop: getLabel("str_DeviceSpeakerStop")], required: true, multiple: false, submitOnChange: true); + break; + } + } + } + } + } + if(settings.controlType && settings.controlType == "homeWatch") { + section(getLabel("str_HomeWatchTitle")) { + input(name: "homeWatchAction", type: "enum", title: getLabel("str_HomeWatchSectionSelect"), required: true, multiple: false, options: [off: "Off", stay: "Stay", arm: "Arm"], submitOnChange: true); + } + } + if(settings.controlType && settings.controlType == "mode") { + section(getLabel("strr_ModeTitle")) { + input(name: "modeAction", type: "mode", title: getLabel("str_ModeSelect"), required: true, multiple: false, submitOnChange: true); + } + } + if(settings.controlType && settings.controlType == "routine") { + def routines = location.helloHome?.getPhrases()*.label; + if(routines) { + section(getLabel("str_RoutineTitle")) { + input(name: "routineAction", type: "enum", title: getLabel("str_RoutineSelect"), options: routines, required: true, multiple: false, submitOnChange: true); + } + } + } +} + + +def otherInputs() { + if (settings.trigger) { + def timeLabel = timeIntervalLabel() + section(title: getLabel("str_Moreoption"), hidden: hideOptionsSection(), hideable: true) { + def timeBasedTrigger = trigger in ["At Sunrise", "At Sunset", "At a Specific Time"] + log.trace "timeBasedTrigger: $timeBasedTrigger" + if (!timeBasedTrigger) { + href "timeIntervalInput", title: getLabel("str_TimeSet"), description: timeLabel ?: getLabel("str_Taptoset"), state: timeLabel ? "complete" : "incomplete" + } + + input "days", "enum", title: getLabel("str_WeekSet"), multiple: true, required: false, + options: [getLabel("str_Monday"), getLabel("str_Tuesday"), getLabel("str_Wednesday"), getLabel("str_Thursday"), getLabel("str_Friday"), getLabel("str_Saturday"), getLabel("str_Sunday")] + + //input "modes", "mode", title: "Only when mode is", multiple: true, required: false + } + } +} + +def timeIntervalInput() { + dynamicPage(name: "timeIntervalInput") { + section { + input "startTimeType", "enum", title: getLabel("str_TimeStartingCondition"), options: [["time": getLabel("str_TimeSpecificTime")], ["sunrise": getLabel("str_TimeSunrise")], ["sunset": getLabel("str_TimeSunset")]], defaultValue: "time", submitOnChange: true + if (startTimeType in ["sunrise","sunset"]) { + input "startTimeOffset", "number", title: getLabel("str_TimeOffset"), range: "*..*", required: false + } + else { + input "starting", "time", title: getLabel("str_TimeStart"), required: false + } + } + section { + input "endTimeType", "enum", title: getLabel("str_TimeEngingCondition"), options: [["time": getLabel("str_TimeSpecificTime")], ["sunrise": getLabel("str_TimeSunrise")], ["sunset": getLabel("str_TimeSunset")]], defaultValue: "time", submitOnChange: true + if (endTimeType in ["sunrise","sunset"]) { + input "endTimeOffset", "number", title: getLabel("str_TimeOffset"), range: "*..*", required: false + } + else { + input "ending", "time", title: getLabel("str_TimeEnd"), required: false + } + } + } +} + +private hideOptionsSection() { + (starting || startTimeType in ["sunrise","sunset"] || ending || endTimeType in ["sunrise","sunset"] || days || modes) ? false : true +} + +private String generateDefaultLabel() { + def sleepSensor = sleepSensor.label; + def trigger = state.sleepActionMap[trigger]; + def device = ""; + + if(controlledDevice) { + device = controlledDevice.size() == 1 ? "${controlledDevice[0].label != null ? controlledDevice[0].label : controlledDevice[0]}": "${controlledDevice[0].label != null ? controlledDevice[0].label : controlledDevice[0]}, etc"; + } else if(modeAction) { + device = "${modeAction}"; + } else if(homeWatchAction) { + device = "Home Watch"; + } + + def defaultLabel = "${trigger}"; + + if(controlType == "device") { + switch(controlledDeviceType) { + case "switch": + switch(actionsLights) { + case "on": + return "${defaultLabel} turn on ${device}"; + break; + case "off": + return "${defaultLabel} turn off ${device}"; + break; + case "color": + return "${defaultLabel} turn on ${device} and set color to ${color}"; + break; + case "level": + return "${defaultLabel} turn on ${device} and set level to ${level}"; + break; + } + break; + + case "imageCapture": + return "${defaultLabel} have ${device} capture Image" + break; + + case "lock": + return "${defaultLabel} ${lockAction[0].toLowerCase() + lockAction.substring(1)} ${device}"; + break; + + case "thermostat": + switch(thermostatMode) { + case "modeCool": + return "${defaultLabel} turn ${device} on, change cooling setpoint to ${thermostatCoolTemp}, and set mode to cool." + break; + case "modeHeat": + return "${defaultLabel} turn ${device} on, change cooling setpoint to ${thermostatHeatTemp}, and set mode to heat." + break; + case "off": + return "${defaultLabel} turn ${device} off." + break; + } + break; + + case "alarm": + return "${defaultLabel} ${alarmAction[0].toLowerCase() + alarmAction.substring(1)} ${device}"; + break; + + case "musicPlayer": + return "$defaultLabel} ${musicPlayerAction[0].toLowerCase() + musicPlayerAction.substring(1)} ${device}" + break; + } + } else if(controlType == "homeWatch") { + return "${defaultLabel} ${homeWatchAction} Home Watch"; + } else if(controlType == "mode") { + return "${defaultLabel} change mode to ${modeAction}"; + } else if(controlType == "routine") { + return "${defaultLabel} run routine ${routineAction}"; + } +} + +def namePage() { + if(!overrideLabel) { + app.updateLabel(generateDefaultLabel()); + } + dynamicPage(name: "namePage") { + if(overrideLabel) { + section(title: getLabel("str_NameAutomation")) { + label(title: getLabel("str_NameUser"), defaultValue: generateDefaultLabel(), required: false); + } + } else { + section(title: getLabel("str_NameAutomation")) { + paragraph app.label; + } + } + section { + input(name: "overrideLabel", type: "bool", title: getLabel("str_NameChange"), required: false, submitOnChange: true); + } + } +} + +def installed() { + log.debug "Installed with settings: ${settings}" + initialize() +} + +def updated() { + log.debug "Updated with settings: ${settings}" + + unsubscribe() + unschedule() + + initialize() +} + +def initialize() { + if(!overrideLabel) { + app.updateLabel(generateDefaultLabel()); + } + + subscribe(sleepSensor, "bedstate", eventHandler); + subscribe(sleepSensor, "sleeping", eventHandler); +} + +def eventHandler(evt) { + if(evt.value == trigger) { + if(getAllOk()) { + log.debug "all ok"; + switch(controlType) { + case "device": + if(controlledDevice) { + switch(controlledDeviceType) { + case "switch": + if(actionsLights == "on") { + controlledDevice.on(); + sendMessage(); + } + if(actionsLights == "off") { + controlledDevice.off(); + sendMessage(); + } + if(actionsLights == "color" || actionsLights == "level") { + setColor(); + } + break; + case "imageCapture": + controlledDevice."${imageCaptureAction}"(); + sendMessage(); + break; + case "lock": + controlledDevice."${lockAction}"(); + sendMessage(); + break; + case "thermostat": + if(thermostatMode == "modeCool") { + controlledDevice.setCoolingSetpoint(thermostatCoolTemp); + controlledDevice.cool(); + sendMessage(); + } + if(thermostatMode == "modeHeat") { + controlledDevice.setHeatingSetpoints(thermostatHeatTemp); + controlledDevice.heat(); + sendMessage(); + } + break; + case "alarm": + controlledDevice."${alarmAction}"(); + sendMessage(); + break; + case "musicPlayer": + controlledDevice."${musicPlayerAction}"(); + sendMessage(); + break; + } + } + break; + case "homeWatch": + log.debug "homeWatch"; + sendLocationEvent(name: "alarmSystemStatus", value: "${homeWatchAction}"); + sendMessage(); + break; + case "mode": + log.debug "mode"; + location.setMode("${modeAction}"); + sendMessage(); + break; + case "routine": + log.debug "routine"; + location.helloHome?.execute("${routineAction}"); + sendMessage(); + break; + } + } + } +} + +private setColor() { + + def hueColor = 0 + def saturation = 100 + + switch(color) { + case "White": + hueColor = 52 + saturation = 19 + 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 "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; + } + + def value = [switch: "on", hue: hueColor, saturation: saturation, level: 100] + + controlledDevice.each { + it.on() + if (actionsLights.contains("color")) { + if(it.hasCapability("Color Control")) + it.setColor(value); + sendMessage(); + } + if (actionsLights.contains("level")) { + if(it.hasCapability("Switch Level")) + it.setLevel(level as Integer ?: 100); + sendMessage(); + } + } +} + +private sendMessage(evt = [:]) { + def color = "#79b821"; + def icon = "st.switches.light.on"; + def actionLabel = ""; + + log.debug "control type: ${controlType}" + + def controlledDeviceLabel = controlledDevice.size() == 1 ? "${controlledDevice[0].label != null ? controlledDevice[0].label : controlledDevice[0]}" : "${controlledDevice[0].label != null ? controlledDevice[0].label : controlledDevice[0]}, ect" + + if(controlType == "device") { + switch(controlledDeviceType) { + case "switch": + switch(actionLights) { + case "on": + icon = "st.switches.light.on"; + actionLabel = "Turned on ${controlledDevice.label}"; + break; + case "off": + color = "#878787"; + icon = "st.switches.light.off"; + actionLabel = "Turned off ${controlledDevice.label}"; + break; + case "color": + icon = "st.switches.light.on"; + actionLabel = "Turned on ${controlledDevice.label} and set color to ${color}"; + break; + case "level": + icon = "st.switches.light.on"; + actionLabel = "Turned on ${controlledDevice.label} and set level to ${level}"; + break; + } + + if (app.currentState("status")?.value != actionLights || app.currentState("status") == null) { + def text = "$app.label $actionLabel" + sendEvent(name: "status", value: actionLights, linkText: app.label, + descriptionText: text, eventType:"SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + } + break; + case "imageCapture": + icon = "st.camera.take-photo"; + actionLabel = "${controlledDevice.label} captured image"; + sendEvent(name: "status", value: imageCaptureAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + break; + case "lock": + if(lockAction == "lock") { + icon = "st.locks.lock.locked"; + actionLabel = "${controlledDevice.label} has been locked"; + sendEvent(name: "status", value: lockAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + } else if(lockAction == "unlock") { + icon = "st.locks.lock.unlocked"; + actionLabel = "${controlledDevice.label} has been unlocked"; + sendEvent(name: "status", value: lockAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + } + break; + case "thermostat": + if(thermostatMode == "modeCool") { + icon = "st.thermostat.cool"; + actionLabel = "${controlledDevice.label} has cooling setpoint of ${thermostatCoolTemp} and is in cooling mode." + } + if(thermostatMode == "modeHeat") { + icon = "st.thermostat.heat"; + actionLabel = "${controlledDevice.label} has heating setpoint of ${thermostatCoolTemp} and is in heating mode." + } + + if (app.currentState("status")?.value != thermostatMode || app.currentState("status") == null) { + def text = "$app.label $actionLabel" + sendEvent(name: "status", value: thermostatMode, linkText: app.label, + descriptionText: text, eventType:"SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + } + break; + case "alarm": + switch(alarmAction) { + case "strobe": + icon = "st.security.alarm.alarm"; + actionLabel = "Strobe the lights on ${controlledDevice.label}"; + sendEvent(name: "status", value: alarmAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + break; + case "siren": + icon = "st.security.alarm.alarm"; + actionLabel = "Sound siren on ${controlledDevice.label}"; + sendEvent(name: "status", value: alarmAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + break; + case "both": + icon = "st.security.alarm.alarm"; + actionLabel = "Strobe the lights and sound the siren on ${controlledDevice.label}"; + sendEvent(name: "status", value: alarmAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + break; + case "off": + icon = "st.security.alarm.clear"; + color = "#878787"; + actionLabel = "Turn ${controlledDevice.label} off"; + sendEvent(name: "status", value: alarmAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + break; + } + break; + case "musicPlayer": + switch(musicPlayerAction) { + case "play": + icon = "st.sonos.play-btn"; + actionLabel = "Play music on ${controlledDevice.label}"; + sendEvent(name: "status", value: musicPlayerAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + break; + case "pause": + icon = "st.sonos.pause-btn"; + color = "#878787"; + actionLabel = "Pause music on ${controlledDevice.label}"; + sendEvent(name: "status", value: musicPlayerAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + break; + case "stop": + icon = "st.sonos.stop-btn"; + color = "#878787"; + actionLabel = "Stop music on ${controlledDevice.label}"; + sendEvent(name: "status", value: musicPlayerAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + break; + } + break; + } + } else if(controlType == "homeWatch") { + switch(homeWatchAction) { + case "off": + icon = "st.security.alarm.off"; + color = "#878787"; + actionLabel = "Smart Home Monitoring is off"; + sendEvent(name: "status", value: homeWatchAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + break; + case "stay": + icon = "st.security.alarm.partial"; + color = "#F0F015"; + actionLabel = "Smart Home Monitoring is in stay"; + sendEvent(name: "status", value: homeWatchAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + break; + case "arm": + icon = "st.security.alarm.on"; + actionLabel = "Smart Home Monitoring is armed"; + sendEvent(name: "status", value: homeWatchAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + break; + } + } else if(controlType == "mode") { + icon = "st.Home.home2"; + actionLabel = "${location.name} changed modes to ${modeAction}"; + sendEvent(name: "status", value: modeAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + } else if(controlType == "routine") { + icon = "st.Home.home2"; + actionLabel = "Execute ${routineAction} at ${location.name}"; + sendEvent(name: "status", value: routineAction, linkText: app.label, + descriptionText: text, eventType: "SOLUTION_EVENT", data: [icon: icon, backgroundColor: color]) + } +} + +// TODO - centralize somehow +private getAllOk() { + modeOk && daysOk && timeOk +} + +private getModeOk() { + def result = !modes || modes.contains(location.mode) + log.trace "modeOk = $result" + result +} + +private getDaysOk() { + def result = true + if (days) { + def df = new java.text.SimpleDateFormat("EEEE") + if (location.timeZone) { + df.setTimeZone(location.timeZone) + } + else { + df.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")) + } + def day = df.format(new Date()) + result = days.contains(day) + } + log.trace "daysOk = $result" + result +} + +private getTimeOk() { + def result = true + def start = timeWindowStart() + def stop = timeWindowStop() + if (start && stop) { + result = timeOfDayIsBetween(start, stop, new Date(), location.timeZone) + } + log.trace "timeOk = $result" + result +} + +private timeWindowStart() { + def result = null + if (startTimeType == "sunrise") { + result = location.currentState("sunriseTime")?.dateValue + if (result && startTimeOffset) { + result = new Date(result.time + Math.round(startTimeOffset * 60000)) + } + } + else if (startTimeType == "sunset") { + result = location.currentState("sunsetTime")?.dateValue + if (result && startTimeOffset) { + result = new Date(result.time + Math.round(startTimeOffset * 60000)) + } + } + else if (starting) { + result = timeToday(starting, location.timeZone) + } + log.trace "timeWindowStart = ${result}" + result +} + +private timeWindowStop() { + def result = null + if (endTimeType == "sunrise") { + result = location.currentState("sunriseTime")?.dateValue + if (result && endTimeOffset) { + result = new Date(result.time + Math.round(endTimeOffset * 60000)) + } + } + else if (endTimeType == "sunset") { + result = location.currentState("sunsetTime")?.dateValue + if (result && endTimeOffset) { + result = new Date(result.time + Math.round(endTimeOffset * 60000)) + } + } + else if (ending) { + result = timeToday(ending, location.timeZone) + } + log.trace "timeWindowStop = ${result}" + result +} + +private hhmm(time, fmt = "h:mm a") +{ + def t = timeToday(time, location.timeZone) + def f = new java.text.SimpleDateFormat(fmt) + f.setTimeZone(location.timeZone ?: timeZone(time)) + f.format(t) +} + +private timeIntervalLabel() { + def start = "" + switch (startTimeType) { + case "time": + if (ending) { + start += hhmm(starting) + } + break + case "sunrise": + case "sunset": + start += startTimeType[0].toUpperCase() + startTimeType[1..-1] + if (startTimeOffset) { + start += startTimeOffset > 0 ? "+${startTimeOffset} min" : "${startTimeOffset} min" + } + break + } + + def finish = "" + switch (endTimeType) { + case "time": + if (ending) { + finish += hhmm(ending) + } + break + case "sunrise": + case "sunset": + finish += endTimeType[0].toUpperCase() + endTimeType[1..-1] + if (endTimeOffset) { + finish += endTimeOffset > 0 ? "+${endTimeOffset} min" : "${endTimeOffset} min" + } + break + } + start && finish ? "${start} to ${finish}" : "" +} + + +def getLabel(value) +{ + //Name Page + def str_NameChange=[ + "kr": "이름을 변경 설정.", + "us": "Do you want to allow custom automation name?" + ] + + def str_NameAutomation=[ + "kr": "이름을 변경 설정.", + "us": "Automation name" + ] + + def str_NameUser=[ + "kr": "사용자 이름.", + "us": "Enter custom name" + ] + + def str_NamePageTitle=[ + "kr": "자동화 룰 이름 설정", + "us": "Configure rule based on sleep sensor state" + ] + + /////////////////////////////////////////////////////////////////////////// + + //Main Page + def str_MainPageTitle=[ + "kr": "슬립센서를 이용하여 자동화 룰을 만드세요.", + "us": "Configure rule based on sleep sensor state" + ] + + def str_SelectSense=[ + "kr": "슬립센서를 선택하세요.", + "us": "Which sleep sensor?" + ] + + def str_SelectSleepTrigger=[ + "kr": "트리거를 선택하세요.", + "us": "Select trigger." + ] + + def str_SelectLocation=[ + "kr": "제어 방식을 선택하세요.", + "us": "What would you like to control?" + ] + + def str_HubofHomeWatch=[ + "kr": "홈지키미의 상태", + "us": "The state of Smart Home Monitoring" + ] + + def str_HubofDevice=[ + "kr": "의 디바이스", + "us": "The mode at " + ] + + def str_HubofMode=[ + "kr": "의 모드", + "us": "A mode at " + ] + + def str_HubofRoutines=[ + "kr": "의 루틴", + "us": "A routine at " + ] + + + /////////////////////////////////////////////////////////////////////////// + + + def str_RoutineTitle=[ + "kr": "자동화 설정", + "us": "Routine Control" + ] + + def str_RoutineSelect=[ + "kr": "자동화 룰을 선택하세요", + "us": "Run the routine..." + ] + + /////////////////////////////////////////////////////////////////////////// + + def strr_ModeTitle=[ + "kr": "모드", + "us": "mode" + ] + + def str_ModeSelect=[ + "kr": "모드 선택", + "us": "Change Mode to..." + ] + + /////////////////////////////////////////////////////////////////////////// + + def str_HomeWatchTitle=[ + "kr": "홈지키미 모드 설정", + "us": "Home Watch Control" + ] + + def str_HomeWatchSectionSelect=[ + "kr": "홈지키미 모드 상태 선택", + "us": "Set HomeWatch status to..." + ] + + /////////////////////////////////////////////////////////////////////////// + + def str_DeviceTitle=[ + "kr": "기기 제어", + "us": "Device Control" + ] + + def str_DeviceSelect=[ + "kr": "기기 선택", + "us": "Select device to control" + ] + + def str_DeviceSwitch=[ + "kr": "스위치 및 디머", + "us": "Switches & Dimmers" + ] + def str_DeviceCameras=[ + "kr": "카메라", + "us": "Cameras" + ] + def str_DeviceLocks=[ + "kr": "자동 잠금 기기", + "us": "Locks" + ] + def str_DeviceThermostats=[ + "kr": "에어컨 및 온도 설정기", + "us": "Thermostats" + ] + def str_DeviceAlarms=[ + "kr": "알림 센서", + "us": "Alarms & Sirens" + ] + def str_DeviceSpeaker=[ + "kr": "스피커", + "us": "Speakers" + ] + + def str_DeviceLightsTitle=[ + "kr": "동작 선택", + "us": "Lights will..." + ] + + def str_DeviceTurnOn=[ + "kr": "켜기", + "us": "Turn On" + ] + + def str_DeviceTurnOff=[ + "kr": "끄기", + "us": "Turn Off" + ] + + def str_DeviceLevel=[ + "kr": "켜고 밝기 조정하기", + "us": "Turn On & Set Level" + ] + + def str_DeviceColor=[ + "kr": "켜고 색상 조정하기", + "us": "Turn On & Set Color" + ] + + def str_DeviceSpeakerTitle=[ + "kr": "동작 선택", + "us": "Speaker will..." + ] + + def str_AlarmWill=[ + "kr": "알람이 발생했을때...", + "us": "Alarm will..." + ] + + def str_DeviceSpeakerPlae=[ + "kr": "동작", + "us": "Play" + ] + + def str_DeviceSpeakerPause=[ + "kr": "일시 정지", + "us": "Pause" + ] + + def str_DeviceSpeakerStop=[ + "kr": "중지", + "us": "Stop" + ] + + + def str_DeviceThermostatTitle=[ + "kr": "동작 선택", + "us": "Thermostat will..." + ] + + def str_DeviceThermostatCool=[ + "kr": "냉방 모드 설정", + "us": "Set cooling point & set mode to cool" + ] + + def str_DeviceThermostatHeat=[ + "kr": "난방 모드 설정", + "us": "Set heating point & set mode to heat" + ] + + def str_DeviceThermostatCoolSet=[ + "kr": "냉방 모드 온도 설정", + "us": "Set cooling point to..." + ] + + def str_DeviceThermostatHeatSet=[ + "kr": "난방 모드 온도 설정", + "us": "Set heating point to..." + ] + + def str_CameraTitle=[ + "kr": "동작 설정", + "us": "Camera will..." + ] + + def str_CameraTake=[ + "kr": "사진 가져 오기", + "us": "Take a photo" + ] + + + def str_LocksTitle=[ + "kr": "동작 설정", + "us": "Lock will..." + ] + + + def str_LocksLock=[ + "kr": "잠그기", + "us": "Lock the door" + ] + + def str_LocksUnLock=[ + "kr": "잠금 풀기", + "us": "Unlock the door" + ] + + + /////////////////////////////////////////////////////////////////////////// + + def str_MoreOption=[ + "kr": "추가 설정", + "us": "More options" + ] + + def str_TimeSet=[ + "kr": "동작 시간 설정", + "us": "Only during a certain time" + ] + + def str_TimeStartingCondition=[ + "kr": "시작 조건", + "us": "Starting at" + ] + + def str_TimeEngingCondition=[ + "kr": "종료 조건", + "us": "Ending at" + ] + + def str_TimeSunrise=[ + "kr": "해 질때", + "us": "At Sunrise" + ] + + def str_TimeSunset=[ + "kr": "해 뜰때", + "us": "At Sunset" + ] + + def str_TimeSpecificTime=[ + "kr": "사용자 설정", + "us": "At a Specific Time" + ] + + def str_TimeOffset=[ + "kr": "오차 범위를 설정하세요.", + "us": "Offset in minutes (+/-)" + ] + + def str_TimeStart=[ + "kr": "시작 시간", + "us": "Start time" + ] + + def str_TimeEnd=[ + "kr": "종료 시간", + "us": "End time" + ] + + def str_WeekSet=[ + "kr": "동작 요일을 선택하세요.", + "us": "Only on certain days of the week" + ] + + /////////////////////////////////////////////////////////////////////////// + + def str_Moreoption=[ + "kr": "추가 설정", + "us": "More options" + ] + + def str_Monday=[ + "kr": "월요일", + "us": "Monday" + ] + + def str_Tuesday=[ + "kr": "화요일", + "us": "Tuesday" + ] + + def str_Wednesday=[ + "kr": "수요일", + "us": "Wednesday" + ] + + def str_Thursday=[ + "kr": "목요일", + "us": "Thursday" + ] + def str_Friday=[ + "kr": "금요일", + "us": "Friday" + ] + def str_Saturday=[ + "kr": "토요일", + "us": "Saturday" + ] + def str_Sunday=[ + "kr": "일요일", + "us": "Sunday" + ] + + /////////////////////////////////////////////////////////////////////////// + + def str_sleep=[ + "kr": "잠 들었을때", + "us": "When I fall asleep" + ] + + def str_wake=[ + "kr": "일어 났을때", + "us": "When I wake" + ] + + def str_inbed=[ + "kr": "잠자리에 들었을때", + "us": "When I get in bed" + ] + + def str_outofbed=[ + "kr": "잠자리에서 나왔을때", + "us": "When I get out of bed" + ] + + def str_Taptoset=[ + "kr": "설정", + "us": "Tap to set" + ] + + + + if(clientLocale?.language == "ko") + { + switch(value) + { + case "str_MainPageTitle": + return str_MainPageTitle["kr"] + case "str_SelectSense": + return str_SelectSense["kr"] + case "str_SelectSleepTrigger": + return str_SelectSleepTrigger["kr"] + case "str_SelectLocation": + return str_SelectLocation["kr"] + case "str_HubofHomeWatch": + return str_HubofHomeWatch["kr"] + case "str_HubofMode": + return str_HubofMode["kr"] + case "str_HubofRoutines": + return str_HubofRoutines["kr"] + case "str_HubofDevice": + return str_HubofDevice["kr"] + + case "str_RoutineTitle": + return str_RoutineTitle["kr"] + case "str_RoutineSelect": + return str_RoutineSelect["kr"] + case "str_TimeSet": + return str_TimeSet["kr"] + case "str_TimeStartingCondition": + return str_TimeStartingCondition["kr"] + case "str_TimeEngingCondition": + return str_TimeEngingCondition["kr"] + case "str_TimeSunrise": + return str_TimeSunrise["kr"] + case "str_TimeSunset": + return str_TimeSunset["kr"] + case "str_TimeSpecificTime": + return str_TimeSpecificTime["kr"] + case "str_TimeOffset": + return str_TimeOffset["kr"] + case "str_TimeStart": + return str_TimeStart["kr"] + case "str_TimeEnd": + return str_TimeEnd["kr"] + case "str_WeekSet": + return str_WeekSet["kr"] + case "str_NameChange": + return str_NameChange["kr"] + case "str_NameAutomation": + return str_NameAutomation["kr"] + case "str_NameUser": + return str_NameUser["kr"] + case "str_NamePageTitle": + return str_NamePageTitle["kr"] + case "str_DeviceTitle": + return str_DeviceTitle["kr"] + case "str_DeviceSelect": + return str_DeviceSelect["kr"] + case "str_DeviceLightsTitle": + return str_DeviceLightsTitle["kr"] + case "str_DeviceTurnOn": + return str_DeviceTurnOn["kr"] + case "str_DeviceTurnOff": + return str_DeviceTurnOff["kr"] + case "str_DeviceLevel": + return str_DeviceLevel["kr"] + case "str_DeviceColor": + return str_DeviceColor["kr"] + case "str_DeviceSpeakerTitle": + return str_DeviceSpeakerTitle["kr"] + case "str_AlarmWill": + return str_AlarmWill["kr"] + case "str_DeviceSpeakerPlae": + return str_DeviceSpeakerPlae["kr"] + case "str_DeviceSpeakerPause": + return str_DeviceSpeakerPause["kr"] + case "str_DeviceSpeakerStop": + return str_DeviceSpeakerStop["kr"] + case "str_DeviceSwitch": + return str_DeviceSwitch["kr"] + case "str_DeviceCameras": + return str_DeviceCameras["kr"] + case "str_DeviceLocks": + return str_DeviceLocks["kr"] + case "str_DeviceThermostats": + return str_DeviceThermostats["kr"] + case "str_DeviceAlarms": + return str_DeviceAlarms["kr"] + case "str_DeviceSpeaker": + return str_DeviceSpeaker["kr"] + case "str_DeviceThermostatTitle": + return str_DeviceThermostatTitle["kr"] + case "str_DeviceThermostatCool": + return str_DeviceThermostatCool["kr"] + case "str_DeviceThermostatHeat": + return str_DeviceThermostatHeat["kr"] + case "str_DeviceThermostatCoolSet": + return str_DeviceThermostatCoolSet["kr"] + case "str_DeviceThermostatHeatSet": + return str_DeviceThermostatHeatSet["kr"] + case "strr_ModeTitle": + return strr_ModeTitle["kr"] + case "str_ModeSelect": + return str_ModeSelect["kr"] + case "str_HomeWatchTitle": + return str_HomeWatchTitle["kr"] + case "str_HomeWatchSectionSelect": + return str_HomeWatchSectionSelect["kr"] + case "str_CameraTitle": + return str_CameraTitle["kr"] + case "str_CameraTake": + return str_CameraTake["kr"] + + case "str_Moreoption": + return str_Moreoption["kr"] + case "str_Monday": + return str_Monday["kr"] + case "str_Tuesday": + return str_Tuesday["kr"] + case "str_Wednesday": + return str_Wednesday["kr"] + case "str_Thursday": + return str_Thursday["kr"] + case "str_Friday": + return str_Friday["kr"] + case "str_Saturday": + return str_Saturday["kr"] + case "str_Sunday": + return str_Sunday["kr"] + + case "str_sleep": + return str_sleep["kr"] + case "str_wake": + return str_wake["kr"] + case "str_inbed": + return str_inbed["kr"] + case "str_outofbed": + return str_outofbed["kr"] + case "str_Taptoset": + return str_Taptoset["kr"] + + } + } + else + { + switch(value) + { + case "str_MainPageTitle": + return str_MainPageTitle["us"] + case "str_SelectSense": + return str_SelectSense["us"] + case "str_SelectSleepTrigger": + return str_SelectSleepTrigger["us"] + case "str_SelectLocation": + return str_SelectLocation["us"] + case "str_HubofHomeWatch": + return str_HubofHomeWatch["us"] + case "str_HubofMode": + return str_HubofMode["us"] + case "str_HubofRoutines": + return str_HubofRoutines["us"] + case "str_HubofDevice": + return str_HubofDevice["us"] + + case "str_RoutineTitle": + return str_RoutineTitle["us"] + case "str_RoutineSelect": + return str_RoutineSelect["us"] + case "str_TimeSet": + return str_TimeSet["us"] + case "str_TimeStartingCondition": + return str_TimeStartingCondition["us"] + case "str_TimeEngingCondition": + return str_TimeEngingCondition["us"] + case "str_TimeSunrise": + return str_TimeSunrise["us"] + case "str_TimeSunset": + return str_TimeSunset["us"] + case "str_TimeSpecificTime": + return str_TimeSpecificTime["us"] + case "str_TimeOffset": + return str_TimeOffset["us"] + case "str_TimeStart": + return str_TimeStart["us"] + case "str_TimeEnd": + return str_TimeEnd["us"] + case "str_WeekSet": + return str_WeekSet["us"] + case "str_NameChange": + return str_NameChange["us"] + case "str_NameAutomation": + return str_NameAutomation["us"] + case "str_NameUser": + return str_NameUser["us"] + case "str_NamePageTitle": + return str_NamePageTitle["us"] + case "str_DeviceTitle": + return str_DeviceTitle["us"] + case "str_DeviceSelect": + return str_DeviceSelect["us"] + case "str_DeviceLightsTitle": + return str_DeviceLightsTitle["us"] + case "str_DeviceTurnOn": + return str_DeviceTurnOn["us"] + case "str_DeviceTurnOff": + return str_DeviceTurnOff["us"] + case "str_DeviceLevel": + return str_DeviceLevel["us"] + case "str_DeviceColor": + return str_DeviceColor["us"] + case "str_DeviceSpeakerTitle": + return str_DeviceSpeakerTitle["us"] + case "str_AlarmWill": + return str_AlarmWill["us"] + case "str_DeviceSpeakerPlae": + return str_DeviceSpeakerPlae["us"] + case "str_DeviceSpeakerPause": + return str_DeviceSpeakerPause["us"] + case "str_DeviceSpeakerStop": + return str_DeviceSpeakerStop["us"] + case "str_DeviceSwitch": + return str_DeviceSwitch["us"] + case "str_DeviceCameras": + return str_DeviceCameras["us"] + case "str_DeviceLocks": + return str_DeviceLocks["us"] + case "str_DeviceThermostats": + return str_DeviceThermostats["us"] + case "str_DeviceAlarms": + return str_DeviceAlarms["us"] + case "str_DeviceSpeaker": + return str_DeviceSpeaker["us"] + case "str_DeviceThermostatTitle": + return str_DeviceThermostatTitle["us"] + case "str_DeviceThermostatCool": + return str_DeviceThermostatCool["us"] + case "str_DeviceThermostatHeat": + return str_DeviceThermostatHeat["us"] + case "str_DeviceThermostatCoolSet": + return str_DeviceThermostatCoolSet["us"] + case "str_DeviceThermostatHeatSet": + return str_DeviceThermostatHeatSet["us"] + case "strr_ModeTitle": + return strr_ModeTitle["us"] + case "str_ModeSelect": + return str_ModeSelect["us"] + case "str_HomeWatchTitle": + return str_HomeWatchTitle["us"] + case "str_HomeWatchSectionSelect": + return str_HomeWatchSectionSelect["us"] + case "str_CameraTitle": + return str_CameraTitle["us"] + case "str_CameraTake": + return str_CameraTake["us"] + + case "str_Moreoption": + return str_Moreoption["us"] + case "str_Monday": + return str_Monday["us"] + case "str_Tuesday": + return str_Tuesday["us"] + case "str_Wednesday": + return str_Wednesday["us"] + case "str_Thursday": + return str_Thursday["us"] + case "str_Friday": + return str_Friday["us"] + case "str_Saturday": + return str_Saturday["us"] + case "str_Sunday": + return str_Sunday["us"] + + case "str_sleep": + return str_sleep["us"] + case "str_wake": + return str_wake["us"] + case "str_inbed": + return str_inbed["us"] + case "str_outofbed": + return str_outofbed["us"] + case "str_Taptoset": + return str_Taptoset["us"] + + } + } + return "Unknown" +} + + + + + + + + diff --git a/smartapps/smartsolutionsv2/sleeping/smart-sleep.src/smart-sleep.groovy b/smartapps/smartsolutionsv2/sleeping/smart-sleep.src/smart-sleep.groovy new file mode 100644 index 0000000..c46f73d --- /dev/null +++ b/smartapps/smartsolutionsv2/sleeping/smart-sleep.src/smart-sleep.groovy @@ -0,0 +1,101 @@ +/** + * Sleep Wizard + * + * 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: "Smart Sleep", + namespace: "smartsolutionsv2/sleeping", + author: "SmartThings", + description: "Create rules to control devices based on a sleep sensor, including in bed, out of bed, sleeping, and not sleeping.", + category: "My Apps", + iconUrl: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/Cat-ModeMagic.png", + iconX2Url: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/Cat-ModeMagic@2x.png", + iconX3Url: "https://s3.amazonaws.com/smartapp-icons/ModeMagic/Cat-ModeMagic@3x.png", + singleInstance: true +) + +preferences { + page(name: "main", title: getLabel("str_Title"), install: true, uninstall: true) { + section { + app(name: "smartsleepautomation", appName: "Smart Sleep Automation", namespace: "smartsolutionsv2/sleeping", title: getLabel("str_SectionTitle"), multiple: true, uninstall: true) + } + } +} + +def installed() { + log.debug "Installed with settings: ${settings}" + initialize() +} + +def updated() { + log.debug "Updated with settings: ${settings}" + initialize() +} + +def initialize() { + def numChildApps = getChildApps().size(); + def text = "${numChildApps} rules configured"; + sendEvent( + linkText: numChildApps.toString(), + descriptionText: next, + eventType: "SOLUTION_SUMMARY", + name: "summary", + value: numChildApps, + data: [["icon": "indicator-dot-gray", "iconColor": "#878787", "value":text]], + displayed: false + ); +} + +cards { + card("Action History") { + tiles { + eventTile { } + } + } +} + +def getLabel(value) +{ + def str_Title=[ + "kr": "룰", + "us": "Rules" + ] + + def str_SectionTitle=[ + "kr": "새로운 자동화 룰 만들기", + "us": "New Smart Sleep Automation" + ] + + if(clientLocale?.language == "ko") + { + switch(value) + { + case "str_Title": + return str_Title["kr"] + case "str_SectionTitle": + return str_SectionTitle["kr"] + } + } + else + { + switch(value) + { + case "str_Title": + return str_Title["us"] + case "str_SectionTitle": + return str_SectionTitle["us"] + } + } + return "Unknown" +} \ No newline at end of file