Compare commits

..

1 Commits

Author SHA1 Message Date
이진희
25d926ed15 MSA-981: test입니다 2016-03-23 02:36:14 -05:00
19 changed files with 222 additions and 208 deletions

View File

@@ -7,10 +7,9 @@ apply plugin: 'smartthings-hipchat'
buildscript {
dependencies {
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.6"
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.3"
}
repositories {
mavenLocal()
jcenter()
maven {
credentials {

View File

@@ -15,13 +15,13 @@ deployment:
develop:
branch: master
commands:
- ./gradlew deployArchives -PsmartThingsArtifactoryUserName=$ARTIFACTORY_USERNAME -PsmartThingsArtifactoryPassword=$ARTIFACTORY_PASSWORD -Ps3Buckets="$S3_BUCKETS_DEV"
- ./gradlew deployArchives -PsmartThingsArtifactoryUserName=$ARTIFACTORY_USERNAME -PsmartThingsArtifactoryPassword=$ARTIFACTORY_PASSWORD -Ps3BucketName=$S3_BUCKET_NAME_PREPROD_DEV
- ./gradlew hipchatSendNotification -PsmartThingsArtifactoryUserName=$ARTIFACTORY_USERNAME -PsmartThingsArtifactoryPassword=$ARTIFACTORY_PASSWORD -Pbranch=$CIRCLE_BRANCH
- ./gradlew hipchatShareFile -PsmartThingsArtifactoryUserName=$ARTIFACTORY_USERNAME -PsmartThingsArtifactoryPassword=$ARTIFACTORY_PASSWORD
stage:
branch: staging
commands:
- ./gradlew deployArchives -PsmartThingsArtifactoryUserName=$ARTIFACTORY_USERNAME -PsmartThingsArtifactoryPassword=$ARTIFACTORY_PASSWORD -Ps3Buckets="$S3_BUCKETS_STAGE"
- ./gradlew deployArchives -PsmartThingsArtifactoryUserName=$ARTIFACTORY_USERNAME -PsmartThingsArtifactoryPassword=$ARTIFACTORY_PASSWORD -Ps3BucketName=$S3_BUCKET_NAME_PREPROD_STAGING
- ./gradlew hipchatSendNotification -PsmartThingsArtifactoryUserName=$ARTIFACTORY_USERNAME -PsmartThingsArtifactoryPassword=$ARTIFACTORY_PASSWORD -Pbranch=$CIRCLE_BRANCH
- ./gradlew hipchatShareFile -PsmartThingsArtifactoryUserName=$ARTIFACTORY_USERNAME -PsmartThingsArtifactoryPassword=$ARTIFACTORY_PASSWORD

View File

@@ -251,4 +251,4 @@ def huesatToRGB(float hue, float sat) {
case 4: return [t, p, 255]
case 5: return [255, p, q]
}
}
}

View File

@@ -103,104 +103,62 @@ void nextLevel() {
}
void setLevel(percent) {
log.debug "Executing 'setLevel'"
if (verifyPercent(percent)) {
parent.setLevel(this, percent)
sendEvent(name: "level", value: percent, descriptionText: "Level has changed to ${percent}%")
sendEvent(name: "switch", value: "on")
}
log.debug "Executing 'setLevel'"
parent.setLevel(this, percent)
sendEvent(name: "level", value: percent, descriptionText: "Level has changed to ${percent}%")
}
void setSaturation(percent) {
log.debug "Executing 'setSaturation'"
if (verifyPercent(percent)) {
parent.setSaturation(this, percent)
sendEvent(name: "saturation", value: percent, displayed: false)
}
log.debug "Executing 'setSaturation'"
parent.setSaturation(this, percent)
sendEvent(name: "saturation", value: percent, displayed: false)
}
void setHue(percent) {
log.debug "Executing 'setHue'"
if (verifyPercent(percent)) {
parent.setHue(this, percent)
sendEvent(name: "hue", value: percent, displayed: false)
}
log.debug "Executing 'setHue'"
parent.setHue(this, percent)
sendEvent(name: "hue", value: percent, displayed: false)
}
void setColor(value) {
log.debug "setColor: ${value}, $this"
def events = []
def validValues = [:]
if (verifyPercent(value.hue)) {
events << createEvent(name: "hue", value: value.hue, displayed: false)
validValues.hue = value.hue
}
if (verifyPercent(value.saturation)) {
events << createEvent(name: "saturation", value: value.saturation, displayed: false)
validValues.saturation = value.saturation
}
if (value.hex != null) {
if (value.hex ==~ /^\#([A-Fa-f0-9]){6}$/) {
events << createEvent(name: "color", value: value.hex)
validValues.hex = value.hex
} else {
log.warn "$value.hex is not a valid color"
}
}
if (verifyPercent(value.level)) {
events << createEvent(name: "level", value: value.level, descriptionText: "Level has changed to ${value.level}%")
validValues.level = value.level
}
if (value.switch == "off" || (value.level != null && value.level <= 0)) {
events << createEvent(name: "switch", value: "off")
validValues.switch = "off"
} else {
events << createEvent(name: "switch", value: "on")
validValues.switch = "on"
}
if (!events.isEmpty()) {
parent.setColor(this, validValues)
}
events.each {
sendEvent(it)
}
log.debug "setColor: ${value}, $this"
parent.setColor(this, value)
if (value.hue) { sendEvent(name: "hue", value: value.hue, displayed: false)}
if (value.saturation) { sendEvent(name: "saturation", value: value.saturation, displayed: false)}
if (value.hex) { sendEvent(name: "color", value: value.hex)}
if (value.level) { sendEvent(name: "level", value: value.level, descriptionText: "Level has changed to ${value.level}%")}
sendEvent(name: "switch", value: "on")
}
void reset() {
log.debug "Executing 'reset'"
log.debug "Executing 'reset'"
def value = [level:100, saturation:56, hue:23]
setAdjustedColor(value)
parent.poll()
parent.poll()
}
void setAdjustedColor(value) {
if (value) {
if (value) {
log.trace "setAdjustedColor: ${value}"
def adjusted = value + [:]
adjusted.hue = adjustOutgoingHue(value.hue)
// Needed because color picker always sends 100
adjusted.level = null
setColor(adjusted)
} else {
log.warn "Invalid color input"
}
}
void setColorTemperature(value) {
if (value) {
if (value) {
log.trace "setColorTemperature: ${value}k"
parent.setColorTemperature(this, value)
sendEvent(name: "colorTemperature", value: value)
sendEvent(name: "switch", value: "on")
} else {
log.warn "Invalid color temperature"
}
}
}
void refresh() {
log.debug "Executing 'refresh'"
parent.manualRefresh()
log.debug "Executing 'refresh'"
parent.manualRefresh()
}
def adjustOutgoingHue(percent) {
@@ -219,14 +177,3 @@ def adjustOutgoingHue(percent) {
log.info "percent: $percent, adjusted: $adjusted"
adjusted
}
def verifyPercent(percent) {
if (percent == null)
return false
else if (percent >= 0 && percent <= 100) {
return true
} else {
log.warn "$percent is not 0-100"
return false
}
}

View File

@@ -79,12 +79,8 @@ void off() {
void setLevel(percent) {
log.debug "Executing 'setLevel'"
if (percent != null && percent >= 0 && percent <= 100) {
parent.setLevel(this, percent)
sendEvent(name: "level", value: percent)
} else {
log.warn "$percent is not 0-100"
}
parent.setLevel(this, percent)
sendEvent(name: "level", value: percent)
}
void refresh() {

View File

@@ -28,8 +28,4 @@
'''{{ device.displayName }} is On'''.ko={{ device.displayName }}켜졌습니다.
'''{{ device.displayName }} is Off'''.ko={{ device.displayName }}꺼졌습니다.
'''{{ device.displayName }} power is {{ value }} Watts'''.ko={{ device.displayName }} 전원은 {{ value }}와트입니다
'''On'''.ko=켜기
'''Off'''.ko=끄기
'''Turning On'''.ko=켜기
'''Turning Off'''.ko=끄기
#==============================================================================

View File

@@ -65,10 +65,10 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "off", label: 'Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "turningOn", label: 'Turning On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "turningOff", label: 'Turning Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
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"
}
tileAttribute ("power", key: "SECONDARY_CONTROL") {
attributeState "power", label:'${currentValue} W'

View File

@@ -43,7 +43,3 @@
'''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}남아있는 배터리는 {{ value }}%입니다.
'''Updating device to garage sensor'''.ko=기기-차고 센서 업데이트 중
'''Updating device to open/close sensor'''.ko=기기-열림/닫힘 센서 업데이트 중
'''Inactive'''.ko=비활성
'''Active'''.ko=활성
'''Open'''.ko=열다
'''Closed'''.ko=닫은

View File

@@ -83,19 +83,19 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){
tileAttribute ("device.status", key: "PRIMARY_CONTROL") {
attributeState "open", label:'Open', icon:"st.contact.contact.open", backgroundColor:"#ffa81e"
attributeState "closed", label:'Closed', icon:"st.contact.contact.closed", backgroundColor:"#79b821"
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e"
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821"
attributeState "garage-open", label:'Open', icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e"
attributeState "garage-closed", label:'Closed', icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821"
}
}
standardTile("contact", "device.contact", width: 2, height: 2) {
state("open", label:'Open', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
state("closed", label:'Closed', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
}
standardTile("acceleration", "device.acceleration", width: 2, height: 2) {
state("active", label:'Active', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0")
state("inactive", label:'Inactive', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0")
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
}
valueTile("temperature", "device.temperature", width: 2, height: 2) {
state("temperature", label:'${currentValue}°',

View File

@@ -203,7 +203,7 @@ private List parseContactMessage(String description) {
parts.each { part ->
part = part.trim()
if (part.startsWith('contactState:')) {
results.addAll(getContactResult(part, description))
results << getContactResult(part, description)
}
else if (part.startsWith('accelerationState:')) {
results << getAccelerationResult(part, description)
@@ -316,7 +316,7 @@ private List getContactResult(part, description) {
results
}
private Map getAccelerationResult(part, description) {
private getAccelerationResult(part, description) {
def name = "acceleration"
def value = part.endsWith("1") ? "active" : "inactive"
def linkText = getLinkText(device)
@@ -335,7 +335,7 @@ private Map getAccelerationResult(part, description) {
]
}
private Map getTempResult(part, description) {
private getTempResult(part, description) {
def name = "temperature"
def temperatureScale = getTemperatureScale()
def value = zigbee.parseSmartThingsTemperatureValue(part, "temp: ", temperatureScale)
@@ -360,7 +360,7 @@ private Map getTempResult(part, description) {
]
}
private Map getXyzResult(results, description) {
private getXyzResult(results, description) {
def name = "threeAxis"
def value = "${results.x},${results.y},${results.z}"
def linkText = getLinkText(device)
@@ -379,7 +379,7 @@ private Map getXyzResult(results, description) {
]
}
private Map getBatteryResult(part, description) {
private getBatteryResult(part, description) {
def batteryDivisor = description.split(",").find {it.split(":")[0].trim() == "batteryDivisor"} ? description.split(",").find {it.split(":")[0].trim() == "batteryDivisor"}.split(":")[1].trim() : null
def name = "battery"
def value = zigbee.parseSmartThingsBatteryValue(part, batteryDivisor)
@@ -400,7 +400,7 @@ private Map getBatteryResult(part, description) {
]
}
private Map getRssiResult(part, description, lastHop=false) {
private getRssiResult(part, description, lastHop=false) {
def name = lastHop ? "lastHopRssi" : "rssi"
def valueString = part.split(":")[1].trim()
def value = (Integer.parseInt(valueString) - 128).toString()
@@ -431,7 +431,7 @@ private Map getRssiResult(part, description, lastHop=false) {
* Note: To make the signal strength indicator more accurate, we could combine
* LQI with RSSI.
*/
private Map getLqiResult(part, description, lastHop=false) {
private getLqiResult(part, description, lastHop=false) {
def name = lastHop ? "lastHopLqi" : "lqi"
def valueString = part.split(":")[1].trim()
def percentageOf = 255

View File

@@ -56,17 +56,21 @@ metadata {
def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
log.info event
if (event.name == "power") {
def resultMap = zigbee.getKnownDescription(description)
if (resultMap) {
log.info resultMap
if (resultMap.type == "update") {
log.info "$device updates: ${resultMap.value}"
}
else if (resultMap.type == "power") {
def powerValue
if (device.getDataValue("manufacturer") != "OSRAM") { //OSRAM devices do not reliably update power
event.value = (event.value as Integer) / 10 //TODO: The divisor value needs to be set as part of configuration
sendEvent(event)
powerValue = (resultMap.value as Integer)/10 //TODO: The divisor value needs to be set as part of configuration
sendEvent(name: "power", value: powerValue)
}
}
else {
sendEvent(event)
sendEvent(name: resultMap.type, value: resultMap.value)
}
}
else {

View File

@@ -51,9 +51,15 @@ metadata {
def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
sendEvent(event)
def resultMap = zigbee.getKnownDescription(description)
if (resultMap) {
log.info resultMap
if (resultMap.type == "update") {
log.info "$device updates: ${resultMap.value}"
}
else {
sendEvent(name: resultMap.type, value: resultMap.value)
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"

View File

@@ -83,19 +83,32 @@ def uninstalled() {
}
def configure() {
/*
def cmds =
zigbee.configureReporting(CLUSTER_DOORLOCK, DOORLOCK_ATTR_LOCKSTATE,
TYPE_ENUM8, 0, 3600, null) +
zigbee.configureReporting(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING,
TYPE_U8, 600, 21600, 0x01)
zigbee.configSetup("${CLUSTER_DOORLOCK}", "${DOORLOCK_ATTR_LOCKSTATE}",
"${TYPE_ENUM8}", 0, 3600, "{01}") +
zigbee.configSetup("${CLUSTER_POWER}", "${POWER_ATTR_BATTERY_PERCENTAGE_REMAINING}",
"${TYPE_U8}", 600, 21600, "{01}")
*/
def zigbeeId = device.zigbeeId
def cmds =
[
"zdo bind 0x${device.deviceNetworkId} 0x${device.endpointId} 1 ${CLUSTER_DOORLOCK} {$zigbeeId} {}", "delay 200",
"zcl global send-me-a-report ${CLUSTER_DOORLOCK} ${DOORLOCK_ATTR_LOCKSTATE} ${TYPE_ENUM8} 0 3600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 0x${device.endpointId}", "delay 200",
"zdo bind 0x${device.deviceNetworkId} 0x${device.endpointId} 1 ${CLUSTER_POWER} {$zigbeeId} {}", "delay 200",
"zcl global send-me-a-report ${CLUSTER_POWER} ${POWER_ATTR_BATTERY_PERCENTAGE_REMAINING} ${TYPE_U8} 600 21600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 0x${device.endpointId}", "delay 200",
]
log.info "configure() --- cmds: $cmds"
return cmds + refresh() // send refresh cmds as part of config
}
def refresh() {
def cmds =
zigbee.readAttribute(CLUSTER_DOORLOCK, DOORLOCK_ATTR_LOCKSTATE) +
zigbee.readAttribute(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING)
zigbee.refreshData("${CLUSTER_DOORLOCK}", "${DOORLOCK_ATTR_LOCKSTATE}") +
zigbee.refreshData("${CLUSTER_POWER}", "${POWER_ATTR_BATTERY_PERCENTAGE_REMAINING}")
log.info "refresh() --- cmds: $cmds"
return cmds
}
@@ -108,27 +121,34 @@ def parse(String description) {
map = parseReportAttributeMessage(description)
}
log.debug "parse() --- Parse returned $map"
def result = map ? createEvent(map) : null
log.debug "parse() --- returned: $result"
return result
}
// Lock capability commands
def lock() {
def cmds = zigbee.command(CLUSTER_DOORLOCK, DOORLOCK_CMD_LOCK_DOOR)
log.info "lock() -- cmds: $cmds"
return cmds
//def cmds = zigbee.zigbeeCommand("${CLUSTER_DOORLOCK}", "${DOORLOCK_CMD_LOCK_DOOR}", "{}")
//log.info "lock() -- cmds: $cmds"
//return cmds
"st cmd 0x${device.deviceNetworkId} 0x${device.endpointId} ${CLUSTER_DOORLOCK} ${DOORLOCK_CMD_LOCK_DOOR} {}"
}
def unlock() {
def cmds = zigbee.command(CLUSTER_DOORLOCK, DOORLOCK_CMD_UNLOCK_DOOR)
log.info "unlock() -- cmds: $cmds"
return cmds
//def cmds = zigbee.zigbeeCommand("${CLUSTER_DOORLOCK}", "${DOORLOCK_CMD_UNLOCK_DOOR}", "{}")
//log.info "unlock() -- cmds: $cmds"
//return cmds
"st cmd 0x${device.deviceNetworkId} 0x${device.endpointId} ${CLUSTER_DOORLOCK} ${DOORLOCK_CMD_UNLOCK_DOOR} {}"
}
// Private methods
private Map parseReportAttributeMessage(String description) {
log.trace "parseReportAttributeMessage() --- description: $description"
Map descMap = zigbee.parseDescriptionAsMap(description)
log.debug "parseReportAttributeMessage() --- descMap: $descMap"
Map resultMap = [:]
if (descMap.clusterInt == CLUSTER_POWER && descMap.attrInt == POWER_ATTR_BATTERY_PERCENTAGE_REMAINING) {
resultMap.name = "battery"
@@ -136,24 +156,18 @@ private Map parseReportAttributeMessage(String description) {
if (device.getDataValue("manufacturer") == "Yale") { //Handling issue with Yale locks incorrect battery reporting
resultMap.value = Integer.parseInt(descMap.value, 16)
}
log.info "parseReportAttributeMessage() --- battery: ${resultMap.value}"
}
else if (descMap.clusterInt == CLUSTER_DOORLOCK && descMap.attrInt == DOORLOCK_ATTR_LOCKSTATE) {
def value = Integer.parseInt(descMap.value, 16)
def linkText = getLinkText(device)
resultMap.name = "lock"
if (value == 0) {
resultMap.value = "unknown"
resultMap.descriptionText = "${linkText} is not fully locked"
} else if (value == 1) {
resultMap.value = "locked"
resultMap.descriptionText = "${linkText} is locked"
} else if (value == 2) {
resultMap.value = "unlocked"
resultMap.descriptionText = "${linkText} is unlocked"
} else {
resultMap.value = "unknown"
resultMap.descriptionText = "${linkText} is in unknown lock state"
}
resultMap.putAll([0:["value":"unknown",
"descriptionText":"Not fully locked"],
1:["value":"locked"],
2:["value":"unlocked"]].get(value,
["value":"unknown",
"descriptionText":"Unknown lock state"]))
log.info "parseReportAttributeMessage() --- lock: ${resultMap.value}"
}
else {
log.debug "parseReportAttributeMessage() --- ignoring attribute"

View File

@@ -51,15 +51,22 @@ metadata {
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
if (event.name == "power") {
def resultMap = zigbee.getKnownDescription(description)
if (resultMap) {
log.info resultMap
if (resultMap.type == "update") {
log.info "$device updates: ${resultMap.value}"
}
else if (resultMap.type == "power") {
def powerValue
powerValue = (event.value as Integer)/10 //TODO: The divisor value needs to be set as part of configuration
sendEvent(name: "power", value: powerValue)
if (device.getDataValue("manufacturer") != "OSRAM") { //OSRAM devices do not reliably update power
powerValue = (resultMap.value as Integer)/10 //TODO: The divisor value needs to be set as part of configuration
sendEvent(name: "power", value: powerValue)
}
}
else {
sendEvent(event)
sendEvent(name: resultMap.type, value: resultMap.value)
}
}
else {

View File

@@ -53,9 +53,16 @@ metadata {
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
sendEvent(event)
def resultMap = zigbee.getKnownDescription(description)
if (resultMap) {
log.info resultMap
if (resultMap.type == "update") {
log.info "$device updates: ${resultMap.value}"
}
else {
sendEvent(name: resultMap.type, value: resultMap.value)
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"

View File

@@ -73,9 +73,16 @@ metadata {
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
sendEvent(event)
def finalResult = zigbee.getKnownDescription(description)
if (finalResult) {
log.info finalResult
if (finalResult.type == "update") {
log.info "$device updates: ${finalResult.value}"
}
else {
sendEvent(name: finalResult.type, value: finalResult.value)
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"

View File

@@ -161,7 +161,7 @@ private sendDeveloperReq() {
headers: [
HOST: host
],
body: [devicetype: "$token-0"]], "${selectedHue}"))
body: [devicetype: "$token-0", username: "$token-0"]], "${selectedHue}"))
}
private discoverHueBulbs() {
@@ -657,53 +657,39 @@ def setColorTemperature(childDevice, huesettings) {
}
def setColor(childDevice, huesettings) {
log.debug "Executing 'setColor($huesettings)'"
def value = [:]
log.debug "Executing 'setColor($huesettings)'"
def hue = null
def sat = null
def xy = null
if (huesettings.hex != null) {
value.xy = getHextoXY(huesettings.hex)
} else {
if (huesettings.hue != null)
value.hue = Math.min(Math.round(huesettings.hue * 65535 / 100), 65535)
if (huesettings.saturation != null)
value.sat = Math.min(Math.round(huesettings.saturation * 255 / 100), 255)
if (huesettings.hex) {
xy = getHextoXY(huesettings.hex)
} else if (huesettings.hue && huesettings.saturation) {
hue = Math.min(Math.round(huesettings.hue * 65535 / 100), 65535)
sat = Math.min(Math.round(huesettings.saturation * 255 / 100), 255)
}
// Default behavior is to turn light on
value.on = true
def alert = huesettings.alert ? huesettings.alert : "none"
def transition = huesettings.transition ? huesettings.transition : 4
if (huesettings.level != null) {
if (huesettings.level <= 0)
value.on = false
else if (huesettings.level == 1)
value.bri = 1
else
value.bri = Math.min(Math.round(huesettings.level * 255 / 100), 255)
}
value.alert = huesettings.alert ? huesettings.alert : "none"
value.transition = huesettings.transition ? huesettings.transition : 4
def value = [xy: xy, sat: sat, hue: hue, alert: alert, transitiontime: transition, on: true]
// Make sure to turn off light if requested
if (huesettings.switch == "off")
value.on = false
if (huesettings.level != null) {
if (huesettings.level == 1) value.bri = 1 else value.bri = Math.min(Math.round(huesettings.level * 255 / 100), 255)
value.on = value.bri > 0
}
log.debug "sending command $value"
put("lights/${getId(childDevice)}/state", value)
return "Color set to $value"
log.debug "sending command $value"
put("lights/${getId(childDevice)}/state", value)
}
def nextLevel(childDevice) {
def level = device.latestValue("level") as Integer ?: 0
if (level < 100) {
level = Math.min(25 * (Math.round(level / 25) + 1), 100) as Integer
} else {
level = 25
}
setLevel(childDevice,level)
def level = device.latestValue("level") as Integer ?: 0
if (level < 100) {
level = Math.min(25 * (Math.round(level / 25) + 1), 100) as Integer
}
else {
level = 25
}
setLevel(childDevice,level)
}
private getId(childDevice) {
@@ -802,14 +788,16 @@ private getHextoXY(String colorStr) {
// Make green more vivid
if (normalizedToOne[1] > 0.04045) {
green = (float) Math.pow((normalizedToOne[1] + 0.055) / (1.0 + 0.055), 2.4);
green = (float) Math.pow((normalizedToOne[1] + 0.055)
/ (1.0 + 0.055), 2.4);
} else {
green = (float) (normalizedToOne[1] / 12.92);
}
// Make blue more vivid
if (normalizedToOne[2] > 0.04045) {
blue = (float) Math.pow((normalizedToOne[2] + 0.055) / (1.0 + 0.055), 2.4);
blue = (float) Math.pow((normalizedToOne[2] + 0.055)
/ (1.0 + 0.055), 2.4);
} else {
blue = (float) (normalizedToOne[2] / 12.92);
}
@@ -818,8 +806,8 @@ private getHextoXY(String colorStr) {
float Y = (float) (red * 0.234327 + green * 0.743075 + blue * 0.022598);
float Z = (float) (red * 0.0000000 + green * 0.053077 + blue * 1.035763);
float x = (X != 0 ? X / (X + Y + Z) : 0);
float y = (Y != 0 ? Y / (X + Y + Z) : 0);
float x = X / (X + Y + Z);
float y = Y / (X + Y + Z);
double[] xy = new double[2];
xy[0] = x;

View File

@@ -0,0 +1,50 @@
/**
* test 앱
*
* Copyright 2016 이진희
*
* 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: "test 앱",
namespace: "test앱",
author: "이진희",
description: "\uD14C\uC2A4\uD2B8\uC785\uB2C8\uB2E4",
category: "",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
preferences {
section("Title") {
// TODO: put inputs here
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
// TODO: subscribe to attributes, devices, locations, etc.
}
// TODO: implement event handlers

View File

@@ -40,7 +40,6 @@ preferences {
page name:"pageSetup"
page name:"Setup"
page name:"Settings"
page name: "timeIntervalInput"
}
@@ -186,8 +185,7 @@ def Settings() {
}
}
def timeIntervalInput() {
dynamicPage(name: "timeIntervalInput") {
page(name: "timeIntervalInput", title: "Only during a certain time", refreshAfterSelection:true) {
section {
input "startTimeType", "enum", title: "Starting at", options: [["time": "A specific time"], ["sunrise": "Sunrise"], ["sunset": "Sunset"]], defaultValue: "time", submitOnChange: true
if (startTimeType in ["sunrise","sunset"]) {
@@ -206,10 +204,9 @@ def timeIntervalInput() {
input "ending", "time", title: "End time", required: false
}
}
}
}
def installed() {
initialize()
}