Compare commits

..

1 Commits

Author SHA1 Message Date
Samsung DA
0c7c1e60f9 MSA-1554: Smartapps is available in association with SLEEPsense DTH.
I was doing this work wiht  Jenny.

e-mail : jihyouk.choi@samsung.com
name : jihyouk-Choi
2016-10-25 19:25:16 -05:00
22 changed files with 1651 additions and 1497 deletions

View File

@@ -1,394 +0,0 @@
/**
* Trend Setter - Colorful Light Group Device
*
* Copyright 2015 Chris Kitch
*
* 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.
*
*/
metadata {
definition (name: "Colorful Light Group Device", namespace: "kriskit.trendSetter", author: "Chris Kitch") {
capability "Actuator"
capability "Sensor"
capability "Switch"
capability "Switch Level"
capability "Color Control"
command "adjustLevel"
command "adjustSaturation"
command "adjustHue"
attribute "onPercentage", "number"
attribute "levelSync", "string"
attribute "colorSync", "string"
attribute "saturationSync", "string"
attribute "hueSync", "string"
}
simulator {
// TODO: define status and reply messages here
}
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label: '${name}', action: "switch.off", icon: "st.lights.multi-light-bulb-on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "off", label: '${name}', action: "switch.on", icon: "st.lights.multi-light-bulb-off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "turningOn", label: '${name}', action: "switch.off", icon: "st.lights.multi-light-bulb-on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "turningOff", label: '${name}', action: "switch.on", icon: "st.lights.multi-light-bulb-off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "half", label: '${name}', action: "switch.on", icon: "st.lights.multi-light-bulb-on", backgroundColor: "#a3d164", nextState: "turningOn"
attributeState "mostlyOn", label: 'Onish', action: "switch.on", icon: "st.lights.multi-light-bulb-on", backgroundColor: "#79b821", nextState: "turningOn"
attributeState "mostlyOff", label: 'Offish', action: "switch.off", icon: "st.lights.multi-light-bulb-off", backgroundColor: "#d1e5b5", nextState: "turninOff"
}
tileAttribute ("device.color", key: "COLOR_CONTROL") {
attributeState "color", action: "color control.setColor"
}
tileAttribute ("device.onPercentage", key: "SECONDARY_CONTROL") {
attributeState "onPercentage", label:'${currentValue}% On'
attributeState "100", label:'All On'
attributeState "0", label:'All Off'
}
tileAttribute("device.level", key: "SLIDER_CONTROL") {
attributeState "default", label: '', action: "switch level.setLevel"
}
}
standardTile("levelLabel", "levelLable", height:1, width:1, decoration: "flat", inactiveLabel: true) {
state "default", label:"Level", unit:"", icon: "st.illuminance.illuminance.light"
}
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 3, inactiveLabel: false) {
state "level", action:"switch level.setLevel"
}
valueTile("levelValue", "device.level", inactiveLabel: true, height:1, width:1, decoration: "flat") {
state "default", label:'${currentValue}%', unit:""
}
valueTile("levelSync", "device.levelSync", height:1, width:1) {
state "default", label:' Sync ', unit:"", action: "adjustLevel", backgroundColor: "#ff9900"
state "ok", label:'', unit:"", backgroundColor: "#00b509"
}
standardTile("saturationLabel", "saturationLabel", height:1, width:1, decoration: "flat", inactiveLabel: true) {
state "default", label:"Sat", unit:"", icon: "st.Kids.kids2"
}
controlTile("saturationSliderControl", "device.saturation", "slider", height: 1, width: 3, inactiveLabel: false) {
state "saturation", action:"color control.setSaturation"
}
valueTile("saturationValue", "device.saturation", inactiveLabel: true, height:1, width:1, decoration: "flat") {
state "default", label:'${currentValue}%', unit:""
}
valueTile("saturationSync", "device.saturationSync", height:1, width:1) {
state "default", label:' Sync ', unit:"", action: "adjustSaturation", backgroundColor: "#ff9900"
state "ok", label:'', unit:"", backgroundColor: "#00b509"
}
standardTile("hueLabel", "hueLabel", height:1, width:1, decoration: "flat", inactiveLabel: true) {
state "default", label:"Hue", unit:"", icon: "st.Kids.kids2"
}
controlTile("hueSliderControl", "device.hue", "slider", height: 1, width: 3, inactiveLabel: false) {
state "hue", action:"color control.setHue"
}
valueTile("hueValue", "device.hue", inactiveLabel: true, height:1, width:1, decoration: "flat") {
state "default", label:'${currentValue}%', unit:""
}
valueTile("hueSync", "device.hueSync", height:1, width:1) {
state "default", label:' Sync ', unit:"", action: "adjustHue", backgroundColor: "#ff9900"
state "ok", label:'', unit:"", backgroundColor: "#00b509"
}
}
main "switch"
details([
"switch",
"levelLabel",
"levelSliderControl",
"levelValue",
"levelSync",
"saturationLabel",
"saturationSliderControl",
"saturationValue",
"saturationSync",
"hueLabel",
"hueSliderControl",
"hueValue",
"hueSync"])
}
def parse(String description) {
}
def groupSync(name, values) {
try {
"sync${name.capitalize()}"(values)
} catch(ex) {
log.error "Error executing 'sync${name.capitalize()}' method: $ex"
}
}
// SWITCH
def on() {
on(true)
}
def on(triggerGroup) {
sendEvent(name: "switch", value: "on")
sendEvent(name: "onPercentage", value: 100, displayed: false)
if (triggerGroup)
parent.performGroupCommand("on")
}
def off() {
off(true)
}
def off(triggerGroup) {
sendEvent(name: "switch", value: "off")
sendEvent(name: "onPercentage", value: 0, displayed: false)
if (triggerGroup)
parent.performGroupCommand("off")
}
def syncSwitch(values) {
log.debug "syncSwitch(): $values"
def onCount = values?.count { it == "on" }
def percentOn = (int)Math.floor((onCount / values?.size()) * 100)
log.debug "Percent On: $percentOn"
if (percentOn == 0 || percentOn == 100) {
if (percentOn == 0)
off(false)
else
on(false)
return
}
def value = null
if (percentOn == 50)
value = "half"
else if (percentOn > 0 && percentOn < 50)
value = "mostlyOff"
else if (percentOn > 50 && percentOn < 100)
value = "mostlyOn"
sendEvent(name: "switch", value: value)
sendEvent(name: "onPercentage", value: percentOn, displayed: false)
}
// LEVEL
def setLevel(val) {
setLevel(val, true)
}
def setLevel(val, triggerGroup) {
log.debug "Setting level to $val"
if (val < 0)
val = 0
if( val > 100)
val = 100
if (triggerGroup) {
if (val == 0)
off()
else
on()
}
sendEvent(name: "level", value: val, isStateChange: true)
sendEvent(name: "switch.setLevel", value: val, isStateChange: true)
if (triggerGroup)
parent.performGroupCommand("setLevel", [val])
}
def syncLevel(values) {
log.debug "syncLevel(): $values"
def valueCount = values?.size()
def valueCountBy = values?.countBy { it }
def matchValue = "bad"
def level = device.currentValue("level")
valueCountBy.each { value, count ->
if (count == valueCount) {
level = value
matchValue = "ok"
return true
}
}
if (matchValue == "bad")
level = getAdjustmentLevel(values)
setLevel(level, false)
sendEvent(name: "levelSync", value: matchValue, displayed: false)
}
def adjustLevel() {
def values = parent.getGroupCurrentValues("level")
if (!values)
return
def level = getAdjustmentLevel(values)
setLevel(level)
}
def getAdjustmentLevel(values) {
if (!values)
return
def valueCountBy = values?.countBy { it }
valueCountBy = valueCountBy?.sort { a, b -> b.value <=> a.value }
def level = device.currentValue("level")
if (valueCountBy.size() > 1) {
if (valueCountBy.size() == values.size()) {
log.debug "Values are all different - making average"
level = Math.round(values.sum() / values.size())
} else {
log.debug "Some values are the same, choosing most popular"
def firstItem = valueCountBy.find { true }
level = firstItem.key
}
}
return level
}
// COLOR
def setColor(value) {
setColor(value, true)
}
def setColor(value, triggerGroup) {
value.level = null
def hex = value.hex
if (!hex && value.hue && value.saturation)
hex = colorUtil.hslToHex(value.hue, value.saturation)
sendEvent(name: "color", value: value.hex, displayed:false)
if (triggerGroup)
parent.performGroupCommand("setColor", [value])
if (value.saturation)
setSaturation(value.saturation, triggerGroup, false)
if (value.hue)
setHue(value.hue, triggerGroup, false)
}
def syncColor(values) {
log.debug "syncColor(): $values"
}
// SATURATION
def setSaturation(value) {
setSaturation(value, true, true)
}
def setSaturation(value, triggerGroup, sendColor) {
on(triggerGroup)
sendEvent(name: "saturation", value: (int)value, displayed:false)
if (triggerGroup)
parent.performGroupCommand("setSaturation", [value])
if (sendColor) {
def hex = colorUtil.hslToHex((int)device.currentValue("hue"), value)
sendEvent(name: "color", value: hex, displayed:false)
}
}
def syncSaturation(values) {
log.debug "syncSaturation(): $values"
def valueCount = values?.size()
def valueCountBy = values?.countBy { it }
def matchValue = "bad"
valueCountBy.each { value, count ->
if (count == valueCount) {
matchValue = "ok"
return true
}
}
sendEvent(name: "saturationSync", value: matchValue, displayed: false)
}
def adjustSaturation() {
def saturation = (int)device.currentValue("saturation")
log.debug "adjustSaturation $saturation"
setSaturation(saturation)
}
// HUE
def setHue(value) {
setHue(value, true, true)
}
def setHue(value, triggerGroup, sendColor) {
on(triggerGroup)
sendEvent(name: "hue", value: (int)value, displayed: false)
if (triggerGroup)
parent.performGroupCommand("setHue", [value])
if (sendColor) {
def hex = colorUtil.hslToHex(value, (int)device.currentValue("saturation"))
sendEvent(name: "color", value: hex, displayed:false)
}
}
def syncHue(values) {
log.debug "syncHue(): $values"
def valueCount = values?.size()
def valueCountBy = values?.countBy { it }
def matchValue = "bad"
valueCountBy.each { value, count ->
if (count == valueCount) {
matchValue = "ok"
return true
}
}
sendEvent(name: "hueSync", value: matchValue, displayed: false)
}
def adjustHue() {
def hue = (int)device.currentValue("hue")
log.debug "adjustHue: $hue"
setHue(hue)
}

View File

@@ -1,229 +0,0 @@
/**
* Trend Setter - Dimmer Group Device
*
* Copyright 2015 Chris Kitch
*
* 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.
*
*/
metadata {
definition (name: "Dimmer Group Device", namespace: "kriskit.trendSetter", author: "Chris Kitch") {
capability "Actuator"
capability "Sensor"
capability "Switch"
capability "Switch Level"
command "adjustLevel"
attribute "onPercentage", "number"
attribute "levelSync", "string"
}
simulator {
// TODO: define status and reply messages here
}
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label: '${name}', action: "switch.off", icon: "st.lights.multi-light-bulb-on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "off", label: '${name}', action: "switch.on", icon: "st.lights.multi-light-bulb-off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "turningOn", label: '${name}', action: "switch.off", icon: "st.lights.multi-light-bulb-on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "turningOff", label: '${name}', action: "switch.on", icon: "st.lights.multi-light-bulb-off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "half", label: '${name}', action: "switch.on", icon: "st.lights.multi-light-bulb-on", backgroundColor: "#a3d164", nextState: "turningOn"
attributeState "mostlyOn", label: 'Onish', action: "switch.on", icon: "st.lights.multi-light-bulb-on", backgroundColor: "#79b821", nextState: "turningOn"
attributeState "mostlyOff", label: 'Offish', action: "switch.off", icon: "st.lights.multi-light-bulb-off", backgroundColor: "#d1e5b5", nextState: "turninOff"
}
tileAttribute ("device.onPercentage", key: "SECONDARY_CONTROL") {
attributeState "onPercentage", label:'${currentValue}% On'
attributeState "100", label:'All On'
attributeState "0", label:'All Off'
}
tileAttribute("device.level", key: "SLIDER_CONTROL") {
attributeState "default", label: '', action: "switch level.setLevel"
}
}
standardTile("levelLabel", "levelLable", height:1, width:1, decoration: "flat", inactiveLabel: true) {
state "default", label:"Level", unit:"", icon: "st.illuminance.illuminance.bright"
}
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 3, inactiveLabel: false) {
state "level", action:"switch level.setLevel"
}
valueTile("levelValue", "device.level", inactiveLabel: true, height:1, width:1, decoration: "flat") {
state "default", label:'${currentValue}%', unit:""
}
valueTile("levelSync", "device.levelSync", height:1, width:1) {
state "default", label:' Sync ', unit:"", action: "adjustLevel", backgroundColor: "#ff9900"
state "ok", label:'', unit:"", backgroundColor: "#00b509"
}
}
main "switch"
details(["switch", "levelLabel", "levelSliderControl", "levelValue", "levelSync"])
}
def parse(String description) {
}
def groupSync(name, values) {
try {
"sync${name.capitalize()}"(values)
} catch(ex) {
log.error "Error executing 'sync${name.capitalize()}' method: $ex"
}
}
// SWITCH
def on() {
on(true)
}
def on(triggerGroup) {
sendEvent(name: "switch", value: "on")
sendEvent(name: "onPercentage", value: 100, displayed: false)
if (triggerGroup)
parent.performGroupCommand("on")
}
def off() {
off(true)
}
def off(triggerGroup) {
sendEvent(name: "switch", value: "off")
sendEvent(name: "onPercentage", value: 0, displayed: false)
if (triggerGroup)
parent.performGroupCommand("off")
}
def syncSwitch(values) {
log.debug "syncSwitch(): $values"
def onCount = values?.count { it == "on" }
def percentOn = (int)Math.floor((onCount / values?.size()) * 100)
log.debug "Percent On: $percentOn"
if (percentOn == 0 || percentOn == 100) {
if (percentOn == 0)
off(false)
else
on(false)
return
}
def value = null
if (percentOn == 50)
value = "half"
else if (percentOn > 0 && percentOn < 50)
value = "mostlyOff"
else if (percentOn > 50 && percentOn < 100)
value = "mostlyOn"
sendEvent(name: "switch", value: value)
sendEvent(name: "onPercentage", value: percentOn, displayed: false)
}
// LEVEL
def setLevel(val){
setLevel(val, true)
}
def setLevel(val, triggerGroup) {
log.debug "Setting level to $val"
if (val < 0)
val = 0
if( val > 100)
val = 100
if (triggerGroup) {
if (val == 0)
off()
else
on()
}
sendEvent(name: "level", value: val, isStateChange: true)
sendEvent(name: "switch.setLevel", value: val, isStateChange: true)
if (triggerGroup)
parent.performGroupCommand("setLevel", [val])
}
def syncLevel(values) {
log.debug "syncLevel(): $values"
def valueCount = values?.size()
def valueCountBy = values?.countBy { it }
def matchValue = "bad"
def level = device.currentValue("level")
valueCountBy.each { value, count ->
if (count == valueCount) {
level = value
matchValue = "ok"
return true
}
}
if (matchValue == "bad")
level = getAdjustmentLevel(values)
setLevel(level, false)
sendEvent(name: "levelSync", value: matchValue, displayed: false)
}
def adjustLevel() {
def values = parent.getGroupCurrentValues("level")
if (!values)
return
def valueCountBy = values?.countBy { it }
valueCountBy = valueCountBy?.sort { a, b -> b.value <=> a.value }
def level = getAdjustmentLevel(values)
setLevel(level)
}
def getAdjustmentLevel(values) {
if (!values)
return
def valueCountBy = values?.countBy { it }
valueCountBy = valueCountBy?.sort { a, b -> b.value <=> a.value }
def level = device.currentValue("level")
if (valueCountBy.size() > 1) {
if (valueCountBy.size() == values.size()) {
log.debug "Values are all different - making average"
level = Math.round(values.sum() / values.size())
} else {
log.debug "Some values are the same, choosing most popular"
def firstItem = valueCountBy.find { true }
level = firstItem.key
}
}
return level
}

View File

@@ -1,162 +0,0 @@
/**
* Power Meter Group Device
*
* Copyright 2015 Chris Kitch
*
* 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.
*
*/
metadata {
definition (name: "Power Meter Group Device", namespace: "kriskit.trendsetter", author: "Chris Kitch") {
capability "Power Meter"
capability "Sensor"
capability "Refresh"
attribute "powerUsage", "string"
}
simulator {
// TODO: define status and reply messages here
}
tiles(scale: 2) {
multiAttributeTile(name:"main", type: "lighting", width: 6, height: 4) {
tileAttribute ("device.powerUsage", key: "PRIMARY_CONTROL") {
attributeState "off", label: '${name}', backgroundColor: "#ffffff", icon: "st.Appliances.appliances17"
attributeState "low", label: '${name}', backgroundColor: "#5CB85C", icon: "st.Appliances.appliances17"
attributeState "medium", label: '${name}', backgroundColor: "#ff7b00", icon: "st.Appliances.appliances17"
attributeState "high", label: '${name}', backgroundColor: "#c90000", icon: "st.Appliances.appliances17"
attributeState "veryHigh", label: '${name}', backgroundColor: "#ff0000", icon: "st.Appliances.appliances17"
}
tileAttribute ("device.power", key: "SECONDARY_CONTROL") {
attributeState "default", label: '${currentValue} W'
}
}
standardTile("refresh", "refresh", height:2, width:6, inactiveLabel: false, decoration: "flat") {
state "default", action: "refresh.refresh", icon:"st.secondary.refresh"
}
main("main")
details(["main", "refresh"])
}
}
// parse events into attributes
def parse(String description) {
}
def groupSync(name, values) {
try {
"sync${name.capitalize()}"(values)
} catch(ex) {
log.error "Error executing 'sync${name.capitalize()}' method: $ex"
}
}
def refresh() {
def powerValues = parent.getGroupCurrentValues("power")
syncPower(powerValues)
}
// POWER
def syncPower(values) {
log.debug "syncPower(): $values"
def total = values?.sum()
if (total == 0) {
sendEvent(name: "power", value: 0)
sendEvent(name: "powerUsage", value: "off")
return
}
def aggregate = state.powerAggregate ?: []
state.powerSyncCount = state.powerSyncCount + 1
if (state.powerSyncCount != null && state.powerSyncCount % 5 != 0) {
aggregate.push(total)
state.powerAggregate = aggregate
return
}
def aggregatedAverage = getAverage(aggregate)
log.debug "Aggregated Average Power: $aggregatedAverage"
sendEvent(name: "power", value: aggregatedAverage)
def level = getPowerUsageLevel(aggregatedAverage)
log.debug "Power usage level: $level"
sendEvent(name: "powerUsage", value: level)
state.powerAggregate = []
}
def getPowerUsageLevel(value) {
if (value == 0)
return "off"
def boundaries = getPowerUsageBoundaries()
if (!boundaries)
return "low"
log.debug "Determining power usage level with boundaries: $boundaries for value $value"
if (value > 0 && value <= boundaries.bottom)
return "low"
if (value > boundaries.bottom && value < boundaries.top)
return "medium"
if (value >= boundaries.top && value <= boundaries.max)
return "high"
if (value > boundaries.max) {
state.powerUsageBoundaries = null
return "veryHigh"
}
}
def getPowerUsageBoundaries() {
if (state.powerUsageBoundaries && state.powerSyncCount < 100)
return state.powerUsageBoundaries
def events = device.events([max: 500])
def powerEvents = events?.findAll {
it.name == "power" && it.doubleValue > 0
}
def powerValues = powerEvents*.doubleValue
powerValues.sort()
def eventCount = powerValues?.size()
def eventChunkSize = (int)Math.round(eventCount / 2)
def chunkedEvents = powerValues.collate(eventChunkSize)
if (chunkedEvents.size() < 2)
return null
def boundaries = [
top: getAverage(chunkedEvents[1]),
bottom: getAverage(chunkedEvents[0]),
max: powerValues.max()
]
state.powerSyncCount = 0
state.powerUsageBoundaries = boundaries
log.debug "New boundaries: $boundaries"
return boundaries
}
def getAverage(values) {
return Math.round((values.sum() / values.size()) * 100) / 100
}

View File

@@ -1,116 +0,0 @@
/**
* Trend Setter - Switch Group Device
*
* Copyright 2015 Chris Kitch
*
* 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.
*
*/
metadata {
definition (name: "Switch Group Device", namespace: "kriskit.trendSetter", author: "Chris Kitch") {
capability "Actuator"
capability "Sensor"
capability "Switch"
attribute "onPercentage", "number"
}
simulator {
// TODO: define status and reply messages here
}
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "turningOn", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "turningOff", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "half", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#a3d164", nextState: "turningOn"
attributeState "mostlyOn", label: 'Onish', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#79b821", nextState: "turningOn"
attributeState "mostlyOff", label: 'Offish', action: "switch.off", icon: "st.switches.switch.off", backgroundColor: "#d1e5b5", nextState: "turninOff"
}
tileAttribute ("device.onPercentage", key: "SECONDARY_CONTROL") {
attributeState "onPercentage", label:'${currentValue}% On'
attributeState "100", label:'All On'
attributeState "0", label:'All Off'
}
}
}
main "switch"
details(["switch"])
}
def parse(String description) {
}
def groupSync(name, values) {
try {
"sync${name.capitalize()}"(values)
} catch(ex) {
log.error "Error executing 'sync${name.capitalize()}' method: $ex"
}
}
// SWITCH
def on() {
on(true)
}
def on(triggerGroup) {
sendEvent(name: "switch", value: "on")
sendEvent(name: "onPercentage", value: 100, displayed: false)
if (triggerGroup)
parent.performGroupCommand("on")
}
def off() {
off(true)
}
def off(triggerGroup) {
sendEvent(name: "switch", value: "off")
sendEvent(name: "onPercentage", value: 0, displayed: false)
if (triggerGroup)
parent.performGroupCommand("off")
}
def syncSwitch(values) {
log.debug "syncSwitch(): $values"
def onCount = values?.count { it == "on" }
def percentOn = (int)Math.floor((onCount / values?.size()) * 100)
log.debug "Percent On: $percentOn"
if (percentOn == 0 || percentOn == 100) {
if (percentOn == 0)
off(false)
else
on(false)
return
}
def value = null
if (percentOn == 50)
value = "half"
else if (percentOn > 0 && percentOn < 50)
value = "mostlyOff"
else if (percentOn > 50 && percentOn < 100)
value = "mostlyOn"
sendEvent(name: "switch", value: value)
sendEvent(name: "onPercentage", value: percentOn, displayed: false)
}

View File

@@ -59,15 +59,6 @@ metadata {
}
}
def installed() {
log.debug "${device} installed"
}
def updated() {
log.debug "${device} updated"
configureHealthCheck()
}
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
@@ -105,14 +96,6 @@ def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh()
}
def configureHealthCheck() {
log.debug "configureHealthCheck"
unschedule("healthPoll")
runEvery5Minutes("healthPoll")
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
def healthPoll() {
log.debug "healthPoll()"
def cmds = zigbee.onOffRefresh() + zigbee.levelRefresh()
@@ -120,5 +103,9 @@ def healthPoll() {
}
def configure() {
refresh()
unschedule()
runEvery5Minutes("healthPoll")
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
zigbee.onOffRefresh() + zigbee.levelRefresh()
}

View File

@@ -74,15 +74,6 @@ metadata {
}
}
def installed() {
log.debug "${device} installed"
}
def updated() {
log.debug "${device} updated"
configureHealthCheck()
}
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
@@ -149,14 +140,10 @@ def refresh() {
zigbee.onOffRefresh() + zigbee.electricMeasurementPowerRefresh()
}
def configureHealthCheck() {
def configure() {
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
def configure() {
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
refresh() + zigbee.onOffConfig(0, 300) + powerConfig()

View File

@@ -84,15 +84,6 @@ metadata {
}
}
def installed() {
log.debug "${device} installed"
}
def updated() {
log.debug "${device} updated"
configureHealthCheck()
}
def parse(String description) {
log.debug "description: $description"
@@ -312,13 +303,11 @@ def refresh() {
return refreshCmds + enrollResponse()
}
def configureHealthCheck() {
def configure() {
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
def configure() {
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config

View File

@@ -88,15 +88,6 @@ metadata {
}
}
def installed() {
log.debug "${device} installed"
}
def updated() {
log.debug "${device} updated"
configureHealthCheck()
}
def parse(String description) {
log.debug "description: $description"
@@ -327,13 +318,11 @@ def refresh() {
return refreshCmds + enrollResponse()
}
def configureHealthCheck() {
def configure() {
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
def configure() {
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config

View File

@@ -115,34 +115,6 @@ metadata {
}
}
def installed() {
log.debug "${device} installed"
}
def updated() {
log.debug "updated called"
log.info "garage value : $garageSensor"
if (garageSensor == "Yes") {
def descriptionText = "Updating device to garage sensor"
if (device.latestValue("status") == "open") {
sendEvent(name: 'status', value: 'garage-open', descriptionText: descriptionText, translatable: true)
}
else if (device.latestValue("status") == "closed") {
sendEvent(name: 'status', value: 'garage-closed', descriptionText: descriptionText, translatable: true)
}
}
else {
def descriptionText = "Updating device to open/close sensor"
if (device.latestValue("status") == "garage-open") {
sendEvent(name: 'status', value: 'open', descriptionText: descriptionText, translatable: true)
}
else if (device.latestValue("status") == "garage-closed") {
sendEvent(name: 'status', value: 'closed', descriptionText: descriptionText, translatable: true)
}
}
configureHealthCheck()
}
def parse(String description) {
Map map = [:]
if (description?.startsWith('catchall:')) {
@@ -274,6 +246,29 @@ private Map parseIasMessage(String description) {
return resultMap
}
def updated() {
log.debug "updated called"
log.info "garage value : $garageSensor"
if (garageSensor == "Yes") {
def descriptionText = "Updating device to garage sensor"
if (device.latestValue("status") == "open") {
sendEvent(name: 'status', value: 'garage-open', descriptionText: descriptionText, translatable: true)
}
else if (device.latestValue("status") == "closed") {
sendEvent(name: 'status', value: 'garage-closed', descriptionText: descriptionText, translatable: true)
}
}
else {
def descriptionText = "Updating device to open/close sensor"
if (device.latestValue("status") == "garage-open") {
sendEvent(name: 'status', value: 'open', descriptionText: descriptionText, translatable: true)
}
else if (device.latestValue("status") == "garage-closed") {
sendEvent(name: 'status', value: 'closed', descriptionText: descriptionText, translatable: true)
}
}
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
@@ -416,13 +411,11 @@ def refresh() {
return refreshCmds + enrollResponse()
}
def configureHealthCheck(){
def configure() {
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
def configure() {
log.debug "Configuring Reporting"
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity

View File

@@ -75,15 +75,6 @@ metadata {
}
}
def installed() {
log.debug "${device} installed"
}
def updated() {
log.debug "${device} updated"
configureHealthCheck()
}
def parse(String description) {
log.debug "description: $description"
@@ -274,12 +265,11 @@ def refresh() {
return refreshCmds + enrollResponse()
}
def configureHealthCheck() {
def configure() {
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
def configure() {
log.debug "Configuring Reporting, IAS CIE, and Bindings."
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity

View File

@@ -69,15 +69,6 @@ metadata {
}
}
def installed() {
log.debug "${device} installed"
}
def updated() {
log.debug "${device} updated"
configureHealthCheck()
}
def parse(String description) {
log.debug "description: $description"
@@ -277,13 +268,11 @@ def refresh()
zigbee.readAttribute(0x0001, 0x0020)
}
def configureHealthCheck() {
def configure() {
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
def configure() {
log.debug "Configuring Reporting and Bindings."
def humidityConfigCmds = [
"zdo bind 0x${device.deviceNetworkId} 1 1 0xFC45 {${device.zigbeeId}} {}", "delay 500",

View File

@@ -1,2 +0,0 @@
.st-ignore
README.md

View File

@@ -1,41 +0,0 @@
# GE Plug-In/In-Wall Smart Dimmer (ZigBee)
Works with:
* [GE In-Wall Smart Dimmer (ZigBee)](https://shop.smartthings.com/#!/products/ge-in-wall-smart-dimmer-switch)
* [GE Plug-In Smart Dimmer (ZigBee)](https://www.smartthings.com/works-with-smartthings/ge/ge-plug-in-smart-dimmer-zigbee)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Troubleshooting](#Troubleshooting)
## Capabilities
* **Actuator** - represents that a Device has commands
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Refresh** - _refresh()_ command for status updates
* **Power Meter** - ability to check the power meter(energy consumption) of device
* **Sensor** - represents the device sensor capability
* **Switch** - can detect state (possible values: on/off)
* **Switch Level** - represents current light level, usually 0-100 in percent
* **Health Check** - indicates ability to get device health notifications
## Device Health
A Zigbee dimmer with maxReportTime of 5 mins.
Check-in interval is double the value of maxReportTime.
This gives the device twice the amount of time to respond before it is marked as offline.
Enrolls with default periodic reporting until newer 5 min interval is confirmed
It then enrolls the device with updated checkInterval i.e. 12 mins
## Troubleshooting
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
Pairing needs to be tried again by placing the device closer to the hub.
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
* [GE Z-Wave In-Wall Smart Dimmer (GE 45857) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204988564-GE-In-Wall-Smart-Dimmer-45857GE-ZigBee-)
* [GE Zigbee Plug-in Smart Dimmer (GE 45852) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/205239280-GE-Plug-In-Smart-Dimmer-45852GE-ZigBee-)

View File

@@ -21,7 +21,6 @@ metadata {
capability "Sensor"
capability "Switch"
capability "Switch Level"
capability "Health Check"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B04"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702"
@@ -71,20 +70,8 @@ def parse(String description) {
}
}
else {
def cluster = zigbee.parse(description)
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
if (cluster.data[0] == 0x00){
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbee.parseDescriptionAsMap(description)
}
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbee.parseDescriptionAsMap(description)
}
}
@@ -100,22 +87,11 @@ def setLevel(value) {
zigbee.setLevel(value)
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.onOffRefresh()
}
def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.simpleMeteringPowerRefresh() + zigbee.electricMeasurementPowerRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.simpleMeteringPowerConfig() + zigbee.electricMeasurementPowerConfig()
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.simpleMeteringPowerRefresh() + zigbee.electricMeasurementPowerRefresh() + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.simpleMeteringPowerConfig() + zigbee.electricMeasurementPowerConfig()
}
def configure() {
log.debug "Configuring Reporting and Bindings."
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
refresh()
}

View File

@@ -48,15 +48,6 @@ metadata {
}
}
def installed() {
log.debug "${device} installed"
}
def updated() {
log.debug "${device} updated"
configureHealthCheck()
}
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
@@ -109,13 +100,12 @@ def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig()
}
def configureHealthCheck() {
def configure() {
log.debug "Configuring Reporting and Bindings."
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
def configure() {
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig()
}

View File

@@ -70,16 +70,6 @@ metadata {
}
}
def installed() {
log.debug "${device} installed"
}
def updated() {
log.debug "${device} updated"
configureHealthCheck()
}
//Globals
private getATTRIBUTE_HUE() { 0x0000 }
private getATTRIBUTE_SATURATION() { 0x0001 }
@@ -148,17 +138,16 @@ def ping() {
}
def refresh() {
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01)
}
def configureHealthCheck() {
def configure() {
log.debug "Configuring Reporting and Bindings."
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
def configure() {
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
refresh()
}

View File

@@ -21,7 +21,6 @@ metadata {
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0006", outClusters: "0003, 0006, 0019, 0406", manufacturer: "Leviton", model: "ZSS-10", deviceJoinName: "Leviton Switch"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0006", outClusters: "000A", manufacturer: "HAI", model: "65A21-1", deviceJoinName: "Leviton Wireless Load Control Module-30amp"
}
// simulator metadata

View File

@@ -69,15 +69,6 @@ metadata {
}
}
def installed() {
log.debug "${device} installed"
}
def updated() {
log.debug "${device} updated"
configureHealthCheck()
}
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
@@ -130,17 +121,16 @@ def ping() {
}
def refresh() {
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig()
}
def configureHealthCheck() {
def configure() {
log.debug "Configuring Reporting and Bindings."
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
def configure() {
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
refresh()
}

View File

@@ -1,317 +0,0 @@
/**
* Trend Setter - Group
*
* Copyright 2015 Chris Kitch
*
* 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: "Group",
namespace: "kriskit.trendSetter",
author: "Chris Kitch",
description: "A child SmartApp for Trend Setter for handling a group of devices.",
category: "My Apps",
iconUrl: "https://cdn.rawgit.com/Kriskit/SmartThingsPublic/master/smartapps/kriskit/trendsetter/icon.png",
iconX2Url: "https://cdn.rawgit.com/Kriskit/SmartThingsPublic/master/smartapps/kriskit/trendsetter/icon@2x.png",
iconX3Url: "https://cdn.rawgit.com/Kriskit/SmartThingsPublic/master/smartapps/kriskit/trendsetter/icon@3x.png",
parent: "kriskit.trendsetter:Trend Setter")
def version() {
return "1.0"
}
def typeDefinitions() {
return [
[
type: "switch",
singular: "Switch",
plural: "Switches",
deviceType: "Switch Group Device",
attributes: [
[name: "switch"]
]
],
[
type: "switchLevel",
singular: "Dimmer",
plural: "Dimmers",
deviceType: "Dimmer Group Device",
inherits: "switch",
attributes: [
[name: "level"]
]
],
[
type: "colorControl",
singular: "Colorful Light",
plural: "Colorful Lights",
deviceType: "Colorful Light Group Device",
inherits: "switchLevel",
attributes: [
[name: "hue"],
[name: "saturation"],
[name: "color"]
]
],
[
type: "powerMeter",
singular: "Power Meter",
plural: "Power Meters",
deviceType: "Power Meter Group Device",
attributes: [
[name: "power"]
]
]
]
}
// Setup
preferences {
page(name: "configure")
}
def configure() {
atomicState.typeDefinitions = null
def controller = getControllerDevice();
dynamicPage(name: "configure", uninstall: controller != null, install: true) {
if (!controller) {
section {
input "deviceType", "enum", title: "Device Type", required: true, submitOnChange: true, options: getDeviceTypeOptions()
paragraph "This cannot be changed once the group is created.", color: "#ffcc00"
}
}
if (deviceType) {
def definition = getTypeDefinition(deviceType)
section(title: controller == null ? "Grouping" : null) {
label title: "Group Name", required: true
input "devices", "capability.${deviceType}", title: "${definition.plural}", multiple: true, required: true, submitOnChange: controller != null
if (selectedDevicesContainsController()) {
paragraph "WARNING: You have selected the controller ${definition.singular.toLowerCase()} for this group. This will likely cause unexpected behaviour.\n\nPlease uncheck the '${controller.displayName}' from the selected ${definition.plural.toLowerCase()}.",
image: "https://cdn2.iconfinder.com/data/icons/freecns-cumulus/32/519791-101_Warning-512.png"
}
}
if (controller == null) {
section(title: "Controller") {
input "deviceName", "text", title: "${definition.singular} Name", required: true, description: "For the controlling virtual ${definition.singular.toLowerCase()} to be created"
}
}
if (definition.advanced) {
section(title: "Advanced", hidden: true, hideable: true) {
}
}
}
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
installControllerDevice()
initialize()
}
def uninstalled() {
log.debug "Uninstalled"
}
def installControllerDevice() {
def definition = getTypeDefinition()
log.debug "Installing switch group controller device..."
addChildDevice("kriskit.trendSetter", definition.deviceType, UUID.randomUUID().toString(), null, ["name": deviceName, "label": deviceName, completedSetup: true])
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
def definition = getTypeDefinition()
addSubscriptions(definition)
def namesToCheck = definition.attributes?.collect { it.name }
updateControllerState(namesToCheck)
}
def addSubscriptions(definition) {
def controller = getControllerDevice()
definition.attributes?.each {
log.debug "Subscribing to ${it.name}..."
subscribe(devices, it.name, onDeviceAttributeChange)
}
}
// Subscription Handlers
def onDeviceAttributeChange(evt) {
def namesToCheck = atomicState.namesToCheck ?: []
log.debug "Device state change: ${evt.device.displayName} -> ${evt.name} = ${evt.value}"
if (!namesToCheck.any { it == evt.name })
namesToCheck.push(evt.name)
atomicState.namesToCheck = namesToCheck
runIn(1, "updateControllerState")
}
def updateControllerState() {
def namesToCheck = atomicState.namesToCheck
updateControllerState(namesToCheck)
atomicState.namesToCheck = null
}
def updateControllerState(namesToCheck) {
if (!namesToCheck)
return
def controller = getControllerDevice()
namesToCheck?.each { name ->
def values = devices?.currentValue(name)
values?.removeAll([null])
log.debug "Updating Controller State: $name -> $values"
controller.groupSync(name, values)
}
}
def performGroupCommand(command, arguments = null) {
runCommand(devices, command, arguments ?: [])
}
def runCommand(target, command, args) {
log.debug "Running command '${command}' with arguments ${args} on ${target}..."
$performCommand(target, command, args)
}
def getGroupCurrentValues(name) {
return devices?.currentValue(name)
}
// Utilities
def getTypeDefinitions() {
if (atomicState.version != version()) {
atomicState.typeDefinitions = null
atomicState.version = version()
}
if (atomicState.typeDefinitions)
return atomicState.typeDefinitions
log.debug "Building type definitions..."
def result = []
def definitions = typeDefinitions()
definitions?.each { definition ->
if (definition.inherits)
definition = mergeAttributes(definition, definitions.find { it.type == definition.inherits })
result.push(definition)
}
atomicState.typeDefinitions = result
return result
}
def mergeAttributes(definition, inheritedDefinition) {
inheritedDefinition.attributes?.each { attr ->
if (!definition.attributes?.any { it.name == attr.name })
definition.attributes.push(attr)
}
if (inheritedDefinition.inherits) {
def definitions = typeDefinitions()
definition = mergeAttributes(definition, definitions.find { it.type == inheritedDefinition.inherits })
}
return definition
}
def getControllerDevice() {
return getChildDevices()?.find { true }
}
def getTypeDefinition() {
return getTypeDefinition(deviceType)
}
def getTypeDefinition(type) {
return getTypeDefinitions().find {
it.type == type
}
}
def getDeviceTypeOptions() {
return getTypeDefinitions().collect {
["${it.type}": it.singular]
}
}
def selectedDevicesContainsController() {
def controller = getControllerDevice()
return devices?.any {
it?.deviceNetworkId == controller?.deviceNetworkId
}
}
private $performCommand(target, command, args) {
switch(args?.size()) {
default:
target?."$command"()
break
case 1:
target?."$command"(args[0])
break
case 2:
target?."$command"(args[0], args[1])
break
case 3:
target?."$command"(args[0], args[1], args[2])
break
case 4:
target?."$command"(args[0], args[1], args[2], args[3])
break
case 5:
target?."$command"(args[0], args[1], args[2], args[3], args[4], args[5])
break
case 6:
target?."$command"(args[0], args[1], args[2], args[3], args[4], args[5], args[6])
break
case 7:
target?."$command"(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7])
break
case 8:
target?."$command"(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8])
break
case 9:
target?."$command"(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9])
break
}
}

View File

@@ -1,58 +0,0 @@
/**
* Trend Setter
*
* Copyright 2015 Chris Kitch
*
* 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: "Trend Setter",
namespace: "kriskit.trendSetter",
author: "Chris Kitch",
description: "Uses virtual child devices to group other devices together and perform commands and aggregate data from the group.",
category: "My Apps",
iconUrl: "https://cdn.rawgit.com/Kriskit/SmartThingsPublic/master/smartapps/kriskit/trendsetter/icon.png",
iconX2Url: "https://cdn.rawgit.com/Kriskit/SmartThingsPublic/master/smartapps/kriskit/trendsetter/icon@2x.png",
iconX3Url: "https://cdn.rawgit.com/Kriskit/SmartThingsPublic/master/smartapps/kriskit/trendsetter/icon@3x.png",
singleInstance: true)
preferences {
page(name: "mainPage")
}
def mainPage() {
dynamicPage(name: "mainPage", title: "Your Groups", install: true, uninstall: true, submitOnChange: true) {
section {
app(name: "groups", appName: "Group", namespace: "kriskit.trendSetter", title: "Create Group...", multiple: true)
}
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
// TODO: subscribe to attributes, devices, locations, etc.
}
def childUninstalled() {
}

View File

@@ -0,0 +1,113 @@
/**
* 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: "Sleep Routine",
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/smartthings-plus/category-icons/sleepsense.png",
iconX2Url: "https://s3.amazonaws.com/smartthings-plus/category-icons/sleepsense.png",
iconX3Url: "https://s3.amazonaws.com/smartthings-plus/category-icons/sleepsense.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() {
updateSolutionSummary();
}
def updateSolutionSummary() {
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
);
}
card("Action History") {
tiles {
eventTile { }
}
}
def getLabel(value)
{
def str_Title=[
"kr": "룰",
"us": "Rules"
]
def str_SectionTitle=[
"kr": "새로운 자동화 룰 만들기",
"us": "New Sleep Routine Automation"
]
def lang = "us"
if(lang == "ko") //clientLocale?.language
{
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"
}