Compare commits

..

9 Commits

Author SHA1 Message Date
Kyle Yoksh
cd9743a10f MSA-1697: Z-Wave Door Sensor as Smoke Detector. Useful for those people wanting to know if their wired interconnected smoke detectors are alerting. 2017-01-09 20:11:04 -08:00
Jack Chi
c028515fcd Merge pull request #1546 from skt123/dimmer_switch
[CHF-487] Health Check for Z-Wave Dimmer Switch
2016-12-29 10:29:43 -08:00
Jack Chi
751c98d123 Merge pull request #1550 from parijatdas/enerwave
[CHF-488] [CHF-489] [CHF-490] Implementation of HealthCheck for Enerwave Duplex Receptacle ZW15R, Enerwave On/Off Switch ZW15S and Leviton 15A Switch VRS15-1LZ
2016-12-29 10:27:18 -08:00
Jack Chi
5b874e8f3a Merge pull request #1545 from pchomal/dimmerswitch_generic
[CHF-477] Health Check for Z-Wave Dimmer Switch Generic
2016-12-27 11:36:51 -08:00
Parijat Das
9e10405527 Added fingerprints for the following devices:
1. Enerwave Duplex Receptacle ZW15R
2. Enerwave On/Off Switch ZW15S
3. Leviton 15A Switch VRS15-1LZ
2016-12-20 18:33:50 +05:30
sushant.k1
32ceaff54d [CHF-487]
Added Health Check Implementation for:
1. 1,000-Watt In-Wall Smart Dimmer Switch (GE 12725)
2. In-Wall Smart Fan Control (GE 12730)
2016-12-20 12:08:16 +05:30
piyush.c
5b1da30a47 [CHF-477]
Health Check implementation for Z-Wave Dimmer Switch Generic with checkinterval of 32min
2016-12-20 10:39:08 +05:30
Vinay Rao
0a82077b24 Merge pull request #1519 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-12-07 14:15:16 -08:00
Vinay Rao
bbad6dfa7a Merge pull request #1501 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-11-28 10:35:24 -08:00
15 changed files with 363 additions and 95 deletions

View File

@@ -22,9 +22,10 @@ metadata {
capability "Sensor" capability "Sensor"
capability "Health Check" capability "Health Check"
fingerprint mfr:"0063", prod:"4457", deviceJoinName: "Z-Wave Wall Dimmer" fingerprint mfr:"0063", prod:"4457", deviceJoinName: "GE In-Wall Smart Dimmer "
fingerprint mfr:"0063", prod:"4944", deviceJoinName: "Z-Wave Wall Dimmer" fingerprint mfr:"0063", prod:"4944", deviceJoinName: "GE In-Wall Smart Dimmer "
fingerprint mfr:"0063", prod:"5044", deviceJoinName: "Z-Wave Plug-In Dimmer" fingerprint mfr:"0063", prod:"5044", deviceJoinName: "GE Plug-In Smart Dimmer "
fingerprint mfr:"0063", prod:"4944", model:"3034", deviceJoinName: "GE In-Wall Smart Fan Control"
} }
simulator { simulator {

View File

@@ -99,7 +99,7 @@ def parse(String description) {
def poll() { def poll() {
def refreshCmds = [ def refreshCmds = [
"st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 2000" "st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 500"
] ]
return refreshCmds + zigbee.onOffRefresh() + zigbee.levelRefresh() return refreshCmds + zigbee.onOffRefresh() + zigbee.levelRefresh()
@@ -197,7 +197,7 @@ def off() {
def refresh() { def refresh() {
def refreshCmds = [ def refreshCmds = [
"st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 2000" "st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 500"
] ]
return refreshCmds + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig() return refreshCmds + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig()

View File

@@ -128,9 +128,9 @@ def setLevel(value) {
def refresh() { def refresh() {
[ [
"st rattr 0x${device.deviceNetworkId} ${endpointId} 6 0", "delay 2000", "st rattr 0x${device.deviceNetworkId} ${endpointId} 6 0", "delay 500",
"st rattr 0x${device.deviceNetworkId} ${endpointId} 8 0", "delay 2000", "st rattr 0x${device.deviceNetworkId} ${endpointId} 8 0", "delay 500",
"st rattr 0x${device.deviceNetworkId} ${endpointId} 0x0B04 0x050B", "delay 2000" "st rattr 0x${device.deviceNetworkId} ${endpointId} 0x0B04 0x050B", "delay 500"
] ]
} }
@@ -313,9 +313,9 @@ def isDescriptionPower(descMap) {
def onOffConfig() { def onOffConfig() {
[ [
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 6 {${device.zigbeeId}} {}", "delay 2000", "zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 6 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 6 0 0x10 0 600 {01}", "delay 200", "zcl global send-me-a-report 6 0 0x10 0 600 {01}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000" "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500"
] ]
} }
@@ -323,9 +323,9 @@ def onOffConfig() {
//min level change is 01 //min level change is 01
def levelConfig() { def levelConfig() {
[ [
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 8 {${device.zigbeeId}} {}", "delay 2000", "zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 8 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 8 0 0x20 5 3600 {01}", "delay 200", "zcl global send-me-a-report 8 0 0x20 5 3600 {01}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000" "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500"
] ]
} }
@@ -333,10 +333,9 @@ def levelConfig() {
//min change in value is 05 //min change in value is 05
def powerConfig() { def powerConfig() {
[ [
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 2000", "zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x0B04 0x050B 0x29 1 600 {05 00}", //The send-me-a-report is custom to the attribute type for CentraLite "zcl global send-me-a-report 0x0B04 0x050B 0x29 1 600 {05 00}", //The send-me-a-report is custom to the attribute type for CentraLite
"delay 200", "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000"
] ]
} }
@@ -345,10 +344,7 @@ def setLevelWithRate(level, rate) {
rate = "0000" rate = "0000"
} }
level = convertToHexString(level * 255 / 100) //Converting the 0-100 range to 0-FF range in hex level = convertToHexString(level * 255 / 100) //Converting the 0-100 range to 0-FF range in hex
[ "st cmd 0x${device.deviceNetworkId} ${endpointId} 8 4 {$level $rate}"
"st cmd 0x${device.deviceNetworkId} ${endpointId} 8 4 {$level $rate}",
"delay 2000"
]
} }
String convertToHexString(value, width=2) { String convertToHexString(value, width=2) {

View File

@@ -51,7 +51,7 @@ def on() {
'zcl on-off on', 'zcl on-off on',
'delay 200', 'delay 200',
"send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}", "send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}",
'delay 2000' 'delay 500'
] ]
@@ -62,6 +62,6 @@ def off() {
'zcl on-off off', 'zcl on-off off',
'delay 200', 'delay 200',
"send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}", "send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}",
'delay 2000' 'delay 500'
] ]
} }

View File

@@ -157,10 +157,9 @@ def configure() {
//min change in value is 01 //min change in value is 01
def powerConfig() { def powerConfig() {
[ [
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 2000", "zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x0B04 0x050B 0x29 1 600 {05 00}", //The send-me-a-report is custom to the attribute type for CentraLite "zcl global send-me-a-report 0x0B04 0x050B 0x29 1 600 {05 00}", //The send-me-a-report is custom to the attribute type for CentraLite
"delay 200", "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000"
] ]
} }

View File

@@ -29,10 +29,9 @@ metadata {
command "enrollResponse" command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-S", deviceJoinName: "Water Leak Sensor" fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-S", deviceJoinName: "Water Leak Sensor"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315" fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-Seu", deviceJoinName: "Water Leak Sensor" fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-Seu", deviceJoinName: "Water Leak Sensor"
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-L", deviceJoinName: "Iris Smart Water Sensor"
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "moisturev4", deviceJoinName: "Water Leak Sensor" fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "moisturev4", deviceJoinName: "Water Leak Sensor"
} }
@@ -286,8 +285,8 @@ def ping() {
def refresh() { def refresh() {
log.debug "Refreshing Temperature and Battery" log.debug "Refreshing Temperature and Battery"
def refreshCmds = [ def refreshCmds = [
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 2000", "st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 2000" "st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
] ]
return refreshCmds + enrollResponse() return refreshCmds + enrollResponse()
@@ -309,10 +308,10 @@ def enrollResponse() {
[ [
//Resending the CIE in case the enroll request is sent before CIE is written //Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", "zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000", "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response //Enroll Response
"raw 0x500 {01 23 00 00 00}", "delay 200", "raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 2000" "send 0x${device.deviceNetworkId} 1 1", "delay 200"
] ]
} }

View File

@@ -298,8 +298,8 @@ def ping() {
def refresh() { def refresh() {
log.debug "refresh called" log.debug "refresh called"
def refreshCmds = [ def refreshCmds = [
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 2000", "st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 2000" "st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
] ]
return refreshCmds + enrollResponse() return refreshCmds + enrollResponse()
@@ -321,10 +321,10 @@ def enrollResponse() {
[ [
//Resending the CIE in case the enroll request is sent before CIE is written //Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", "zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000", "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response //Enroll Response
"raw 0x500 {01 23 00 00 00}", "delay 200", "raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 2000" "send 0x${device.deviceNetworkId} 1 1", "delay 200"
] ]
} }

View File

@@ -428,10 +428,10 @@ def enrollResponse() {
[ [
//Resending the CIE in case the enroll request is sent before CIE is written //Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", "zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000", "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response //Enroll Response
"raw 0x500 {01 23 00 00 00}", "delay 200", "raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 2000" "send 0x${device.deviceNetworkId} 1 1", "delay 200"
] ]
} }

View File

@@ -252,8 +252,8 @@ def ping() {
def refresh() { def refresh() {
log.debug "Refreshing Temperature and Battery" log.debug "Refreshing Temperature and Battery"
def refreshCmds = [ def refreshCmds = [
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 2000", "st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 2000" "st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
] ]
return refreshCmds + enrollResponse() return refreshCmds + enrollResponse()
@@ -277,10 +277,10 @@ def enrollResponse() {
[ [
//Resending the CIE in case the enroll request is sent before CIE is written //Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200", "zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000", "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response //Enroll Response
"raw 0x500 {01 23 00 00 00}", "delay 200", "raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 2000" "send 0x${device.deviceNetworkId} 1 1", "delay 200"
] ]
} }

View File

@@ -270,9 +270,9 @@ def configure() {
log.debug "Configuring Reporting and Bindings." log.debug "Configuring Reporting and Bindings."
def humidityConfigCmds = [ def humidityConfigCmds = [
"zdo bind 0x${device.deviceNetworkId} 1 1 0xFC45 {${device.zigbeeId}} {}", "delay 2000", "zdo bind 0x${device.deviceNetworkId} 1 1 0xFC45 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 0xFC45 0 0x29 30 3600 {6400}", "delay 200", "zcl global send-me-a-report 0xFC45 0 0x29 30 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 1", "delay 2000" "send 0x${device.deviceNetworkId} 1 1", "delay 500"
] ]
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity // temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity

View File

@@ -28,8 +28,8 @@ metadata {
fingerprint inClusters: "0000, 0001, 0003, 0020, 0402, 0B05", outClusters: "0003, 0006, 0008, 0019", manufacturer: "OSRAM", model: "LIGHTIFY Dimming Switch", deviceJoinName: "OSRAM LIGHTIFY Dimming Switch" fingerprint inClusters: "0000, 0001, 0003, 0020, 0402, 0B05", outClusters: "0003, 0006, 0008, 0019", manufacturer: "OSRAM", model: "LIGHTIFY Dimming Switch", deviceJoinName: "OSRAM LIGHTIFY Dimming Switch"
//fingerprint inClusters: "0000, 0001, 0003, 0020, 0500", outClusters: "0003,0019", manufacturer: "CentraLite", model: "3455-L", deviceJoinName: "Iris Care Pendant" //fingerprint inClusters: "0000, 0001, 0003, 0020, 0500", outClusters: "0003,0019", manufacturer: "CentraLite", model: "3455-L", deviceJoinName: "Iris Care Pendant"
fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0402, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model: "3460-L", deviceJoinName: "Iris Smart Button" //fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0402, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model: "3460-L", deviceJoinName: "Iris Smart Button"
fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model:"3450-L", deviceJoinName: "Iris KeyFob" //fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model:"3450-L", deviceJoinName: "Iris KeyFob"
} }
simulator {} simulator {}

View File

@@ -24,6 +24,10 @@ 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" fingerprint mfr:"001D", prod:"1B03", model:"0334", deviceJoinName: "Leviton Universal Dimmer"
fingerprint mfr:"011A", prod:"0102", model:"0201", deviceJoinName: "Enerwave In-Wall Dimmer"
fingerprint mfr:"001D", prod:"1001", model:"0334", deviceJoinName: "Leviton 3-Speed Fan Controller"
fingerprint mfr:"001D", prod:"0602", model:"0334", deviceJoinName: "Leviton Magnetic Low Voltage Dimmer"
fingerprint mfr:"001D", prod:"0401", model:"0334", deviceJoinName: "Leviton 600W Incandescent Dimmer"
} }
simulator { simulator {

View File

@@ -0,0 +1,273 @@
/**
* 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.
*
* Z-Wave Door/Window Sensor
*
* Author: SmartThings
* Date: 2013-11-3
*/
metadata {
definition (name: "Z-Wave Door Sensor as Smoke Detector", namespace: "smartthings", author: "SmartThings") {
capability "Contact Sensor"
capability "Sensor"
capability "Battery"
capability "Configuration"
fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x85,0x86,0x72"
fingerprint deviceId: "0x07", inClusters: "0x30"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x98"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x80,0x71,0x85,0x70,0x72,0x86,0x30,0x31,0x84,0x59,0x73,0x5A,0x8F,0x98,0x7A", outClusters:"0x20" // Philio multi+
}
// simulator metadata
simulator {
// status messages
status "fire": "command: 2001, payload: FF"
status "safe": "command: 2001, payload: 00"
status "wake up": "command: 8407, payload: "
}
// UI tile definitions
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state "fire",label: '${name}',icon: "st.alarm.smoke.smoke",backgroundColor: "#ffa81e"
state "safe",label: '${name}',icon: "st.alarm.smoke.clear",backgroundColor: "#79b821"
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
}
main "contact"
details(["contact", "battery"])
}
}
def parse(String description) {
def result = null
if (description.startsWith("Err 106")) {
if (state.sec) {
log.debug description
} else {
result = createEvent(
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.",
eventType: "ALERT",
name: "secureInclusion",
value: "failed",
isStateChange: true,
)
}
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
log.debug "parsed '$description' to $result"
return result
}
def updated() {
def cmds = []
if (!state.MSR) {
cmds = [
command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()),
"delay 1200",
zwave.wakeUpV1.wakeUpNoMoreInformation().format()
]
} else if (!state.lastbat) {
cmds = []
} else {
cmds = [zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
response(cmds)
}
def configure() {
commands([
zwave.manufacturerSpecificV2.manufacturerSpecificGet(),
zwave.batteryV1.batteryGet()
], 6000)
}
def sensorValueEvent(value) {
if (value) {
createEvent(name: "contact", value: "fire", descriptionText: "$device.displayName fire detected")
} else {
createEvent(name: "contact", value: "safe", descriptionText: "$device.displayName is safe")
}
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cmd)
{
sensorValueEvent(cmd.sensorValue)
}
def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)
{
sensorValueEvent(cmd.sensorState)
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd)
{
def result = []
if (cmd.notificationType == 0x06 && cmd.event == 0x16) {
result << sensorValueEvent(1)
} else if (cmd.notificationType == 0x06 && cmd.event == 0x17) {
result << sensorValueEvent(0)
} else if (cmd.notificationType == 0x07) {
if (cmd.v1AlarmType == 0x07) { // special case for nonstandard messages from Monoprice door/window sensors
result << sensorValueEvent(cmd.v1AlarmLevel)
} else if (cmd.event == 0x01 || cmd.event == 0x02) {
result << sensorValueEvent(1)
} else if (cmd.event == 0x03) {
result << createEvent(descriptionText: "$device.displayName covering was removed", isStateChange: true)
if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()))
} else if (cmd.event == 0x05 || cmd.event == 0x06) {
result << createEvent(descriptionText: "$device.displayName detected glass breakage", isStateChange: true)
} else if (cmd.event == 0x07) {
if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()))
result << createEvent(name: "motion", value: "active", descriptionText:"$device.displayName detected motion")
}
} else if (cmd.notificationType) {
def text = "Notification $cmd.notificationType: event ${([cmd.event] + cmd.eventParameter).join(", ")}"
result << createEvent(name: "notification$cmd.notificationType", value: "$cmd.event", descriptionText: text, displayed: false)
} else {
def value = cmd.v1AlarmLevel == 255 ? "active" : cmd.v1AlarmLevel ?: "inactive"
result << createEvent(name: "alarm $cmd.v1AlarmType", value: value, displayed: false)
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
def event = createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)
def cmds = []
if (!state.MSR) {
cmds << command(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
cmds << "delay 1200"
}
if (!state.lastbat || now() - state.lastbat > 53*60*60*1000) {
cmds << command(zwave.batteryV1.batteryGet())
} else {
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
}
[event, response(cmds)]
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} has a low battery"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbat = now()
[createEvent(map), response(zwave.wakeUpV1.wakeUpNoMoreInformation())]
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def result = []
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
log.debug "msr: $msr"
updateDataValue("MSR", msr)
retypeBasedOnMSR()
result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
if (msr == "011A-0601-0901") { // Enerwave motion doesn't always get the associationSet that the hub sends on join
result << response(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId))
} else if (!device.currentState("battery")) {
if (msr == "0086-0102-0059") {
result << response(zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.batteryV1.batteryGet()).format())
} else {
result << response(command(zwave.batteryV1.batteryGet()))
}
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
// log.debug "encapsulated: $encapsulatedCommand"
if (encapsulatedCommand) {
state.sec = 1
zwaveEvent(encapsulatedCommand)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: "$device.displayName: $cmd", displayed: false)
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec == 1) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=200) {
delayBetween(commands.collect{ command(it) }, delay)
}
def retypeBasedOnMSR() {
switch (state.MSR) {
case "0086-0002-002D":
log.debug "Changing device type to Z-Wave Water Sensor"
setDeviceType("Z-Wave Water Sensor")
break
case "011F-0001-0001": // Schlage motion
case "014A-0001-0001": // Ecolink motion
case "014A-0004-0001": // Ecolink motion +
case "0060-0001-0002": // Everspring SP814
case "0060-0001-0003": // Everspring HSP02
case "011A-0601-0901": // Enerwave ZWN-BPC
log.debug "Changing device type to Z-Wave Motion Sensor"
setDeviceType("Z-Wave Motion Sensor")
break
case "013C-0002-000D": // Philio multi +
log.debug "Changing device type to 3-in-1 Multisensor Plus (SG)"
setDeviceType("3-in-1 Multisensor Plus (SG)")
break
case "0109-2001-0106": // Vision door/window
log.debug "Changing device type to Z-Wave Plus Door/Window Sensor"
setDeviceType("Z-Wave Plus Door/Window Sensor")
break
case "0109-2002-0205": // Vision Motion
log.debug "Changing device type to Z-Wave Plus Motion/Temp Sensor"
setDeviceType("Z-Wave Plus Motion/Temp Sensor")
break
}
}

View File

@@ -25,6 +25,9 @@ metadata {
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"
fingerprint mfr:"001D", prod:"1D04", model:"0334", deviceJoinName: "Leviton Outlet" fingerprint mfr:"001D", prod:"1D04", model:"0334", deviceJoinName: "Leviton Outlet"
fingerprint mfr:"001D", prod:"1C02", model:"0334", deviceJoinName: "Leviton Switch" fingerprint mfr:"001D", prod:"1C02", model:"0334", deviceJoinName: "Leviton Switch"
fingerprint mfr:"001D", prod:"0301", model:"0334", deviceJoinName: "Leviton 15A Switch"
fingerprint mfr:"011A", prod:"0101", model:"0102", deviceJoinName: "Enerwave On/Off Switch"
fingerprint mfr:"011A", prod:"0101", model:"0603", deviceJoinName: "Enerwave Duplex Receptacle"
} }
// simulator metadata // simulator metadata

View File

@@ -1,11 +1,10 @@
/** /**
* Color Coordinator * Color Coordinator
* Version 1.1.1 - 11/9/16 * 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. * 1.1.0 - Fixed issue where master can be part of slaves. This causes a loop that impacts SmartThings.
* 1.1.1 - Fix NPE being thrown for slave/master inputs being empty.
* *
* *
* 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
@@ -34,17 +33,17 @@ preferences {
def mainPage() { def mainPage() {
dynamicPage(name: "mainPage", title: "", install: true, uninstall: false) { dynamicPage(name: "mainPage", title: "", install: true, uninstall: false) {
def masterInList = slaves?.id?.find{it==master?.id} def masterInList = slaves.id.find{it==master.id}
if (masterInList) { if (masterInList) {
section ("**WARNING**"){ 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" 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") { section("Master Light") {
input "master", "capability.colorControl", title: "Colored Light", required: true 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: true, submitOnChange: true input "slaves", "capability.colorControl", title: "Colored Lights", multiple: true, required: false, submitOnChange: true
} }
section([mobileOnly:true], "Options") { section([mobileOnly:true], "Options") {
input "randomYes", "bool",title: "When Master Turned On, Randomize Color", defaultValue: false input "randomYes", "bool",title: "When Master Turned On, Randomize Color", defaultValue: false
@@ -82,44 +81,40 @@ def init() {
} }
//----------------------------------- //-----------------------------------
def onOffHandler(evt){ def onOffHandler(evt){
if (slaves && master) { if (!slaves.id.find{it==master.id}){
if (!slaves?.id.find{it==master?.id}){ if (master.currentValue("switch") == "on"){
if (master?.currentValue("switch") == "on"){ if (randomYes) getRandomColorMaster()
if (randomYes) getRandomColorMaster() else slaves?.on()
else slaves?.on() }
} else {
else { slaves?.off()
slaves?.off() }
}
}
} }
} }
def colorHandler(evt) { def colorHandler(evt) {
if (slaves && master) { if (!slaves.id.find{it==master.id} && master.currentValue("switch") == "on"){
if (!slaves?.id?.find{it==master?.id} && master?.currentValue("switch") == "on"){ log.debug "Changing Slave units H,S,L"
log.debug "Changing Slave units H,S,L" def dimLevel = master.currentValue("level")
def dimLevel = master?.currentValue("level") def hueLevel = master.currentValue("hue")
def hueLevel = master?.currentValue("hue") def saturationLevel = master.currentValue("saturation")
def saturationLevel = master.currentValue("saturation") def newValue = [hue: hueLevel, saturation: saturationLevel, level: dimLevel as Integer]
def newValue = [hue: hueLevel, saturation: saturationLevel, level: dimLevel as Integer] slaves?.setColor(newValue)
slaves?.setColor(newValue) try {
try { log.debug "Changing Slave color temp"
log.debug "Changing Slave color temp" def tempLevel = master.currentValue("colorTemperature")
def tempLevel = master?.currentValue("colorTemperature") slaves?.setColorTemperature(tempLevel)
slaves?.setColorTemperature(tempLevel) }
} catch (e){
catch (e){ log.debug "Color temp for master --"
log.debug "Color temp for master --" }
}
}
} }
} }
def getRandomColorMaster(){ def getRandomColorMaster(){
def hueLevel = Math.floor(Math.random() *1000) def hueLevel = Math.floor(Math.random() *1000)
def saturationLevel = Math.floor(Math.random() * 100) def saturationLevel = Math.floor(Math.random() * 100)
def dimLevel = master?.currentValue("level") 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 hueLevel
log.debug saturationLevel log.debug saturationLevel
@@ -128,14 +123,12 @@ def getRandomColorMaster(){
} }
def tempHandler(evt){ def tempHandler(evt){
if (slaves && master) { if (!slaves.id.find{it==master.id} && master.currentValue("switch") == "on"){
if (!slaves?.id?.find{it==master?.id} && master?.currentValue("switch") == "on"){ if (evt.value != "--") {
if (evt.value != "--") { log.debug "Changing Slave color temp based on Master change"
log.debug "Changing Slave color temp based on Master change" def tempLevel = master.currentValue("colorTemperature")
def tempLevel = master.currentValue("colorTemperature") slaves?.setColorTemperature(tempLevel)
slaves?.setColorTemperature(tempLevel) }
}
}
} }
} }
@@ -146,7 +139,7 @@ private def textAppName() {
} }
private def textVersion() { private def textVersion() {
def text = "Version 1.1.1 (12/13/2016)" def text = "Version 1.1.0 (11/09/2016)"
} }
private def textCopyright() { private def textCopyright() {