Compare commits

..

7 Commits

Author SHA1 Message Date
Vinay Rao
8e37b1fce7 Merge pull request #1460 from bbodenmiller/patch-1
Github -> GitHub (Text change, no ticket)
2016-11-13 05:34:47 -08:00
Ben Bodenmiller
439dd634bd Github -> GitHub 2016-11-12 00:19:55 -08:00
Juan Pablo Risso
1db5f75ec5 DVCSMP-2211 - Update Button Number and Holdable capability (#1458) 2016-11-11 16:10:44 -05:00
Juan Pablo Risso
7978f45996 DVCSMP-2221 - Replace display with displayed (#1457) 2016-11-11 14:09:04 -05:00
Vinay Rao
0ab657d5f2 Merge pull request #1456 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-11-11 02:47:42 -08:00
tslagle13
0ae836b023 Merge pull request #1442 from MichaelStruck/MSA-1576-14
MSA-1576: Color Coordinator
2016-11-09 11:18:22 -08:00
Michael Struck
0b4d555d33 MSA-1576: Fixes various bugs and adds a random color feature. 2016-11-09 09:33:31 -08:00
16 changed files with 319 additions and 185 deletions

View File

@@ -1,10 +1,10 @@
# SmartThings Public Github Repo # SmartThings Public GitHub Repo
An official list of SmartApps and Device Types from SmartThings. An official list of SmartApps and Device Types from SmartThings.
Here are some links to help you get started coding right away: Here are some links to help you get started coding right away:
* [Github-specific Documentation](http://docs.smartthings.com/en/latest/tools-and-ide/github-integration.html) * [GitHub-specific Documentation](http://docs.smartthings.com/en/latest/tools-and-ide/github-integration.html)
* [Full Documentation](http://docs.smartthings.com) * [Full Documentation](http://docs.smartthings.com)
* [IDE & Simulator](http://ide.smartthings.com) * [IDE & Simulator](http://ide.smartthings.com)
* [Community Forums](http://community.smartthings.com) * [Community Forums](http://community.smartthings.com)

View File

@@ -15,6 +15,7 @@ metadata {
definition (name: "Aeon Key Fob", namespace: "smartthings", author: "SmartThings") { definition (name: "Aeon Key Fob", namespace: "smartthings", author: "SmartThings") {
capability "Actuator" capability "Actuator"
capability "Button" capability "Button"
capability "Holdable Button"
capability "Configuration" capability "Configuration"
capability "Sensor" capability "Sensor"
capability "Battery" capability "Battery"
@@ -118,3 +119,7 @@ def configure() {
log.debug("Sending configuration: $cmd") log.debug("Sending configuration: $cmd")
return cmd return cmd
} }
def updated() {
sendEvent(name: "numberOfButtons", value: 4)
}

View File

@@ -15,6 +15,7 @@ metadata {
definition (name: "Aeon Minimote", namespace: "smartthings", author: "SmartThings") { definition (name: "Aeon Minimote", namespace: "smartthings", author: "SmartThings") {
capability "Actuator" capability "Actuator"
capability "Button" capability "Button"
capability "Holdable Button"
capability "Configuration" capability "Configuration"
capability "Sensor" capability "Sensor"
@@ -107,3 +108,7 @@ def configure() {
log.debug("Sending configuration: $cmds") log.debug("Sending configuration: $cmds")
return cmds return cmds
} }
def updated() {
sendEvent(name: "numberOfButtons", value: 4)
}

View File

@@ -16,7 +16,7 @@ metadata {
capability "Switch" capability "Switch"
capability "Switch Level" capability "Switch Level"
capability "Button" capability "Button"
capability "Actuator" capability "Actuator"
//fingerprint deviceId: "0x1200", inClusters: "0x77 0x86 0x75 0x73 0x85 0x72 0xEF", outClusters: "0x26" //fingerprint deviceId: "0x1200", inClusters: "0x77 0x86 0x75 0x73 0x85 0x72 0xEF", outClusters: "0x26"
} }
@@ -182,3 +182,7 @@ def updateState(String name, String value) {
state[name] = value state[name] = value
device.updateDataValue(name, value) device.updateDataValue(name, value)
} }
def updated() {
sendEvent(name: "numberOfButtons", value: 3)
}

View File

@@ -236,17 +236,17 @@ def refresh() {
} }
void indicatorWhenOn() { void indicatorWhenOn() {
sendEvent(name: "indicatorStatus", value: "when on", display: false) sendEvent(name: "indicatorStatus", value: "when on", displayed: false)
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format())) sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()))
} }
void indicatorWhenOff() { void indicatorWhenOff() {
sendEvent(name: "indicatorStatus", value: "when off", display: false) sendEvent(name: "indicatorStatus", value: "when off", displayed: false)
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format())) sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()))
} }
void indicatorNever() { void indicatorNever() {
sendEvent(name: "indicatorStatus", value: "never", display: false) sendEvent(name: "indicatorStatus", value: "never", displayed: false)
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format())) sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format()))
} }

View File

@@ -125,7 +125,7 @@ metadata {
void installed() { void installed() {
// The device refreshes every 5 minutes by default so if we miss 2 refreshes we can consider it offline // The device refreshes every 5 minutes by default so if we miss 2 refreshes we can consider it offline
// Using 12 minutes because in testing, device health team found that there could be "jitter" // Using 12 minutes because in testing, device health team found that there could be "jitter"
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "cloud"], displayed: false) sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "cloud", hubHardwareId: device.hub.hardwareID], displayed: false)
} }
// Device Watch will ping the device to proactively determine if the device has gone offline // Device Watch will ping the device to proactively determine if the device has gone offline

View File

@@ -546,7 +546,7 @@ def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport
def value = "when off" def value = "when off"
if (cmd.configurationValue[0] == 1) {value = "when on"} if (cmd.configurationValue[0] == 1) {value = "when on"}
if (cmd.configurationValue[0] == 2) {value = "never"} if (cmd.configurationValue[0] == 2) {value = "never"}
[name: "indicatorStatus", value: value, display: false] [name: "indicatorStatus", value: value, displayed: false]
} }
*/ */
def createEvent(physicalgraph.zwave.Command cmd, Map map) { def createEvent(physicalgraph.zwave.Command cmd, Map map) {
@@ -829,7 +829,7 @@ def toggleTiles(color) {
state.colorTiles.each({ state.colorTiles.each({
if ( it == color ) { if ( it == color ) {
log.debug "Turning ${it} on" log.debug "Turning ${it} on"
cmds << sendEvent(name: it, value: "on${it}", display: True, descriptionText: "${device.displayName} ${color} is 'ON'", isStateChange: true) cmds << sendEvent(name: it, value: "on${it}", displayed: True, descriptionText: "${device.displayName} ${color} is 'ON'", isStateChange: true)
} else { } else {
//log.debug "Turning ${it} off" //log.debug "Turning ${it} off"
cmds << sendEvent(name: it, value: "off${it}", displayed: false) cmds << sendEvent(name: it, value: "off${it}", displayed: false)

View File

@@ -43,8 +43,8 @@ def parse(String description) {
} }
def push() { def push() {
sendEvent(name: "switch", value: "on", isStateChange: true, display: false) sendEvent(name: "switch", value: "on", isStateChange: true, displayed: false)
sendEvent(name: "switch", value: "off", isStateChange: true, display: false) sendEvent(name: "switch", value: "off", isStateChange: true, displayed: false)
sendEvent(name: "momentary", value: "pushed", isStateChange: true) sendEvent(name: "momentary", value: "pushed", isStateChange: true)
} }

View File

@@ -71,7 +71,7 @@ def parse(String description) {
def event = [:] def event = [:]
def finalResult = isKnownDescription(description) def finalResult = isKnownDescription(description)
if (finalResult) { if (finalResult != "false") {
log.info finalResult log.info finalResult
if (finalResult.type == "update") { if (finalResult.type == "update") {
log.info "$device updates: ${finalResult.value}" log.info "$device updates: ${finalResult.value}"
@@ -212,16 +212,13 @@ def isKnownDescription(description) {
else if (descMap.cluster == "0B04" || descMap.clusterId == "0B04"){ else if (descMap.cluster == "0B04" || descMap.clusterId == "0B04"){
isDescriptionPower(descMap) isDescriptionPower(descMap)
} }
else {
return [:]
}
} }
else if(description?.startsWith("on/off:")) { else if(description?.startsWith("on/off:")) {
def switchValue = description?.endsWith("1") ? "on" : "off" def switchValue = description?.endsWith("1") ? "on" : "off"
return [type: "switch", value : switchValue] return [type: "switch", value : switchValue]
} }
else { else {
return [:] return "false"
} }
} }
@@ -255,7 +252,7 @@ def isDescriptionOnOff(descMap) {
return [type: "switch", value : switchValue] return [type: "switch", value : switchValue]
} }
else { else {
return [:] return "false"
} }
} }
@@ -282,9 +279,10 @@ def isDescriptionLevel(descMap) {
if (dimmerValue != -1){ if (dimmerValue != -1){
return [type: "level", value : dimmerValue] return [type: "level", value : dimmerValue]
} }
else { else {
return [:] return "false"
} }
} }
@@ -306,7 +304,7 @@ def isDescriptionPower(descMap) {
return [type: "power", value : powerValue] return [type: "power", value : powerValue]
} }
else { else {
return [:] return "false"
} }
} }

View File

@@ -15,6 +15,7 @@ metadata {
definition (name: "Simulated Minimote", namespace: "smartthings/testing", author: "SmartThings") { definition (name: "Simulated Minimote", namespace: "smartthings/testing", author: "SmartThings") {
capability "Actuator" capability "Actuator"
capability "Button" capability "Button"
capability "Holdable Button"
capability "Configuration" capability "Configuration"
capability "Sensor" capability "Sensor"
@@ -125,3 +126,6 @@ private hold(button) {
sendEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was held", isStateChange: true) sendEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was held", isStateChange: true)
} }
def updated() {
sendEvent(name: "numberOfButtons", value: 4)
}

View File

@@ -19,6 +19,7 @@ metadata {
capability "Actuator" capability "Actuator"
capability "Battery" capability "Battery"
capability "Button" capability "Button"
capability "Holdable Button"
capability "Configuration" capability "Configuration"
capability "Refresh" capability "Refresh"
capability "Sensor" capability "Sensor"

View File

@@ -33,7 +33,7 @@ metadata {
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04", outClusters: "0019" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04", outClusters: "0019"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY BR Tunable White", deviceJoinName: "OSRAM LIGHTIFY LED Flood BR30 Tunable White" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY BR Tunable White", deviceJoinName: "OSRAM LIGHTIFY LED Flood BR30 Tunable White"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY RT Tunable White", deviceJoinName: "OSRAM LIGHTIFY LED Recessed Kit RT 5/6 Tunable White" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY RT Tunable White", deviceJoinName: "OSRAM LIGHTIFY RT5/6 Tunable White"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic A60 TW", deviceJoinName: "OSRAM LIGHTIFY LED Tunable White 60W" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic A60 TW", deviceJoinName: "OSRAM LIGHTIFY LED Tunable White 60W"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY A19 Tunable White", deviceJoinName: "OSRAM LIGHTIFY LED Tunable White 60W" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY A19 Tunable White", deviceJoinName: "OSRAM LIGHTIFY LED Tunable White 60W"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic B40 TW - LIGHTIFY", deviceJoinName: "OSRAM LIGHTIFY Classic B40 Tunable White" fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic B40 TW - LIGHTIFY", deviceJoinName: "OSRAM LIGHTIFY Classic B40 Tunable White"
@@ -83,24 +83,105 @@ def parse(String description) {
} }
} }
else { else {
def cluster = zigbee.parse(description) Map bindingTable = parseBindingTableResponse(description)
if (bindingTable) {
List<String> cmds = []
bindingTable.table_entries.inject(cmds) { acc, entry ->
// The binding entry is not for our hub and should be deleted
if (entry["dstAddr"] != zigbeeEui) {
acc.addAll(removeBinding(entry.clusterId, entry.srcAddr, entry.srcEndpoint, entry.dstAddr, entry.dstEndpoint))
}
acc
}
// There are more entries that we haven't examined yet
if (bindingTable.numTableEntries > bindingTable.startIndex + bindingTable.numEntriesReturned) {
def startPos
if (cmds) {
log.warn "Removing binding entries for other devices: $cmds"
// Since we are removing some entries, we should start in the same spot as we just read since values
// will fill in the newly vacated spots
startPos = bindingTable.startIndex
} else {
// Since we aren't removing anything we move forward to the next set of table entries
startPos = bindingTable.startIndex + bindingTable.numEntriesReturned
}
cmds.addAll(requestBindingTable(startPos))
}
sendHubCommand(cmds.collect { it ->
new physicalgraph.device.HubAction(it)
}, 2000)
} else {
def cluster = zigbee.parse(description)
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) { if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
if (cluster.data[0] == 0x00) { if (cluster.data[0] == 0x00) {
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) 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 { else {
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}" log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug "${cluster}"
} }
} }
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug "${cluster}"
}
} }
} }
def parseBindingTableResponse(description) {
Map descMap = zigbee.parseDescriptionAsMap(description)
if (descMap["clusterInt"] == 0x8033) {
def header_field_lengths = ["transactionSeqNo": 1, "status": 1, "numTableEntries": 1, "startIndex": 1, "numEntriesReturned": 1]
def field_values = [:]
def data = descMap["data"]
header_field_lengths.each { k, v ->
field_values[k] = Integer.parseInt(data.take(v).join(""), 16);
data = data.drop(v);
}
List<Map> table = []
if (field_values.numEntriesReturned) {
def table_entry_lengths = ["srcAddr": 8, "srcEndpoint": 1, "clusterId": 2, "dstAddrMode": 1]
for (def i : 0..(field_values.numEntriesReturned - 1)) {
def entryMap = [:]
table_entry_lengths.each { k, v ->
def val = data.take(v).reverse().join("")
entryMap[k] = val.length() < 8 ? Integer.parseInt(val, 16) : val
data = data.drop(v)
}
switch (entryMap.dstAddrMode) {
case 0x01:
entryMap["dstAddr"] = data.take(2).reverse().join("")
data = data.drop(2)
break
case 0x03:
entryMap["dstAddr"] = data.take(8).reverse().join("")
data = data.drop(8)
entryMap["dstEndpoint"] = Integer.parseInt(data.take(1).join(""), 16)
data = data.drop(1)
break
}
table << entryMap
}
}
field_values["table_entries"] = table
return field_values
}
return [:]
}
def requestBindingTable(startPos=0) {
return ["zdo mgmt-bind 0x${zigbee.deviceNetworkId} $startPos"]
}
def removeBinding(cluster, srcAddr, srcEndpoint, destAddr, destEndpoint) {
return ["zdo unbind unicast 0x${zigbee.deviceNetworkId} {${srcAddr}} $srcEndpoint $cluster {${destAddr}} $destEndpoint"]
}
def off() { def off() {
zigbee.off() zigbee.off()
} }
@@ -130,8 +211,7 @@ def configure() {
// enrolls with default periodic reporting until newer 5 min interval is confirmed // enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 2 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]) sendEvent(name: "checkInterval", value: 2 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity refresh() + requestBindingTable(0) + ["delay 2000"]
refresh()
} }
def setColorTemperature(value) { def setColorTemperature(value) {

View File

@@ -81,7 +81,7 @@ def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport
def value = "when off" def value = "when off"
if (cmd.configurationValue[0] == 1) {value = "when on"} if (cmd.configurationValue[0] == 1) {value = "when on"}
if (cmd.configurationValue[0] == 2) {value = "never"} if (cmd.configurationValue[0] == 2) {value = "never"}
[name: "indicatorStatus", value: value, display: false] [name: "indicatorStatus", value: value, displayed: false]
} }
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) { def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {

View File

@@ -114,7 +114,7 @@ def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport
def value = "when off" def value = "when off"
if (cmd.configurationValue[0] == 1) {value = "when on"} if (cmd.configurationValue[0] == 1) {value = "when on"}
if (cmd.configurationValue[0] == 2) {value = "never"} if (cmd.configurationValue[0] == 2) {value = "never"}
[name: "indicatorStatus", value: value, display: false] [name: "indicatorStatus", value: value, displayed: false]
} }
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) { def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
@@ -174,17 +174,17 @@ def refresh() {
} }
void indicatorWhenOn() { void indicatorWhenOn() {
sendEvent(name: "indicatorStatus", value: "when on", display: false) sendEvent(name: "indicatorStatus", value: "when on", displayed: false)
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format())) sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()))
} }
void indicatorWhenOff() { void indicatorWhenOff() {
sendEvent(name: "indicatorStatus", value: "when off", display: false) sendEvent(name: "indicatorStatus", value: "when off", displayed: false)
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format())) sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()))
} }
void indicatorNever() { void indicatorNever() {
sendEvent(name: "indicatorStatus", value: "never", display: false) sendEvent(name: "indicatorStatus", value: "never", displayed: false)
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format())) sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format()))
} }

View File

@@ -1,9 +1,10 @@
/** /**
* Color Coordinator * Color Coordinator
* Version 1.0.0 - 7/4/15 * Version 1.1.0 - 11/9/16
* By Michael Struck * By Michael Struck
* *
* 1.0.0 - Initial release * 1.0.0 - Initial release
* 1.1.0 - Fixed issue where master can be part of slaves. This causes a loop that impacts SmartThings.
* *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
@@ -31,27 +32,35 @@ preferences {
} }
def mainPage() { def mainPage() {
dynamicPage(name: "mainPage", title: "", install: true, uninstall: true) { dynamicPage(name: "mainPage", title: "", install: true, uninstall: false) {
section("Master Light") { def masterInList = slaves.id.find{it==master.id}
if (masterInList) {
section ("**WARNING**"){
paragraph "You have included the Master Light in the Slave Group. This will cause a loop in execution. Please remove this device from the Slave Group.", image: "https://raw.githubusercontent.com/MichaelStruck/SmartThingsPublic/master/img/caution.png"
}
}
section("Master Light") {
input "master", "capability.colorControl", title: "Colored Light" input "master", "capability.colorControl", title: "Colored Light"
} }
section("Lights that follow the master settings") { section("Lights that follow the master settings") {
input "slaves", "capability.colorControl", title: "Colored Lights", multiple: true, required: false input "slaves", "capability.colorControl", title: "Colored Lights", multiple: true, required: false, submitOnChange: true
} }
section([mobileOnly:true], "Options") { section([mobileOnly:true], "Options") {
label(title: "Assign a name", required: false) input "randomYes", "bool",title: "When Master Turned On, Randomize Color", defaultValue: false
href "pageAbout", title: "About ${textAppName()}", description: "Tap to get application version, license and instructions" href "pageAbout", title: "About ${textAppName()}", description: "Tap to get application version, license and instructions"
} }
} }
} }
page(name: "pageAbout", title: "About ${textAppName()}") { page(name: "pageAbout", title: "About ${textAppName()}", uninstall: true) {
section { section {
paragraph "${textVersion()}\n${textCopyright()}\n\n${textLicense()}\n" paragraph "${textVersion()}\n${textCopyright()}\n\n${textLicense()}\n"
} }
section("Instructions") { section("Instructions") {
paragraph textHelp() paragraph textHelp()
} }
section("Tap button below to remove application"){
}
} }
def installed() { def installed() {
@@ -72,27 +81,55 @@ def init() {
} }
//----------------------------------- //-----------------------------------
def onOffHandler(evt){ def onOffHandler(evt){
if (master.currentValue("switch") == "on"){ if (!slaves.id.find{it==master.id}){
slaves?.on() if (master.currentValue("switch") == "on"){
} if (randomYes) getRandomColorMaster()
else { else slaves?.on()
slaves?.off() }
} else {
slaves?.off()
}
}
} }
def colorHandler(evt) { def colorHandler(evt) {
def dimLevel = master.currentValue("level") if (!slaves.id.find{it==master.id} && master.currentValue("switch") == "on"){
def hueLevel = master.currentValue("hue") log.debug "Changing Slave units H,S,L"
def saturationLevel = master.currentValue("saturation") def dimLevel = master.currentValue("level")
def hueLevel = master.currentValue("hue")
def saturationLevel = master.currentValue("saturation")
def newValue = [hue: hueLevel, saturation: saturationLevel, level: dimLevel as Integer]
slaves?.setColor(newValue)
try {
log.debug "Changing Slave color temp"
def tempLevel = master.currentValue("colorTemperature")
slaves?.setColorTemperature(tempLevel)
}
catch (e){
log.debug "Color temp for master --"
}
}
}
def getRandomColorMaster(){
def hueLevel = Math.floor(Math.random() *1000)
def saturationLevel = Math.floor(Math.random() * 100)
def dimLevel = master.currentValue("level")
def newValue = [hue: hueLevel, saturation: saturationLevel, level: dimLevel as Integer] def newValue = [hue: hueLevel, saturation: saturationLevel, level: dimLevel as Integer]
log.debug hueLevel
log.debug saturationLevel
master.setColor(newValue)
slaves?.setColor(newValue) slaves?.setColor(newValue)
} }
def tempHandler(evt){ def tempHandler(evt){
if (evt.value != "--") { if (!slaves.id.find{it==master.id} && master.currentValue("switch") == "on"){
def tempLevel = master.currentValue("colorTemperature") if (evt.value != "--") {
slaves?.setColorTemperature(tempLevel) log.debug "Changing Slave color temp based on Master change"
} def tempLevel = master.currentValue("colorTemperature")
slaves?.setColorTemperature(tempLevel)
}
}
} }
//Version/Copyright/Information/Help //Version/Copyright/Information/Help
@@ -102,11 +139,11 @@ private def textAppName() {
} }
private def textVersion() { private def textVersion() {
def text = "Version 1.0.0 (07/04/2015)" def text = "Version 1.1.0 (11/09/2016)"
} }
private def textCopyright() { private def textCopyright() {
def text = "Copyright © 2015 Michael Struck" def text = "Copyright © 2016 Michael Struck"
} }
private def textLicense() { private def textLicense() {
@@ -128,5 +165,5 @@ private def textHelp() {
def text = def text =
"This application will allow you to control the settings of multiple colored lights with one control. " + "This application will allow you to control the settings of multiple colored lights with one control. " +
"Simply choose a master control light, and then choose the lights that will follow the settings of the master, "+ "Simply choose a master control light, and then choose the lights that will follow the settings of the master, "+
"including on/off conditions, hue, saturation, level and color temperature." "including on/off conditions, hue, saturation, level and color temperature. Also includes a random color feature."
} }

View File

@@ -516,7 +516,7 @@ def pollResponse(response, data) {
def hub = getChildDevice("harmony-${it.key}") def hub = getChildDevice("harmony-${it.key}")
if (hub) { if (hub) {
if (it.value.response.data.currentAvActivity == "-1") { if (it.value.response.data.currentAvActivity == "-1") {
hub.sendEvent(name: "currentActivity", value: "--", descriptionText: "There isn't any activity running", display: false) hub.sendEvent(name: "currentActivity", value: "--", descriptionText: "There isn't any activity running", displayed: false)
} else { } else {
def currentActivity def currentActivity
def activityDTH = getChildDevice("harmony-${it.key}-${it.value.response.data.currentAvActivity}") def activityDTH = getChildDevice("harmony-${it.key}-${it.value.response.data.currentAvActivity}")
@@ -524,7 +524,7 @@ def pollResponse(response, data) {
currentActivity = activityDTH.device.displayName currentActivity = activityDTH.device.displayName
else else
currentActivity = getActivityName(it.value.response.data.currentAvActivity,it.key) currentActivity = getActivityName(it.value.response.data.currentAvActivity,it.key)
hub.sendEvent(name: "currentActivity", value: currentActivity, descriptionText: "Current activity is ${currentActivity}", display: false) hub.sendEvent(name: "currentActivity", value: currentActivity, descriptionText: "Current activity is ${currentActivity}", displayed: false)
} }
} }
} else { } else {
@@ -576,7 +576,7 @@ def getActivityList() {
} }
activities += [id: "off", name: "Activity OFF", type: "0"] activities += [id: "off", name: "Activity OFF", type: "0"]
} }
hub.sendEvent(name: "activities", value: new groovy.json.JsonBuilder(activities).toString(), descriptionText: "Activities are ${activities.collect { it.name }?.join(', ')}", display: false) hub.sendEvent(name: "activities", value: new groovy.json.JsonBuilder(activities).toString(), descriptionText: "Activities are ${activities.collect { it.name }?.join(', ')}", displayed: false)
} }
} }
} }