mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-20 21:03:46 +00:00
Compare commits
1 Commits
DEVC-484
...
MSA-1570-1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f29521237c |
@@ -87,7 +87,7 @@ metadata {
|
|||||||
def parse(String description) {
|
def parse(String description) {
|
||||||
def resultMap = zigbee.getEvent(description)
|
def resultMap = zigbee.getEvent(description)
|
||||||
if (resultMap) {
|
if (resultMap) {
|
||||||
if (resultMap.name != "level" || resultMap.value != 0) { // Ignore level reports of 0 sent when bulb turns off
|
if ((resultMap.name == "level" && state.trigger == "setLevel") || resultMap.name != "level") { //doing this to account for weird level reporting bug with GE Link Bulbs
|
||||||
sendEvent(resultMap)
|
sendEvent(resultMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,10 +188,12 @@ def updated() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def on() {
|
def on() {
|
||||||
|
state.trigger = "on/off"
|
||||||
zigbee.on()
|
zigbee.on()
|
||||||
}
|
}
|
||||||
|
|
||||||
def off() {
|
def off() {
|
||||||
|
state.trigger = "on/off"
|
||||||
zigbee.off()
|
zigbee.off()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +206,7 @@ def refresh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def setLevel(value) {
|
def setLevel(value) {
|
||||||
|
state.trigger = "setLevel"
|
||||||
def cmd
|
def cmd
|
||||||
def delayForRefresh = 500
|
def delayForRefresh = 500
|
||||||
if (dimRate && (state?.rate != null)) {
|
if (dimRate && (state?.rate != null)) {
|
||||||
|
|||||||
@@ -69,17 +69,15 @@ metadata {
|
|||||||
def parse(String description) {
|
def parse(String description) {
|
||||||
log.debug "description is $description"
|
log.debug "description is $description"
|
||||||
|
|
||||||
def event = [:]
|
|
||||||
def finalResult = isKnownDescription(description)
|
def finalResult = isKnownDescription(description)
|
||||||
if (finalResult != "false") {
|
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}"
|
||||||
event = null
|
|
||||||
}
|
}
|
||||||
else if (finalResult.type == "power") {
|
else if (finalResult.type == "power") {
|
||||||
def powerValue = (finalResult.value as Integer)/10
|
def powerValue = (finalResult.value as Integer)/10
|
||||||
event = createEvent(name: "power", value: powerValue)
|
sendEvent(name: "power", value: powerValue)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Dividing by 10 as the Divisor is 10000 and unit is kW for the device. AttrId: 0302 and 0300. Simplifying to 10
|
Dividing by 10 as the Divisor is 10000 and unit is kW for the device. AttrId: 0302 and 0300. Simplifying to 10
|
||||||
@@ -89,14 +87,13 @@ def parse(String description) {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
event = createEvent(name: finalResult.type, value: finalResult.value)
|
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"
|
||||||
log.debug parseDescriptionAsMap(description)
|
log.debug parseDescriptionAsMap(description)
|
||||||
}
|
}
|
||||||
return event
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commands to device
|
// Commands to device
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ def parse(String description) {
|
|||||||
log.debug "description is $description"
|
log.debug "description is $description"
|
||||||
|
|
||||||
def finalResult = zigbee.getKnownDescription(description)
|
def finalResult = zigbee.getKnownDescription(description)
|
||||||
def event = [:]
|
|
||||||
|
|
||||||
//TODO: Remove this after getKnownDescription can parse it automatically
|
//TODO: Remove this after getKnownDescription can parse it automatically
|
||||||
if (!finalResult && description!="updated")
|
if (!finalResult && description!="updated")
|
||||||
@@ -89,11 +88,10 @@ def parse(String description) {
|
|||||||
log.info "final result = $finalResult"
|
log.info "final result = $finalResult"
|
||||||
if (finalResult.type == "update") {
|
if (finalResult.type == "update") {
|
||||||
log.info "$device updates: ${finalResult.value}"
|
log.info "$device updates: ${finalResult.value}"
|
||||||
event = null
|
|
||||||
}
|
}
|
||||||
else if (finalResult.type == "power") {
|
else if (finalResult.type == "power") {
|
||||||
def powerValue = (finalResult.value as Integer)/10
|
def powerValue = (finalResult.value as Integer)/10
|
||||||
event = createEvent(name: "power", value: powerValue, descriptionText: '{{ device.displayName }} power is {{ value }} Watts', translatable: true)
|
sendEvent(name: "power", value: powerValue, descriptionText: '{{ device.displayName }} power is {{ value }} Watts', translatable: true )
|
||||||
/*
|
/*
|
||||||
Dividing by 10 as the Divisor is 10000 and unit is kW for the device. AttrId: 0302 and 0300. Simplifying to 10
|
Dividing by 10 as the Divisor is 10000 and unit is kW for the device. AttrId: 0302 and 0300. Simplifying to 10
|
||||||
power level is an integer. The exact power level with correct units needs to be handled in the device type
|
power level is an integer. The exact power level with correct units needs to be handled in the device type
|
||||||
@@ -102,7 +100,7 @@ def parse(String description) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
def descriptionText = finalResult.value == "on" ? '{{ device.displayName }} is On' : '{{ device.displayName }} is Off'
|
def descriptionText = finalResult.value == "on" ? '{{ device.displayName }} is On' : '{{ device.displayName }} is Off'
|
||||||
event = createEvent(name: finalResult.type, value: finalResult.value, descriptionText: descriptionText, translatable: true)
|
sendEvent(name: finalResult.type, value: finalResult.value, descriptionText: descriptionText, translatable: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -111,11 +109,10 @@ def parse(String 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
|
||||||
event = createEvent(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 {
|
else {
|
||||||
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
|
||||||
event = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -123,7 +120,6 @@ def parse(String description) {
|
|||||||
log.debug "${cluster}"
|
log.debug "${cluster}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return event
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def off() {
|
def off() {
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ metadata {
|
|||||||
|
|
||||||
def parse(String description) {
|
def parse(String description) {
|
||||||
log.debug "parse($description)"
|
log.debug "parse($description)"
|
||||||
def results = [:]
|
def results = null
|
||||||
|
|
||||||
if (!isSupportedDescription(description) || zigbee.isZoneType19(description)) {
|
if (!isSupportedDescription(description) || zigbee.isZoneType19(description)) {
|
||||||
// Ignore this in favor of orientation-based state
|
// Ignore this in favor of orientation-based state
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ def parse(String description) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.debug "Parse returned $map"
|
log.debug "Parse returned $map"
|
||||||
def result = map ? createEvent(map) : [:]
|
def result = map ? createEvent(map) : null
|
||||||
|
|
||||||
if (description?.startsWith('enroll request')) {
|
if (description?.startsWith('enroll request')) {
|
||||||
List cmds = enrollResponse()
|
List cmds = enrollResponse()
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ def parse(String description) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.debug "Parse returned $map"
|
log.debug "Parse returned $map"
|
||||||
def result = map ? createEvent(map) : [:]
|
def result = map ? createEvent(map) : null
|
||||||
|
|
||||||
if (description?.startsWith('enroll request')) {
|
if (description?.startsWith('enroll request')) {
|
||||||
List cmds = enrollResponse()
|
List cmds = enrollResponse()
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ def parse(String description) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.debug "Parse returned $map"
|
log.debug "Parse returned $map"
|
||||||
def result = map ? createEvent(map) : [:]
|
def result = map ? createEvent(map) : null
|
||||||
|
|
||||||
if (description?.startsWith('enroll request')) {
|
if (description?.startsWith('enroll request')) {
|
||||||
List cmds = enrollResponse()
|
List cmds = enrollResponse()
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def parse(String description) {
|
def parse(String description) {
|
||||||
def results = [:]
|
def results
|
||||||
if (isZoneType19(description) || !isSupportedDescription(description)) {
|
if (isZoneType19(description) || !isSupportedDescription(description)) {
|
||||||
results = parseBasicMessage(description)
|
results = parseBasicMessage(description)
|
||||||
}
|
}
|
||||||
@@ -57,25 +57,21 @@ def parse(String description) {
|
|||||||
|
|
||||||
private Map parseBasicMessage(description) {
|
private Map parseBasicMessage(description) {
|
||||||
def name = parseName(description)
|
def name = parseName(description)
|
||||||
if (name != null) {
|
def value = parseValue(description)
|
||||||
def value = parseValue(description)
|
def linkText = getLinkText(device)
|
||||||
def linkText = getLinkText(device)
|
def descriptionText = parseDescriptionText(linkText, value, description)
|
||||||
def descriptionText = parseDescriptionText(linkText, value, description)
|
def handlerName = value
|
||||||
def handlerName = value
|
def isStateChange = isStateChange(device, name, value)
|
||||||
def isStateChange = isStateChange(device, name, value)
|
|
||||||
|
|
||||||
def results = [
|
def results = [
|
||||||
name : name,
|
name: name,
|
||||||
value : value,
|
value: value,
|
||||||
linkText : linkText,
|
linkText: linkText,
|
||||||
descriptionText: descriptionText,
|
descriptionText: descriptionText,
|
||||||
handlerName : handlerName,
|
handlerName: handlerName,
|
||||||
isStateChange : isStateChange,
|
isStateChange: isStateChange,
|
||||||
displayed : displayed(description, isStateChange)
|
displayed: displayed(description, isStateChange)
|
||||||
]
|
]
|
||||||
} else {
|
|
||||||
results = [:]
|
|
||||||
}
|
|
||||||
log.debug "Parse returned $results.descriptionText"
|
log.debug "Parse returned $results.descriptionText"
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ def parse(String description) {
|
|||||||
map = parseIasMessage(description)
|
map = parseIasMessage(description)
|
||||||
}
|
}
|
||||||
|
|
||||||
def result = map ? createEvent(map) : [:]
|
def result = map ? createEvent(map) : null
|
||||||
|
|
||||||
if (description?.startsWith('enroll request')) {
|
if (description?.startsWith('enroll request')) {
|
||||||
List cmds = enrollResponse()
|
List cmds = enrollResponse()
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ def parse(String description) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.debug "Parse returned $map"
|
log.debug "Parse returned $map"
|
||||||
def result = map ? createEvent(map) : [:]
|
def result = map ? createEvent(map) : null
|
||||||
|
|
||||||
if (description?.startsWith('enroll request')) {
|
if (description?.startsWith('enroll request')) {
|
||||||
List cmds = enrollResponse()
|
List cmds = enrollResponse()
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ def parse(String description) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.debug "Parse returned $map"
|
log.debug "Parse returned $map"
|
||||||
return map ? createEvent(map) : [:]
|
return map ? createEvent(map) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map parseCatchAllMessage(String description) {
|
private Map parseCatchAllMessage(String description) {
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
# Zigbee Dimmer
|
# OSRAM Lightify LED On/Off/Dim
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Works with:
|
Works with:
|
||||||
|
|
||||||
* [OSRAM Lightify LED On/Off/Dim](https://shop.smartthings.com/#!/products/osram-led-smart-bulb-on-off-dim)
|
* [OSRAM Lightify LED On/Off/Dim](https://shop.smartthings.com/#!/products/osram-led-smart-bulb-on-off-dim)
|
||||||
* [WeMo LED Bulb](https://support.smartthings.com/hc/en-us/articles/204259040-Belkin-WeMo-LED-Bulb-F7C033-)
|
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
@@ -24,16 +23,14 @@ Works with:
|
|||||||
|
|
||||||
## Device Health
|
## Device Health
|
||||||
|
|
||||||
A Zigbee dimmer with maxReportTime of 5 mins.
|
A Category C1 Zigbee dimmer with maxReportTime of 5 mins.
|
||||||
Check-in interval is double the value of maxReportTime.
|
Check-in interval is double the value of maxReportTime.
|
||||||
This gives the device twice the amount of time to respond before it is marked as offline.
|
This gives the device twice the amount of time to respond before it is marked as offline.
|
||||||
Enrolls with default periodic reporting until newer 5 min interval is confirmed
|
Check-in interval = 12 mins
|
||||||
It then enrolls the device with updated checkInterval i.e. 12 mins
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
|
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
|
||||||
Pairing needs to be tried again by placing the device closer to the hub.
|
Pairing needs to be tried again by placing the device closer to the hub.
|
||||||
Other troubleshooting tips are listed as follows:
|
Other troubleshooting tips are listed as follows:
|
||||||
* [OSRAM Lightify LED On/Off/Dim Troubleshooting:](https://support.smartthings.com/hc/en-us/articles/207191763-OSRAM-LIGHTIFY-LED-Smart-Connected-Light-A19-On-Off-Dim)
|
* [Troubleshooting:](https://support.smartthings.com/hc/en-us/articles/207191763-OSRAM-LIGHTIFY-LED-Smart-Connected-Light-A19-On-Off-Dim)
|
||||||
* [WeMo LED Bulb Troubleshooting:](https://support.smartthings.com/hc/en-us/articles/204259040-Belkin-WeMo-LED-Bulb-F7C033-)
|
|
||||||
|
|||||||
@@ -84,20 +84,18 @@ def refresh() {
|
|||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
log.debug "in configure()"
|
log.debug "in configure()"
|
||||||
return configureHealthCheck()
|
configureHealthCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
def configureHealthCheck() {
|
def configureHealthCheck() {
|
||||||
Integer hcIntervalMinutes = 12
|
Integer hcIntervalMinutes = 12
|
||||||
|
refresh()
|
||||||
sendEvent(name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
sendEvent(name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||||
return refresh()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def updated() {
|
def updated() {
|
||||||
log.debug "in updated()"
|
log.debug "in updated()"
|
||||||
// updated() doesn't have it's return value processed as hub commands, so we have to send them explicitly
|
configureHealthCheck()
|
||||||
def cmds = configureHealthCheck()
|
|
||||||
cmds.each{ sendHubCommand(new physicalgraph.device.HubAction(it)) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def ping() {
|
def ping() {
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
# ZigBee White Color Temperature Bulb
|
# OSRAM Lightify Tunable 60 White
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Works with:
|
Works with:
|
||||||
|
|
||||||
* [OSRAM Lightify Tunable 60 White](http://www.osram.com/osram_com/tools-and-services/tools/lightify---smart-connected-light/lightify-for-home---what-is-light-to-you/lightify-products/lightify-classic-a60-tunable-white/index.jsp)
|
* [OSRAM Lightify Tunable 60 White](http://www.osram.com/osram_com/tools-and-services/tools/lightify---smart-connected-light/lightify-for-home---what-is-light-to-you/lightify-products/lightify-classic-a60-tunable-white/index.jsp)
|
||||||
* [OSRAM LIGHTIFY RT5/6 Tunable White](https://www.smartthings.com/works-with-smartthings/light-bulbs/osram-lightify-rt56-tunable-white)
|
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
@@ -25,16 +24,14 @@ Works with:
|
|||||||
|
|
||||||
## Device Health
|
## Device Health
|
||||||
|
|
||||||
Zigbee Bulb with maxReportTime of 5 mins.
|
A Category C1 OSRAM Lightify Tunable 60 White with maxReportTime of 5 mins.
|
||||||
Check-in interval is double the value of maxReportTime.
|
Check-in interval is double the value of maxReportTime.
|
||||||
This gives the device twice the amount of time to respond before it is marked as offline.
|
This gives the device twice the amount of time to respond before it is marked as offline.
|
||||||
Enrolls with default periodic reporting until newer 5 min interval is confirmed
|
Check-in interval = 12 mins
|
||||||
It then enrolls the device with updated checkInterval i.e. 12 mins
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
|
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
|
||||||
Pairing needs to be tried again by placing the device closer to the hub.
|
Pairing needs to be tried again by placing the device closer to the hub.
|
||||||
Other troubleshooting tips are listed as follows:
|
Other troubleshooting tips are listed as follows:
|
||||||
* [OSRAM Lightify Tunable 60 White Troubleshooting](https://support.smartthings.com/hc/en-us/articles/204576454-OSRAM-LIGHTIFY-Tunable-White-60-Bulb)
|
* [Troubleshooting:](https://support.smartthings.com/hc/en-us/articles/204576454-OSRAM-LIGHTIFY-Tunable-White-60-Bulb)
|
||||||
* [OSRAM LIGHTIFY RT5/6 Tunable White Troubleshooting](https://support.smartthings.com/hc/en-us/articles/214191863-How-to-connect-OSRAM-LIGHTIFY-Bulbs)
|
|
||||||
|
|||||||
@@ -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 RT5/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 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: "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"
|
||||||
|
|||||||
@@ -4,8 +4,7 @@
|
|||||||
|
|
||||||
Works with:
|
Works with:
|
||||||
|
|
||||||
* [Leviton Plug-in Lamp Dimmer Module (DZPD3-1LW)](https://www.smartthings.com/works-with-smartthings/outlets/leviton-plug-in-lamp-dimmer-module)
|
* [Leviton Plug-in Lamp Dimmer Module (DZPD3-1LW)](http://www.leviton.com/OA_HTML/ProductDetail.jsp?partnumber=DZPD3-1LW)
|
||||||
* [Leviton Universal Dimmer (DZMX1-LZ)](https://www.smartthings.com/works-with-smartthings/switches-and-dimmers/leviton-universal-dimmer)
|
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
@@ -25,7 +24,7 @@ Works with:
|
|||||||
|
|
||||||
## Device Health
|
## Device Health
|
||||||
|
|
||||||
Leviton Plug-in Lamp Dimmer Module (DZPA1-1LW) (Z-wave) and Leviton Universal Dimmer (DZMX1-LZ) (Z-Wave) are polled by the hub.
|
A Category C5 Leviton Plug-in Lamp Dimmer Module (DZPA1-1LW) (Z-Wave) polled by the hub.
|
||||||
As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed.
|
As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed.
|
||||||
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins.
|
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins.
|
||||||
Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for
|
Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for
|
||||||
@@ -37,5 +36,4 @@ it is not polled for 5 minutes by the hub. This can delay up the process of bein
|
|||||||
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
|
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
|
||||||
Pairing needs to be tried again by placing the device closer to the hub.
|
Pairing needs to be tried again by placing the device closer to the hub.
|
||||||
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
|
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
|
||||||
* [Leviton Plug-in Lamp Dimmer Module (DZPD3-1LW) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)
|
* [Leviton Plug-in Lamp Dimmer Module (DZPD3-1LW) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)
|
||||||
* [Leviton Universal Dimmer (DZMX1-LZ) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)
|
|
||||||
@@ -23,7 +23,6 @@ metadata {
|
|||||||
|
|
||||||
fingerprint inClusters: "0x26", deviceJoinName: "Z-Wave Dimmer"
|
fingerprint inClusters: "0x26", deviceJoinName: "Z-Wave Dimmer"
|
||||||
fingerprint mfr:"001D", prod:"1902", deviceJoinName: "Z-Wave Dimmer"
|
fingerprint mfr:"001D", prod:"1902", deviceJoinName: "Z-Wave Dimmer"
|
||||||
fingerprint mfr:"001D", prod:"1B03", model:"0334", deviceJoinName: "Leviton Universal Dimmer"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
simulator {
|
simulator {
|
||||||
|
|||||||
@@ -4,10 +4,8 @@
|
|||||||
|
|
||||||
Works with:
|
Works with:
|
||||||
|
|
||||||
* [Leviton Appliance Module (DZPA1-1LW)](https://www.smartthings.com/works-with-smartthings/outlets/leviton-appliance-module)
|
* [Leviton Appliance Module (DZPA1-1LW)](https://support.smartthings.com/hc/en-us/articles/205881176-Leviton-Appliance-Module-DZPA1-1LW-)
|
||||||
* [GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave)](https://www.smartthings.com/works-with-smartthings/outlets/ge-plug-in-outdoor-smart-switch)
|
* [GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave)](https://support.smartthings.com/hc/en-us/articles/200903080-GE-Plug-In-Outdoor-Smart-Switch-GE-12720-Z-Wave-)
|
||||||
* [Leviton Outlet (DZR15-1LZ)](https://www.smartthings.com/works-with-smartthings/outlets/leviton-outlet)
|
|
||||||
* [Leviton Switch (DZS15-1LZ)](https://www.smartthings.com/works-with-smartthings/switches-and-dimmers/leviton-switch)
|
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
@@ -25,7 +23,7 @@ Works with:
|
|||||||
|
|
||||||
## Device Health
|
## Device Health
|
||||||
|
|
||||||
Leviton Appliance Module (DZPA1-1LW), GE Plug-In Outdoor Smart Switch (GE 12720), Leviton Outlet (DZR15-1LZ) and Leviton Switch (DZS15-1LZ) (Z-Wave) are polled by the hub.
|
A Category C5 Leviton Appliance Module (DZPA1-1LW) and GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave) polled by the hub.
|
||||||
As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed.
|
As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed.
|
||||||
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins.
|
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins.
|
||||||
Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for
|
Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for
|
||||||
@@ -37,7 +35,5 @@ it is not polled for 5 minutes by the hub. This can delay up the process of bein
|
|||||||
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
|
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
|
||||||
Pairing needs to be tried again by placing the device closer to the hub.
|
Pairing needs to be tried again by placing the device closer to the hub.
|
||||||
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
|
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
|
||||||
* [Leviton Appliance Module (DZPA1-1LW) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)
|
* [Leviton Appliance Module (DZPA1-1LW) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/205881176-Leviton-Appliance-Module-DZPA1-1LW-)
|
||||||
* [GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200903080-GE-Plug-In-Outdoor-Smart-Switch-GE-12720-Z-Wave-)
|
* [GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200903080-GE-Plug-In-Outdoor-Smart-Switch-GE-12720-Z-Wave-)
|
||||||
* [Leviton Outlet (DZR15-1LZ) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)
|
|
||||||
* [Leviton Switch (DZS15-1LZ) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206171053-How-to-connect-Leviton-Z-Wave-devices)
|
|
||||||
@@ -21,13 +21,7 @@ metadata {
|
|||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
|
|
||||||
fingerprint inClusters: "0x25", deviceJoinName: "Z-Wave Switch"
|
fingerprint inClusters: "0x25", deviceJoinName: "Z-Wave Switch"
|
||||||
fingerprint deviceId: "0x1001", inClusters: "0x5E,0x20,0x25,0x27,0x72,0x86,0x70,0x85", deviceJoinName: "Z-Wave Switch" // to prevent typing as relay
|
|
||||||
fingerprint deviceId: "0x1003", inClusters: "0x5E,0x25,0x2B,0x2C,0x27,0x75,0x73,0x70,0x86,0x72", deviceJoinName: "Z-Wave Switch"
|
|
||||||
fingerprint mfr:"001D", prod:"1A02", model:"0334", deviceJoinName: "Leviton Appliance Module"
|
fingerprint mfr:"001D", prod:"1A02", model:"0334", deviceJoinName: "Leviton Appliance Module"
|
||||||
fingerprint mfr:"001D", prod:"3601", model:"0001", deviceJoinName: "Leviton Appliance Module"
|
|
||||||
fingerprint mfr:"001D", prod:"1D04", model:"0334", deviceJoinName: "Leviton Outlet"
|
|
||||||
fingerprint mfr:"001D", prod:"1C02", model:"0334", deviceJoinName: "Leviton Switch"
|
|
||||||
fingerprint mfr:"001D", prod:"3401", model:"0001", deviceJoinName: "Leviton Switch"
|
|
||||||
fingerprint mfr:"0063", prod:"4F50", model:"3031", deviceJoinName: "GE Plug-in Outdoor Switch"
|
fingerprint mfr:"0063", prod:"4F50", model:"3031", deviceJoinName: "GE Plug-in Outdoor Switch"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
238
smartapps/js/switch-timer.src/switch-timer.groovy
Normal file
238
smartapps/js/switch-timer.src/switch-timer.groovy
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
/**
|
||||||
|
* Switch Timer
|
||||||
|
*
|
||||||
|
* Copyright 2016 Joe Saporito
|
||||||
|
*
|
||||||
|
* 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: "Switch Timer",
|
||||||
|
namespace: "js",
|
||||||
|
author: "Joe Saporito",
|
||||||
|
description: "Turns on switches that are not already on for a determined amount of time after an event. ",
|
||||||
|
category: "Convenience",
|
||||||
|
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 {
|
||||||
|
|
||||||
|
page(name: "settings")
|
||||||
|
page(name: "certainTime")
|
||||||
|
page(name: "renameLabel")
|
||||||
|
}
|
||||||
|
|
||||||
|
def settings() {
|
||||||
|
dynamicPage(name: "settings", title: "Turn switches off after some minutes, unless already on", uninstall: true, install: true) {
|
||||||
|
section("Choose one or more, when..."){
|
||||||
|
input "people", "capability.presenceSensor", title: "Arrival Of", required: false, multiple: true
|
||||||
|
input "doors", "capability.contactSensor", title: "Doors", required: false, multiple: true
|
||||||
|
input "motion", "capability.motionSensor", title: "Motion Here", required: false, multiple: true
|
||||||
|
}
|
||||||
|
section("Turn on switches"){
|
||||||
|
input "switches", "capability.switch", multiple: true, required: true
|
||||||
|
}
|
||||||
|
section("Turn off after") {
|
||||||
|
input "waitTime", "decimal", title: "Minutes", required: true
|
||||||
|
}
|
||||||
|
section(title: "Additional Options") {
|
||||||
|
def timeLabel = timeIntervalLabel()
|
||||||
|
href "certainTime", title: "Only during a certain time", description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : null
|
||||||
|
def appLabel = getDefaultLabel()
|
||||||
|
href "renameLabel", title: "Rename '" + appLabel + "'", description: ""
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def certainTime() {
|
||||||
|
dynamicPage(name:"certainTime",title: "Only during a certain time", uninstall: false) {
|
||||||
|
section() {
|
||||||
|
input "startEnum", "enum", title: "Starting at", options: ["A specific time", "Sunrise", "Sunset"], defaultValue: "A specific time", submitOnChange: true
|
||||||
|
if(startEnum in [null, "A specific time"]) input "startTime", "time", title: "Start time", required: false
|
||||||
|
else {
|
||||||
|
if(startEnum == "Sunrise") input "startSunriseOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false
|
||||||
|
else if(startEnum == "Sunset") input "startSunsetOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
section() {
|
||||||
|
input "endEnum", "enum", title: "Ending at", options: ["A specific time", "Sunrise", "Sunset"], defaultValue: "A specific time", submitOnChange: true
|
||||||
|
if(endEnum in [null, "A specific time"]) input "endTime", "time", title: "End time", required: false
|
||||||
|
else {
|
||||||
|
if(endEnum == "Sunrise") input "endSunriseOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false
|
||||||
|
else if(endEnum == "Sunset") input "endSunsetOffset", "number", range: "*..*", title: "Offset in minutes (+/-)", required: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def renameLabel() {
|
||||||
|
dynamicPage(name:"renameLabel",title: "Rename", uninstall: false) {
|
||||||
|
section() {
|
||||||
|
input "appLabelText", "text", title: "Rename to", defaultValue: (appLabelText ? appLabelText : getDefaultLabel()), required: false
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def installed() {
|
||||||
|
log.debug "Installed with settings: ${settings}"
|
||||||
|
|
||||||
|
initialize()
|
||||||
|
updateLabel()
|
||||||
|
}
|
||||||
|
|
||||||
|
def updated() {
|
||||||
|
log.debug "Updated with settings: ${settings}"
|
||||||
|
unsubscribe()
|
||||||
|
initialize()
|
||||||
|
updateLabel()
|
||||||
|
}
|
||||||
|
|
||||||
|
def initialize() {
|
||||||
|
subscribeToEvents()
|
||||||
|
}
|
||||||
|
|
||||||
|
def subscribeToEvents() {
|
||||||
|
subscribe(doors, "contact.open", activateHandler)
|
||||||
|
subscribe(people, "presence.present", activateHandler)
|
||||||
|
subscribe(motion, "motion.active", activateHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement event handlers
|
||||||
|
def activateHandler(evt) {
|
||||||
|
if (checkTime()) {
|
||||||
|
log.trace("$evt.name triggered")
|
||||||
|
turnOn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def turnOn() {
|
||||||
|
if(state.offSwitches) {
|
||||||
|
runIn(waitTime * 60, turnOff)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
def offSwitches = getOffSwitches()
|
||||||
|
for (s in offSwitches) {
|
||||||
|
s.on()
|
||||||
|
}
|
||||||
|
if (offSwitches.size() > 0) {
|
||||||
|
state.offSwitches = offSwitches.displayName
|
||||||
|
runIn(waitTime * 60, turnOff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def turnOff() {
|
||||||
|
if (state.offSwitches) {
|
||||||
|
def offSwitches = switches.findAll {
|
||||||
|
it.displayName in state.offSwitches
|
||||||
|
}
|
||||||
|
for (s in offSwitches) {
|
||||||
|
s.off()
|
||||||
|
}
|
||||||
|
state.offSwitches = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def updateLabel() {
|
||||||
|
if (appLabelText) {
|
||||||
|
if (appLabelText != app.label) {
|
||||||
|
log.trace("Renamed to $appLabelText")
|
||||||
|
app.updateLabel(appLabelText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
def label = getDefaultLabel()
|
||||||
|
log.trace("Renamed to $label")
|
||||||
|
app.updateLabel(label)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getDefaultLabel() {
|
||||||
|
def label = "Switch Timer"
|
||||||
|
|
||||||
|
if (switches) {
|
||||||
|
label = "Timer for " + switches[0].displayName
|
||||||
|
}
|
||||||
|
|
||||||
|
return label
|
||||||
|
}
|
||||||
|
|
||||||
|
private getOffSwitches() {
|
||||||
|
def offSwitches = switches.findAll {
|
||||||
|
it.currentSwitch == "off" ||
|
||||||
|
it.currentSwitch == null
|
||||||
|
}
|
||||||
|
return offSwitches
|
||||||
|
}
|
||||||
|
private checkTime() {
|
||||||
|
def result = true
|
||||||
|
|
||||||
|
if ((startTime && endTime) ||
|
||||||
|
(startTime && endEnum in ["Sunrise", "Sunset"]) ||
|
||||||
|
(startEnum in ["Sunrise", "Sunset"] && endTime) ||
|
||||||
|
(startEnum in ["Sunrise", "Sunset"] && endEnum in ["Sunrise", "Sunset"])) {
|
||||||
|
def currentTime = now()
|
||||||
|
def start = null
|
||||||
|
def stop = null
|
||||||
|
def sun = getSunriseAndSunset(zipCode: zipCode, sunriseOffset: startSunriseOffset, sunsetOffset: startSunsetOffset)
|
||||||
|
|
||||||
|
if (startEnum == "Sunrise")
|
||||||
|
start = sun.sunrise.time
|
||||||
|
else if (startEnum == "Sunset")
|
||||||
|
start = sun.sunset.time
|
||||||
|
else if (startTime)
|
||||||
|
start = timeToday(startTime,location.timeZone).time
|
||||||
|
|
||||||
|
sun = getSunriseAndSunset(zipCode: zipCode, sunriseOffset: endSunriseOffset, sunsetOffset: endSunsetOffset)
|
||||||
|
if (endEnum == "Sunrise")
|
||||||
|
stop = sun.sunrise.time
|
||||||
|
else if (endEnum == "Sunset")
|
||||||
|
stop = sun.sunset.time
|
||||||
|
else if (endTime)
|
||||||
|
stop = timeToday(endTime,location.timeZone).time
|
||||||
|
|
||||||
|
result = start < stop ? currentTime >= start && currentTime <= stop : currentTime <= stop || currentTime >= start
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private hideOptionsSection() {
|
||||||
|
(startTime || endTime || startEnum || endEnum) ? false : true
|
||||||
|
}
|
||||||
|
|
||||||
|
private offset(value) {
|
||||||
|
def result = value ? ((value > 0 ? "+" : "") + value + " min") : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
private hhmm(time, fmt = "h:mm a") {
|
||||||
|
def t = timeToday(time, location.timeZone)
|
||||||
|
def f = new java.text.SimpleDateFormat(fmt)
|
||||||
|
f.setTimeZone(location.timeZone ?: timeZone(time))
|
||||||
|
f.format(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
private timeIntervalLabel() {
|
||||||
|
def result = ""
|
||||||
|
if (startEnum == "Sunrise" && endEnum == "Sunrise") result = "Sunrise" + offset(startSunriseOffset) + " to " + "Sunrise" + offset(endSunriseOffset)
|
||||||
|
else if (startEnum == "Sunrise" && endEnum == "Sunset") result = "Sunrise" + offset(startSunriseOffset) + " to " + "Sunset" + offset(endSunsetOffset)
|
||||||
|
else if (startEnum == "Sunset" && endEnum == "Sunrise") result = "Sunset" + offset(startSunsetOffset) + " to " + "Sunrise" + offset(endSunriseOffset)
|
||||||
|
else if (startEnum == "Sunset" && endEnum == "Sunset") result = "Sunset" + offset(startSunsetOffset) + " to " + "Sunset" + offset(endSunsetOffset)
|
||||||
|
else if (startEnum == "Sunrise" && endTime) result = "Sunrise" + offset(startSunriseOffset) + " to " + hhmm(endTime, "h:mm a z")
|
||||||
|
else if (startEnum == "Sunset" && endTime) result = "Sunset" + offset(startSunsetOffset) + " to " + hhmm(endTime, "h:mm a z")
|
||||||
|
else if (startTime && endEnum == "Sunrise") result = hhmm(startTime) + " to " + "Sunrise" + offset(endSunriseOffset)
|
||||||
|
else if (startTime && endEnum == "Sunset") result = hhmm(startTime) + " to " + "Sunset" + offset(endSunsetOffset)
|
||||||
|
else if (startTime && endTime) result = hhmm(startTime) + " to " + hhmm(endTime, "h:mm a z")
|
||||||
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* Color Coordinator
|
* Color Coordinator
|
||||||
* Version 1.1.0 - 11/9/16
|
* Version 1.0.0 - 7/4/15
|
||||||
* 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
|
||||||
@@ -32,35 +31,27 @@ preferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def mainPage() {
|
def mainPage() {
|
||||||
dynamicPage(name: "mainPage", title: "", install: true, uninstall: false) {
|
dynamicPage(name: "mainPage", title: "", install: true, uninstall: true) {
|
||||||
def masterInList = slaves.id.find{it==master.id}
|
section("Master Light") {
|
||||||
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, submitOnChange: true
|
input "slaves", "capability.colorControl", title: "Colored Lights", multiple: true, required: false
|
||||||
}
|
}
|
||||||
section([mobileOnly:true], "Options") {
|
section([mobileOnly:true], "Options") {
|
||||||
input "randomYes", "bool",title: "When Master Turned On, Randomize Color", defaultValue: false
|
label(title: "Assign a name", required: 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()}", uninstall: true) {
|
page(name: "pageAbout", title: "About ${textAppName()}") {
|
||||||
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() {
|
||||||
@@ -81,55 +72,27 @@ def init() {
|
|||||||
}
|
}
|
||||||
//-----------------------------------
|
//-----------------------------------
|
||||||
def onOffHandler(evt){
|
def onOffHandler(evt){
|
||||||
if (!slaves.id.find{it==master.id}){
|
if (master.currentValue("switch") == "on"){
|
||||||
if (master.currentValue("switch") == "on"){
|
slaves?.on()
|
||||||
if (randomYes) getRandomColorMaster()
|
}
|
||||||
else slaves?.on()
|
else {
|
||||||
}
|
slaves?.off()
|
||||||
else {
|
}
|
||||||
slaves?.off()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def colorHandler(evt) {
|
def colorHandler(evt) {
|
||||||
if (!slaves.id.find{it==master.id} && master.currentValue("switch") == "on"){
|
def dimLevel = master.currentValue("level")
|
||||||
log.debug "Changing Slave units H,S,L"
|
def hueLevel = master.currentValue("hue")
|
||||||
def dimLevel = master.currentValue("level")
|
def saturationLevel = master.currentValue("saturation")
|
||||||
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
|
slaves?.setColor(newValue)
|
||||||
log.debug saturationLevel
|
|
||||||
master.setColor(newValue)
|
|
||||||
slaves?.setColor(newValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def tempHandler(evt){
|
def tempHandler(evt){
|
||||||
if (!slaves.id.find{it==master.id} && master.currentValue("switch") == "on"){
|
if (evt.value != "--") {
|
||||||
if (evt.value != "--") {
|
def tempLevel = master.currentValue("colorTemperature")
|
||||||
log.debug "Changing Slave color temp based on Master change"
|
slaves?.setColorTemperature(tempLevel)
|
||||||
def tempLevel = master.currentValue("colorTemperature")
|
}
|
||||||
slaves?.setColorTemperature(tempLevel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Version/Copyright/Information/Help
|
//Version/Copyright/Information/Help
|
||||||
@@ -139,11 +102,11 @@ private def textAppName() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private def textVersion() {
|
private def textVersion() {
|
||||||
def text = "Version 1.1.0 (11/09/2016)"
|
def text = "Version 1.0.0 (07/04/2015)"
|
||||||
}
|
}
|
||||||
|
|
||||||
private def textCopyright() {
|
private def textCopyright() {
|
||||||
def text = "Copyright © 2016 Michael Struck"
|
def text = "Copyright © 2015 Michael Struck"
|
||||||
}
|
}
|
||||||
|
|
||||||
private def textLicense() {
|
private def textLicense() {
|
||||||
@@ -165,5 +128,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. Also includes a random color feature."
|
"including on/off conditions, hue, saturation, level and color temperature."
|
||||||
}
|
}
|
||||||
@@ -381,28 +381,38 @@ def updateDevices() {
|
|||||||
selectors.add("${device.id}")
|
selectors.add("${device.id}")
|
||||||
if (!childDevice) {
|
if (!childDevice) {
|
||||||
// log.info("Adding device ${device.id}: ${device.product}")
|
// log.info("Adding device ${device.id}: ${device.product}")
|
||||||
|
def data = [
|
||||||
|
label: device.label,
|
||||||
|
level: Math.round((device.brightness ?: 1) * 100),
|
||||||
|
switch: device.power,
|
||||||
|
colorTemperature: device.color.kelvin
|
||||||
|
]
|
||||||
if (device.product.capabilities.has_color) {
|
if (device.product.capabilities.has_color) {
|
||||||
childDevice = addChildDevice(app.namespace, "LIFX Color Bulb", device.id, null, ["label": device.label, "completedSetup": true])
|
data["color"] = colorUtil.hslToHex((device.color.hue / 3.6) as int, (device.color.saturation * 100) as int)
|
||||||
|
data["hue"] = device.color.hue / 3.6
|
||||||
|
data["saturation"] = device.color.saturation * 100
|
||||||
|
childDevice = addChildDevice(app.namespace, "LIFX Color Bulb", device.id, null, data)
|
||||||
} else {
|
} else {
|
||||||
childDevice = addChildDevice(app.namespace, "LIFX White Bulb", device.id, null, ["label": device.label, "completedSetup": true])
|
childDevice = addChildDevice(app.namespace, "LIFX White Bulb", device.id, null, data)
|
||||||
}
|
}
|
||||||
|
childDevice?.completedSetup = true
|
||||||
|
} else {
|
||||||
|
if (device.product.capabilities.has_color) {
|
||||||
|
sendEvent(name: "color", value: colorUtil.hslToHex((device.color.hue / 3.6) as int, (device.color.saturation * 100) as int))
|
||||||
|
sendEvent(name: "hue", value: device.color.hue / 3.6)
|
||||||
|
sendEvent(name: "saturation", value: device.color.saturation * 100)
|
||||||
|
}
|
||||||
|
childDevice.sendEvent(name: "label", value: device.label)
|
||||||
|
childDevice.sendEvent(name: "level", value: Math.round((device.brightness ?: 1) * 100))
|
||||||
|
childDevice.sendEvent(name: "switch.setLevel", value: Math.round((device.brightness ?: 1) * 100))
|
||||||
|
childDevice.sendEvent(name: "switch", value: device.power)
|
||||||
|
childDevice.sendEvent(name: "colorTemperature", value: device.color.kelvin)
|
||||||
|
childDevice.sendEvent(name: "model", value: device.product.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device.product.capabilities.has_color) {
|
|
||||||
childDevice.sendEvent(name: "color", value: colorUtil.hslToHex((device.color.hue / 3.6) as int, (device.color.saturation * 100) as int))
|
|
||||||
childDevice.sendEvent(name: "hue", value: device.color.hue / 3.6)
|
|
||||||
childDevice.sendEvent(name: "saturation", value: device.color.saturation * 100)
|
|
||||||
}
|
|
||||||
childDevice.sendEvent(name: "label", value: device.label)
|
|
||||||
childDevice.sendEvent(name: "level", value: Math.round((device.brightness ?: 1) * 100))
|
|
||||||
childDevice.sendEvent(name: "switch.setLevel", value: Math.round((device.brightness ?: 1) * 100))
|
|
||||||
childDevice.sendEvent(name: "switch", value: device.power)
|
|
||||||
childDevice.sendEvent(name: "colorTemperature", value: device.color.kelvin)
|
|
||||||
childDevice.sendEvent(name: "model", value: device.product.name)
|
|
||||||
|
|
||||||
if (state.devices[device.id] == null) {
|
if (state.devices[device.id] == null) {
|
||||||
// State missing, add it and set it to opposite status as current status to provoke event below
|
// State missing, add it and set it to opposite status as current status to provoke event below
|
||||||
state.devices[device.id] = [online: !device.connected]
|
state.devices[device.id] = [online : !device.connected]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.devices[device.id]?.online && device.connected) {
|
if (!state.devices[device.id]?.online && device.connected) {
|
||||||
|
|||||||
@@ -24,12 +24,6 @@
|
|||||||
* switches | switch | on, off | on, off
|
* switches | switch | on, off | on, off
|
||||||
* motionSensors | motion | | active, inactive
|
* motionSensors | motion | | active, inactive
|
||||||
* contactSensors | contact | | open, closed
|
* contactSensors | contact | | open, closed
|
||||||
* thermostat | thermostat | setHeatingSetpoint, | temperature, heatingSetpoint
|
|
||||||
* | | setCoolingSetpoint(number) | coolingSetpoint, thermostatSetpoint
|
|
||||||
* | | off, heat, emergencyHeat | thermostatMode — ["emergency heat", "auto", "cool", "off", "heat"]
|
|
||||||
* | | cool, setThermostatMode | thermostatFanMode — ["auto", "on", "circulate"]
|
|
||||||
* | | fanOn, fanAuto, fanCirculate| thermostatOperatingState — ["cooling", "heating", "pending heat",
|
|
||||||
* | | setThermostatFanMode, auto | "fan only", "vent economizer", "pending cool", "idle"]
|
|
||||||
* presenceSensors | presence | | present, 'not present'
|
* presenceSensors | presence | | present, 'not present'
|
||||||
* temperatureSensors | temperature | | <numeric, F or C according to unit>
|
* temperatureSensors | temperature | | <numeric, F or C according to unit>
|
||||||
* accelerationSensors | acceleration | | active, inactive
|
* accelerationSensors | acceleration | | active, inactive
|
||||||
@@ -64,7 +58,6 @@ preferences(oauthPage: "deviceAuthorization") {
|
|||||||
input "switches", "capability.switch", title: "Which Switches?", multiple: true, required: false
|
input "switches", "capability.switch", title: "Which Switches?", multiple: true, required: false
|
||||||
input "motionSensors", "capability.motionSensor", title: "Which Motion Sensors?", multiple: true, required: false
|
input "motionSensors", "capability.motionSensor", title: "Which Motion Sensors?", multiple: true, required: false
|
||||||
input "contactSensors", "capability.contactSensor", title: "Which Contact Sensors?", multiple: true, required: false
|
input "contactSensors", "capability.contactSensor", title: "Which Contact Sensors?", multiple: true, required: false
|
||||||
input "thermostats", "capability.thermostat", title: "Which Thermostats?", multiple: true, required: false
|
|
||||||
input "presenceSensors", "capability.presenceSensor", title: "Which Presence Sensors?", multiple: true, required: false
|
input "presenceSensors", "capability.presenceSensor", title: "Which Presence Sensors?", multiple: true, required: false
|
||||||
input "temperatureSensors", "capability.temperatureMeasurement", title: "Which Temperature Sensors?", multiple: true, required: false
|
input "temperatureSensors", "capability.temperatureMeasurement", title: "Which Temperature Sensors?", multiple: true, required: false
|
||||||
input "accelerationSensors", "capability.accelerationSensor", title: "Which Vibration Sensors?", multiple: true, required: false
|
input "accelerationSensors", "capability.accelerationSensor", title: "Which Vibration Sensors?", multiple: true, required: false
|
||||||
@@ -943,7 +936,7 @@ def deleteHarmony() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getAllDevices() {
|
private getAllDevices() {
|
||||||
([] + switches + motionSensors + contactSensors + thermostats + presenceSensors + temperatureSensors + accelerationSensors + waterSensors + lightSensors + humiditySensors + alarms + locks)?.findAll()?.unique { it.id }
|
([] + switches + motionSensors + contactSensors + presenceSensors + temperatureSensors + accelerationSensors + waterSensors + lightSensors + humiditySensors + alarms + locks)?.findAll()?.unique { it.id }
|
||||||
}
|
}
|
||||||
|
|
||||||
private deviceItem(device) {
|
private deviceItem(device) {
|
||||||
|
|||||||
Reference in New Issue
Block a user