Compare commits

..

32 Commits

Author SHA1 Message Date
Vinay Rao
51fb7fc7a9 Merge pull request #717 from SmartThingsCommunity/staging
Rolling up changes to production from staging 2016-03-31 Release
2016-03-31 14:31:39 -07:00
Doug Sabers
babc0206df Merge pull request #742 from sabersd/tilesWork
INTL-309 translating tiles
2016-03-31 10:02:43 -05:00
sabersd
d419fb8606 INTL-309 translating tiles 2016-03-31 09:28:25 -05:00
Lars Finander
70aae0d76c Merge pull request #720 from larsfinander/staging_DVCSMP_1667_Authentication_update_Philips_Hue
DVCSMP-1667 Authentication needs to be updated for Philips Hue
2016-03-30 16:37:16 -07:00
Lars Finander
1cd5c68e68 DVCSMP-1667 Authentication needs to be updated for Philips Hue
-Philips updaded their API and current ST implementation will stop
working when next Hue firmware is released without this change
2016-03-30 13:58:53 -07:00
tslagle13
9e427d4108 Merge pull request #718 from tslagle13/bug-fix-for-vacation-lighting-director
Make timeIntervalInput dynamic page
2016-03-29 17:20:14 -07:00
tslagle13
a8628b7343 Make timeIntervalInput dynamic page
Forgot to make timeIntervalInput a dynamic page so it can update view on selection.
2016-03-29 17:12:28 -07:00
Vinay Rao
eb8d5ed4c9 Merge pull request #706 from SmartThingsCommunity/production
Rolling down build changes to staging from production
2016-03-25 16:47:12 -07:00
Vinay Rao
7b5d618de8 Merge pull request #705 from jeff-blaisdell/fix-production
Update public repo to new build setup.
2016-03-25 16:45:47 -07:00
Jeff Blaisdell
c024e09fb8 Update public repo to new build setup. 2016-03-25 18:33:15 -05:00
Vinay Rao
fe92f7ad19 Merge pull request #698 from SmartThingsCommunity/master
Rolling up master to staging
2016-03-24 13:25:36 -07:00
Vinay Rao
10245315ee Merge pull request #697 from SmartThingsCommunity/staging
Rolling down staging commits to master
2016-03-24 13:22:33 -07:00
Vinay Rao
0b239d4686 Merge pull request #696 from SmartThingsCommunity/revert-668-staging_remove_hue
Revert "Revert "DVCSMP-1615 & DEVC-372""
2016-03-24 13:19:48 -07:00
Vinay Rao
9374290d64 Revert "Revert "DVCSMP-1615 & DEVC-372"" 2016-03-24 13:12:23 -07:00
Vinay Rao
ffcacb9da5 Merge pull request #664 from SmartThingsCommunity/staging
Rolling up changes to production from staging 2016-03-25 Release
2016-03-24 13:03:24 -07:00
Vinay Rao
c45129170a Merge pull request #668 from larsfinander/staging_remove_hue
Revert "DVCSMP-1615 & DEVC-372"
2016-03-24 12:56:35 -07:00
Lars Finander
53406ada8e Merge pull request #690 from larsfinander/DVCSMP-1615-Improve-Hue-error-handling
DVCSMP-1615 Hue setColor throws exceptions when missing parameters
2016-03-23 18:57:32 -07:00
Lars Finander
ffd0dd1545 DVCSMP-1615 Hue setColor throws exceptions when missing parameters
-DVCSMP-1637 Color picker set the light on but status not updated on the detail page
-DVCSMP-1638 Temperature control selection set the light on but status not updated on the detail page
-Added a lot of error checking for input parameters
-Fixed some data parsing exceptions
2016-03-23 16:10:11 -07:00
Vinay Rao
5c1236a21a Merge pull request #693 from SmartThingsCommunity/staging
[DVCSMP-1657] Syncing down changes from staging to master
2016-03-23 15:24:13 -07:00
Vinay Rao
0911651f71 Merge pull request #692 from workingmonk/bug/hotfix_multi
[DVCSMP-1657] Bug/hotfix multi
2016-03-23 15:19:18 -07:00
Vinay Rao
9cc92b1987 fixing issue with list of list of maps with multi parsing
adding return type to methods
2016-03-23 15:13:33 -07:00
Vinay Rao
1e27dc1824 Merge pull request #674 from workingmonk/feature/zigbee_library_refactor
[DPROT-20] ZigBee Refactor
2016-03-23 11:44:42 -07:00
Tom Manley
4bf3679942 Merge pull request #376 from tpmanley/feature/zigbee_refactor
[DPROT-20] Feature/zigbee refactor
2016-03-23 09:51:37 -05:00
Tom Manley
c714720578 Update zigbee-lock, zigbee-dimmer and zigbee-dimmer-power to use ZB lib API
https://smartthings.atlassian.net/browse/DPROT-20
2016-03-23 09:51:02 -05:00
Vinay Rao
281fc939ac refactoring code to get it inline with the new zigbee apis 2016-03-23 00:27:23 -07:00
Lars Finander
633bef2ac5 Revert "DVCSMP-1615 & DEVC-372"
This reverts commit 6fbef3b297.
(temporary for staging, MArch 25 deploy)
2016-03-22 14:29:32 -07:00
Vinay Rao
a8357e7644 Merge pull request #652 from SmartThingsCommunity/master
Rolling up changes from master to staging
2016-03-18 13:38:31 -07:00
Vinay Rao
024a6cb698 Merge pull request #632 from SmartThingsCommunity/staging
Rolling up changes to production from staging 2016-03-17 Release
2016-03-18 10:43:22 -07:00
Vinay Rao
62a965d90b Merge pull request #599 from SmartThingsCommunity/staging
Rolling up changes to production from staging 2016-03-10 Release
2016-03-10 16:26:26 -08:00
Vinay Rao
515b268374 Merge pull request #549 from SmartThingsCommunity/staging
Rolling up changes to production from staging 2016-02-25 Release
2016-02-26 10:51:42 -08:00
Vinay Rao
a103d437c2 Merge pull request #523 from SmartThingsCommunity/staging
Deploy to production 2/18
2016-02-18 09:28:02 -08:00
Vinay Rao
bdd88deb99 Merge pull request #504 from SmartThingsCommunity/staging
Merging changes from staging to production
2016-02-11 22:40:38 -08:00
19 changed files with 207 additions and 514 deletions

View File

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

View File

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

View File

@@ -1,143 +0,0 @@
/**
* 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.
*
* Aeon Home Energy Meter
*
* Author: SmartThings
*
* Date: 2013-05-30
*/
metadata {
definition (name: "Aeon Home Energy Meter With PCode", namespace: "smartthings", author: "SmartThings") {
capability "Energy Meter"
capability "Power Meter"
capability "Configuration"
capability "Sensor"
attribute "ManufacturerCode", "string"
attribute "ProductCode", "string"
attribute "ProduceTypeCode", "string"
attribute "WirelessConfig", "string"
command "reset"
fingerprint deviceId: "0x2101", inClusters: " 0x70,0x31,0x72,0x86,0x32,0x80,0x85,0x60"
}
// simulator metadata
simulator {
for (int i = 0; i <= 10000; i += 1000) {
status "power ${i} W": new physicalgraph.zwave.Zwave().meterV1.meterReport(
scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage()
}
for (int i = 0; i <= 100; i += 10) {
status "energy ${i} kWh": new physicalgraph.zwave.Zwave().meterV1.meterReport(
scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage()
}
}
// tile definitions
tiles {
valueTile("power", "device.power", decoration: "flat") {
state "default", label:'${currentValue} W'
}
valueTile("energy", "device.energy", decoration: "flat") {
state "default", label:'${currentValue} kWh'
}
standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat") {
state "default", label:'reset kWh', action:"reset"
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
standardTile("configure", "device.power", inactiveLabel: false, decoration: "flat") {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
main (["power","energy"])
details(["power","energy", "reset","refresh", "configure"])
}
}
def parse(String description) {
def result = null
def cmd = zwave.parse(description, [0x31: 1, 0x32: 1, 0x60: 3])
if (cmd) {
result = createEvent(zwaveEvent(cmd))
}
log.debug "Parse returned ${result?.descriptionText}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.meterv1.MeterReport cmd) {
if (cmd.scale == 0) {
[name: "energy", value: cmd.scaledMeterValue, unit: "kWh"]
} else if (cmd.scale == 1) {
[name: "energy", value: cmd.scaledMeterValue, unit: "kVAh"]
}
else {
[name: "power", value: Math.round(cmd.scaledMeterValue), unit: "W"]
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in
[:]
}
def refresh() {
delayBetween([
zwave.meterV2.meterGet(scale: 0).format(),
zwave.meterV2.meterGet(scale: 2).format()
])
}
def reset() {
// No V1 available
return [
zwave.meterV2.meterReset().format(),
zwave.meterV2.meterGet(scale: 0).format()
]
}
def configure() {
def cmd = delayBetween([
zwave.manufacturerSpecificV2.manufacturerSpecificGet().format(),
zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 4).format(), // combined power in watts
zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 900).format(), // every 5 min
zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 8).format(), // combined energy in kWh
zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 3600).format(), // every 5 min
zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 0).format(), // no third report
zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 900).format() // every 5 min
])
log.debug cmd
cmd
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def result = []
def manufacturerCode = String.format("%04X", cmd.manufacturerId)
def productCode = String.format("%04X", cmd.productId)
def produceTypeCode = String.format("%04X", cmd.productTypeId)
def wirelessConfig = "ZWA"
sendEvent(name: "ManufacturerCode", value: manufacturerCode)
sendEvent(name: "ProductCode", value: productCode)
sendEvent(name: "ProduceTypeCode", value: produceTypeCode)
sendEvent(name: "WirelessConfig", value: wirelessConfig)
result << createEvent(descriptionText: "$device.displayName", isStateChange: false)
return result
}

View File

@@ -1,200 +0,0 @@
/**
* 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.
*
*/
metadata {
definition (name: "Aeon Smart Switch GEN5", namespace: "smartthings", author: "SmartThings") {
capability "Power Meter"
capability "Energy Meter"
capability "Actuator"
capability "Switch"
capability "Configuration"
capability "Polling"
capability "Refresh"
capability "Sensor"
attribute "ManufacturerCode", "string"
attribute "ProductCode", "string"
attribute "ProduceTypeCode", "string"
attribute "WirelessConfig", "string"
command "reset"
fingerprint deviceId: "0x1001", inClusters: "0x25,0x32,0x27,0x2C,0x2B,0x70,0x85,0x56,0x72,0x86,0x5E,0x59,0x7A,0x73,0x98,0xEF,0x5A,0x82", outClusters: "0x82"
}
// simulator metadata
simulator {
status "on": "command: 2003, payload: FF"
status "off": "command: 2003, payload: 00"
for (int i = 0; i <= 100; i += 10) {
status "energy ${i} kWh": new physicalgraph.zwave.Zwave().meterV2.meterReport(
scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage()
}
// reply messages
reply "2001FF,delay 100,2502": "command: 2503, payload: FF"
reply "200100,delay 100,2502": "command: 2503, payload: 00"
}
// tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
valueTile("power", "device.power", decoration: "flat") {
state "default", label:'${currentValue} W'
}
valueTile("energy", "device.energy", decoration: "flat") {
state "default", label:'${currentValue} kWh'
}
standardTile("configure", "device.power", inactiveLabel: false, decoration: "flat") {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
main "switch"
details(["switch","power","energy","refresh","configure"])
}
}
def parse(String description) {
def result = null
def cmd = zwave.parse(description, [0x20: 1, 0x32: 2])
if (cmd) {
log.debug cmd
result = createEvent(zwaveEvent(cmd))
}
return result
}
def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) {
log.debug "MeterReport ${cmd}"
if (cmd.scale == 0) {
[name: "energy", value: cmd.scaledMeterValue, unit: "kWh"]
} else if (cmd.scale == 1) {
[name: "energy", value: cmd.scaledMeterValue, unit: "kVAh"]
}
else {
[name: "power", value: Math.round(cmd.scaledMeterValue), unit: "W"]
}
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
[
name: "switch", value: cmd.value ? "on" : "off", type: "physical"
]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
[
name: "switch", value: cmd.value ? "on" : "off", type: "digital"
]
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in
return createEvent(descriptionText: "$device.displayName: $cmd", displayed: false)
[:]
}
def on() {
delayBetween([
secure(zwave.basicV1.basicSet(value: 0xFF)),
secure(zwave.switchBinaryV1.switchBinaryGet())
])
}
def off() {
delayBetween([
secure(zwave.basicV1.basicSet(value: 0x00)),
secure(zwave.switchBinaryV1.switchBinaryGet())
])
}
def poll() {
delayBetween([
secure(zwave.switchBinaryV1.switchBinaryGet()),
secure(zwave.meterV2.meterGet())
])
}
def refresh() {
secure(zwave.switchBinaryV1.switchBinaryGet())
}
def reset() {
return [
secure(zwave.meterV2.meterReset()),
secure(zwave.meterV2.meterGet())
]
}
def configure() {
delayBetween([
zwave.manufacturerSpecificV2.manufacturerSpecificGet().format(),
secure(zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 8)), // energy in kWh
secure(zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 300)), // every 1 min
secure(zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 4)),
secure(zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 900)),
secure(zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 0))
])
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def result = []
def manufacturerCode = String.format("%04X", cmd.manufacturerId)
def productCode = String.format("%04X", cmd.productId)
def produceTypeCode = String.format("%04X", cmd.productTypeId)
def wirelessConfig = "ZWP"
sendEvent(name: "ManufacturerCode", value: manufacturerCode)
sendEvent(name: "ProductCode", value: productCode)
sendEvent(name: "ProduceTypeCode", value: produceTypeCode)
sendEvent(name: "WirelessConfig", value: wirelessConfig)
result << createEvent(descriptionText: "$device.displayName", isStateChange: false)
return result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x85: 2, 0x70: 1])
log.debug "encapsulated: $encapsulatedCommand"
if (encapsulatedCommand) {
state.sec = 1
zwaveEvent(encapsulatedCommand)
}
}
private secure(physicalgraph.zwave.Command cmd) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
}
private secureSequence(commands, delay=200) {
delayBetween(commands.collect{ secure(it) }, delay)
}

View File

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

View File

@@ -28,4 +28,8 @@
'''{{ device.displayName }} is On'''.ko={{ device.displayName }}켜졌습니다. '''{{ device.displayName }} is On'''.ko={{ device.displayName }}켜졌습니다.
'''{{ device.displayName }} is Off'''.ko={{ device.displayName }}꺼졌습니다. '''{{ device.displayName }} is Off'''.ko={{ device.displayName }}꺼졌습니다.
'''{{ device.displayName }} power is {{ value }} Watts'''.ko={{ device.displayName }} 전원은 {{ value }}와트입니다 '''{{ 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) { tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff" attributeState "on", label: 'On', 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 "off", label: 'Off', 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 "turningOn", label: 'Turning On', 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 "turningOff", label: 'Turning Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
} }
tileAttribute ("power", key: "SECONDARY_CONTROL") { tileAttribute ("power", key: "SECONDARY_CONTROL") {
attributeState "power", label:'${currentValue} W' attributeState "power", label:'${currentValue} W'

View File

@@ -43,3 +43,7 @@
'''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}남아있는 배터리는 {{ value }}%입니다. '''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}남아있는 배터리는 {{ value }}%입니다.
'''Updating device to garage sensor'''.ko=기기-차고 센서 업데이트 중 '''Updating device to garage sensor'''.ko=기기-차고 센서 업데이트 중
'''Updating device to open/close 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) { tiles(scale: 2) {
multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){ multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){
tileAttribute ("device.status", key: "PRIMARY_CONTROL") { tileAttribute ("device.status", key: "PRIMARY_CONTROL") {
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e" attributeState "open", label:'Open', icon:"st.contact.contact.open", backgroundColor:"#ffa81e"
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821" attributeState "closed", label:'Closed', icon:"st.contact.contact.closed", backgroundColor:"#79b821"
attributeState "garage-open", label:'Open', icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e" 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" attributeState "garage-closed", label:'Closed', icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821"
} }
} }
standardTile("contact", "device.contact", width: 2, height: 2) { standardTile("contact", "device.contact", width: 2, height: 2) {
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e") state("open", label:'Open', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821") state("closed", label:'Closed', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
} }
standardTile("acceleration", "device.acceleration", width: 2, height: 2) { standardTile("acceleration", "device.acceleration", width: 2, height: 2) {
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0") state("active", label:'Active', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0")
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff") state("inactive", label:'Inactive', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
} }
valueTile("temperature", "device.temperature", width: 2, height: 2) { valueTile("temperature", "device.temperature", width: 2, height: 2) {
state("temperature", label:'${currentValue}°', state("temperature", label:'${currentValue}°',

View File

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

View File

@@ -56,21 +56,17 @@ metadata {
def parse(String description) { def parse(String description) {
log.debug "description is $description" log.debug "description is $description"
def resultMap = zigbee.getKnownDescription(description) def event = zigbee.getEvent(description)
if (resultMap) { if (event) {
log.info resultMap log.info event
if (resultMap.type == "update") { if (event.name == "power") {
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 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 event.value = (event.value as Integer) / 10 //TODO: The divisor value needs to be set as part of configuration
sendEvent(name: "power", value: powerValue) sendEvent(event)
} }
} }
else { else {
sendEvent(name: resultMap.type, value: resultMap.value) sendEvent(event)
} }
} }
else { else {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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