Compare commits

..

39 Commits

Author SHA1 Message Date
Vinay Rao
a7cd9e072b Merge pull request #1078 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2016-07-26 13:45:49 -07:00
Vinay Rao
b5843acc38 Merge pull request #1067 from SmartThingsCommunity/master
Rolling up master to staging
2016-07-19 16:00:31 -07:00
Vinay Rao
863c49ffd4 Merge pull request #1066 from SmartThingsCommunity/staging
Rolling down staging hotfix to production
2016-07-19 15:55:53 -07:00
Vinay Rao
4e5d1f6ad0 Merge pull request #1065 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2016-07-19 15:09:07 -07:00
Vinay Rao
2f0d8d814b Merge pull request #1064 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-07-19 15:06:43 -07:00
Vinay Rao
a86eba494f Merge pull request #1063 from tslagle13/add-capability-SS-open/closed
Add capability sensor to SS Open/Closed
2016-07-18 15:46:21 -07:00
tslagle13
2549372bb7 Add capability sensor to SS Open/Closed
There are some integrations out there using the "Actuator" and "Sensor" Capabilities and this doesn't show up for them.
2016-07-18 15:20:06 -07:00
Vinay Rao
38cdde7479 Merge pull request #1057 from SmartThingsCommunity/DVCSMP-1892
DVCSMP-1892 Fix error in Z-Wave Door/Window Sensor wake up handler
2016-07-14 10:54:36 -07:00
Duncan McKee
853f616cc8 DVCSMP-1892 Fix error in Z-Wave Door/Window Sensor wake up handler 2016-07-14 13:51:36 -04:00
Vinay Rao
2b3a4e1278 Merge pull request #1055 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-07-13 19:45:29 -07:00
Vinay Rao
825e693efd Merge pull request #1054 from SmartThingsCommunity/production
Rolling down prod hotfix to staging
2016-07-13 19:44:57 -07:00
Vinay Rao
686c8f7337 Merge pull request #1053 from rappleg/FixFalseBatteryNotificationOnNewerGroovyVersion
PRP-192 Fix false low battery notifications on Groovy 2.4.4
2016-07-13 19:40:55 -07:00
rappleg
11f4e42fe9 PRP-192 Fix false low battery notifications on Groovy 2.4.4 2016-07-13 21:22:57 -05:00
Steve Vlaminck
bc459ae178 Merge pull request #1051 from vlaminck/GWU-exception-fix
fix divide by zero exception [DVCSMP-1891]
2016-07-13 10:01:10 -05:00
vlaminck
1392b6e1a5 fix divide by zero exception 2016-07-13 09:27:23 -05:00
Vinay Rao
3db96faa00 Merge pull request #1049 from SmartThingsCommunity/master
Rolling up master to staging
2016-07-12 15:04:26 -07:00
Vinay Rao
399fbcb676 Merge pull request #1048 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-07-12 15:03:28 -07:00
Vinay Rao
eed1ced71b Merge pull request #1047 from SmartThingsCommunity/staging
Rolling up staging for production deploy
2016-07-12 14:33:19 -07:00
Vinay Rao
d080833d5c Merge pull request #1046 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-07-12 14:26:10 -07:00
Vinay Rao
e998528e8e Merge pull request #1041 from rappleg/ProductionFixJsonSlurperHashMap
PRP-172 Fix Hue Connect parse errors on newer versions of Groovy
2016-07-11 23:49:10 -07:00
Jack Chi
3472ee329d Merge pull request #1036 from jackchi/healthcheck-zwave-aeon
[CHF-138] Adds HealthCheck to Z-Wave Sensors
2016-07-11 11:21:30 -07:00
Juan Pablo Risso
577b127287 PRP-151 Harmony cloud fix + PENG-161 - Allow setLevel (#1035)
* PRP-151 - Harmony Cloud

Added is IP

Try around Integer.parseInt

declare int p outside try

* Remove unsubscribe & unschedule

* PENG-161 - Allow setLevel for switch capability

Last version
2016-07-11 10:04:32 -04:00
rappleg
d85566bb98 PRP-172 Fix Hue Connect parse errors on newer versions of Groovy 2016-07-10 15:35:12 -05:00
jackchi
5f41af35e2 [CHF-138] Adds HealthCheck to Z-Wave Sensors 2016-07-08 15:36:58 -07:00
Duncan McKee
e1a5b4dd27 Merge pull request #1034 from SmartThingsCommunity/DVCSMP-1879
DVCSMP-1879 Fix error in Z-Wave Door/Window Sensor throwing exceptions on update
2016-07-06 17:43:42 -04:00
Duncan McKee
a2baa37901 DVCSMP-1879 Fix error in Z-Wave Door/Window Sensor throwing exceptions on update 2016-07-06 17:08:15 -04:00
Vinay Rao
922ab45343 Merge pull request #1033 from SmartThingsCommunity/master
Rolling up master to staging for deploy
2016-07-06 13:59:03 -07:00
Vinay Rao
962774996e Merge pull request #1032 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-07-06 13:57:35 -07:00
Vinay Rao
d79594cbcb Merge pull request #1031 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-07-06 13:56:39 -07:00
Vinay Rao
bf8fe4cad7 Merge pull request #1030 from rappleg/RevertLazyMapNewerGroovyVersion
Revert "PRP-172 Fix Hue Connect parse errors on newer versions of Groovy"
2016-07-06 13:53:32 -07:00
rappleg
65752ce378 Revert "PRP-172 Fix Hue Connect parse errors on newer versions of Groovy"
This reverts commit be7f6a76a9.
2016-07-06 14:44:58 -05:00
spurohit1
95f08aeb3d Update logitech-harmony-connect.groovy (#1009)
If port is present in the callbackUrl then send command to hub else post the request through http.
Removed isIP function since it is no longer required.
2016-07-06 09:40:29 -04:00
Vinay Rao
cd7bc1b262 Merge pull request #1023 from rappleg/FixHueConnectParseErrorsGrailsUpgradeProduction
PRP-172 Fix Hue Connect parse errors on newer versions of Groovy
2016-06-30 00:46:24 -07:00
rappleg
be7f6a76a9 PRP-172 Fix Hue Connect parse errors on newer versions of Groovy 2016-06-30 02:42:24 -05:00
Vinay Rao
10e5b7e9d7 Merge pull request #1021 from SmartThingsCommunity/master
Rolling up master to staging
2016-06-28 22:57:32 -07:00
Vinay Rao
fc38c534f9 Merge pull request #1020 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-06-28 21:04:33 -07:00
Steve Vlaminck
fd47bcb8a8 Merge pull request #1011 from vlaminck/gwu-exception-handling
Gwu exception handling
2016-06-23 12:26:42 -05:00
vlaminck
972599b1b5 Provide a way to remove unsupported devices from settings 2016-06-23 12:19:54 -05:00
vlaminck
f5d3cca6a0 Guard against devices that don't support necessary commands 2016-06-23 09:27:54 -05:00
15 changed files with 163 additions and 132 deletions

View File

@@ -22,6 +22,7 @@ metadata {
capability "Configuration"
capability "Sensor"
capability "Battery"
capability "Health Check"
attribute "tamper", "enum", ["detected", "clear"]
attribute "batteryStatus", "string"
@@ -326,6 +327,9 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) {
}
def configure() {
// allow device user configured or default 16 min to check in; double the periodic reporting interval
sendEvent(name: "checkInterval", value: 2* timeOptionValueMap[reportInterval] ?: 2*8*60, displayed: false)
// This sensor joins as a secure device if you double-click the button to include it
log.debug "${device.displayName} is configuring its settings"
def request = []

View File

@@ -20,6 +20,9 @@ metadata {
capability "Configuration"
capability "Sensor"
capability "Battery"
capability "Health Check"
command "configureAfterSecure"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x98,0x7A", outClusters:"0x5A"
}
@@ -245,6 +248,8 @@ def configureAfterSecure() {
def configure() {
// log.debug "configure()"
//["delay 30000"] + secure(zwave.securityV1.securityCommandsSupportedGet())
// allow device 16 min to check in; double the periodic reporting interval
sendEvent(name: "checkInterval", value: 2*8*60, displayed: false)
}
private setConfigured() {

View File

@@ -20,6 +20,7 @@ metadata {
capability "Illuminance Measurement"
capability "Sensor"
capability "Battery"
capability "Health Check"
fingerprint deviceId: "0x2001", inClusters: "0x30,0x31,0x80,0x84,0x70,0x85,0x72,0x86"
}
@@ -180,6 +181,9 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) {
}
def configure() {
// allow device 10 min to check in; double the periodic reporting interval
sendEvent(name: "checkInterval", value: 2*5*60, displayed: false)
delayBetween([
// send binary sensor report instead of basic set for motion
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: 2).format(),

View File

@@ -255,7 +255,8 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
result.value = Math.min(100, roundedPct)
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
}
}

View File

@@ -271,7 +271,8 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
result.value = Math.min(100, roundedPct)
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
}
}

View File

@@ -24,7 +24,7 @@ metadata {
capability "Temperature Measurement"
capability "Refresh"
capability "Sensor"
command "enrollResponse"
}
@@ -73,7 +73,7 @@ metadata {
def parse(String description) {
log.debug "description: $description"
Map map = [:]
if (description?.startsWith('catchall:')) {
map = parseCatchAllMessage(description)
@@ -87,10 +87,10 @@ def parse(String description) {
else if (description?.startsWith('zone status')) {
map = parseIasMessage(description)
}
log.debug "Parse returned $map"
def result = map ? createEvent(map) : null
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
log.debug "enroll response: ${cmds}"
@@ -128,7 +128,7 @@ private Map parseCatchAllMessage(String description) {
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
// 0x07 is bind message
boolean ignoredMessage = cluster.profileId != 0x0104 ||
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
cluster.command == 0x07 ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
@@ -141,7 +141,7 @@ private Map parseReportAttributeMessage(String description) {
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
log.debug "Desc Map: $descMap"
Map resultMap = [:]
if (descMap.cluster == "0402" && descMap.attrId == "0000") {
def value = getTemperature(descMap.value)
@@ -153,11 +153,11 @@ private Map parseReportAttributeMessage(String description) {
else if (descMap.cluster == "0406" && descMap.attrId == "0000") {
def value = descMap.value.endsWith("01") ? "active" : "inactive"
resultMap = getMotionResult(value)
}
}
return resultMap
}
private Map parseCustomMessage(String description) {
Map resultMap = [:]
if (description?.startsWith('temperature: ')) {
@@ -170,7 +170,7 @@ private Map parseCustomMessage(String description) {
private Map parseIasMessage(String description) {
List parsedMsg = description.split(' ')
String msgCode = parsedMsg[2]
Map resultMap = [:]
switch(msgCode) {
case '0x0020': // Closed/No Motion/Dry
@@ -240,7 +240,8 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
}

View File

@@ -338,7 +338,8 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
result.value = Math.min(100, roundedPct)
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
}
}

View File

@@ -234,7 +234,8 @@ def getTemperature(value) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}

View File

@@ -13,7 +13,7 @@
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
definition (name: "SmartSense Open/Closed Sensor", namespace: "smartthings", author: "SmartThings", category: "C2") {
capability "Battery"
@@ -22,24 +22,25 @@ metadata {
capability "Refresh"
capability "Temperature Measurement"
capability "Health Check"
capability "Sensor"
command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3300-S"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3300"
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3320-L", deviceJoinName: "Iris Contact Sensor"
}
simulator {
}
preferences {
input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
}
tiles(scale: 2) {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
@@ -72,10 +73,10 @@ metadata {
details(["contact","temperature","battery","refresh"])
}
}
def parse(String description) {
log.debug "description: $description"
Map map = [:]
if (description?.startsWith('catchall:')) {
map = parseCatchAllMessage(description)
@@ -89,10 +90,10 @@ def parse(String description) {
else if (description?.startsWith('zone status')) {
map = parseIasMessage(description)
}
log.debug "Parse returned $map"
def result = map ? createEvent(map) : null
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
log.debug "enroll response: ${cmds}"
@@ -100,7 +101,7 @@ def parse(String description) {
}
return result
}
private Map parseCatchAllMessage(String description) {
Map resultMap = [:]
def cluster = zigbee.parse(description)
@@ -126,7 +127,7 @@ private Map parseCatchAllMessage(String description) {
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
// 0x07 is bind message
boolean ignoredMessage = cluster.profileId != 0x0104 ||
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
cluster.command == 0x07 ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
@@ -136,14 +137,14 @@ private boolean shouldProcessMessage(cluster) {
private int getHumidity(value) {
return Math.round(Double.parseDouble(value))
}
private Map parseReportAttributeMessage(String description) {
Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
log.debug "Desc Map: $descMap"
Map resultMap = [:]
if (descMap.cluster == "0402" && descMap.attrId == "0000") {
def value = getTemperature(descMap.value)
@@ -152,10 +153,10 @@ private Map parseReportAttributeMessage(String description) {
else if (descMap.cluster == "0001" && descMap.attrId == "0020") {
resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16))
}
return resultMap
}
private Map parseCustomMessage(String description) {
Map resultMap = [:]
if (description?.startsWith('temperature: ')) {
@@ -168,7 +169,7 @@ private Map parseCustomMessage(String description) {
private Map parseIasMessage(String description) {
List parsedMsg = description.split(' ')
String msgCode = parsedMsg[2]
Map resultMap = [:]
switch(msgCode) {
case '0x0020': // Closed/No Motion/Dry
@@ -201,7 +202,7 @@ private Map parseIasMessage(String description) {
}
return resultMap
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
@@ -214,11 +215,11 @@ def getTemperature(value) {
private Map getBatteryResult(rawValue) {
log.debug 'Battery'
def linkText = getLinkText(device)
def result = [
name: 'battery'
]
def volts = rawValue / 10
def descriptionText
if (rawValue == 0 || rawValue == 255) {}
@@ -229,7 +230,8 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
@@ -275,7 +277,7 @@ def refresh() {
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [

View File

@@ -205,7 +205,8 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}

View File

@@ -13,7 +13,7 @@
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
definition (name: "Tyco Door/Window Sensor", namespace: "smartthings", author: "SmartThings") {
capability "Battery"
@@ -21,28 +21,28 @@ metadata {
capability "Contact Sensor"
capability "Refresh"
capability "Temperature Measurement"
command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "Visonic", model: "MCT-340 SMA"
}
simulator {
}
preferences {
input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
}
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
}
valueTile("temperature", "device.temperature", inactiveLabel: false) {
state "temperature", label:'${currentValue}°',
backgroundColors:[
@@ -58,23 +58,23 @@ metadata {
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") {
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
}
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
main (["contact", "temperature"])
details(["contact","temperature","battery","refresh","configure"])
}
}
def parse(String description) {
log.debug "description: $description"
Map map = [:]
if (description?.startsWith('catchall:')) {
map = parseCatchAllMessage(description)
@@ -88,10 +88,10 @@ def parse(String description) {
else if (description?.startsWith('zone status')) {
map = parseIasMessage(description)
}
log.debug "Parse returned $map"
def result = map ? createEvent(map) : null
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
log.debug "enroll response: ${cmds}"
@@ -99,7 +99,7 @@ def parse(String description) {
}
return result
}
private Map parseCatchAllMessage(String description) {
Map resultMap = [:]
def cluster = zigbee.parse(description)
@@ -125,20 +125,20 @@ private Map parseCatchAllMessage(String description) {
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
// 0x07 is bind message
boolean ignoredMessage = cluster.profileId != 0x0104 ||
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
cluster.command == 0x07 ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
return !ignoredMessage
}
private Map parseReportAttributeMessage(String description) {
Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
log.debug "Desc Map: $descMap"
Map resultMap = [:]
if (descMap.cluster == "0402" && descMap.attrId == "0000") {
def value = getTemperature(descMap.value)
@@ -147,10 +147,10 @@ private Map parseReportAttributeMessage(String description) {
else if (descMap.cluster == "0001" && descMap.attrId == "0020") {
resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16))
}
return resultMap
}
private Map parseCustomMessage(String description) {
Map resultMap = [:]
if (description?.startsWith('temperature: ')) {
@@ -163,7 +163,7 @@ private Map parseCustomMessage(String description) {
private Map parseIasMessage(String description) {
List parsedMsg = description.split(' ')
String msgCode = parsedMsg[2]
Map resultMap = [:]
switch(msgCode) {
case '0x0020': // Closed/No Motion/Dry
@@ -196,7 +196,7 @@ private Map parseIasMessage(String description) {
}
return resultMap
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
@@ -209,11 +209,11 @@ def getTemperature(value) {
private Map getBatteryResult(rawValue) {
log.debug 'Battery'
def linkText = getLinkText(device)
def result = [
name: 'battery'
]
def volts = rawValue / 10
def descriptionText
if (volts > 3.5) {
@@ -223,7 +223,8 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
@@ -261,7 +262,7 @@ def refresh()
{
log.debug "Refreshing Temperature and Battery"
[
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20"
@@ -274,24 +275,24 @@ def configure() {
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
"delay 1000",
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global send-me-a-report 1 0x20 0x20 600 3600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
//"raw 0x500 {01 23 00 00 00}", "delay 200",
//"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zdo bind 0x${device.deviceNetworkId} 1 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}",
"delay 500"
]
return configCmds + enrollResponse() + refresh() // send refresh cmds as part of config
@@ -299,11 +300,11 @@ def configure() {
def enrollResponse() {
log.debug "Sending enroll response"
[
[
"raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1"
]
}
private hex(value) {

View File

@@ -28,7 +28,6 @@ metadata {
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+
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x72,0x5A,0x80,0x73,0x84,0x85,0x59,0x71,0x70,0x7A,0x98" // Vision door/window
}
// simulator metadata
@@ -36,6 +35,7 @@ metadata {
// status messages
status "open": "command: 2001, payload: FF"
status "closed": "command: 2001, payload: 00"
status "wake up": "command: 8407, payload: "
}
// UI tile definitions
@@ -83,12 +83,12 @@ def updated() {
cmds = [
command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()),
"delay 1200",
zwave.wakeUpV1.wakeUpNoMoreInformation()
zwave.wakeUpV1.wakeUpNoMoreInformation().format()
]
} else if (!state.lastbat) {
cmds = []
} else {
cmds = [zwave.wakeUpV1.wakeUpNoMoreInformation()]
cmds = [zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
response(cmds)
}
@@ -175,7 +175,7 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
if (!state.lastbat || now() - state.lastbat > 53*60*60*1000) {
cmds << command(zwave.batteryV1.batteryGet())
} else {
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation()
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
}
[event, response(cmds)]
}

View File

@@ -39,6 +39,7 @@ preferences {
page(name: "completionPage")
page(name: "numbersPage")
page(name: "controllerExplanationPage")
page(name: "unsupportedDevicesPage")
}
def rootPage() {
@@ -47,6 +48,9 @@ def rootPage() {
section("What to dim") {
input(name: "dimmers", type: "capability.switchLevel", title: "Dimmers", description: null, multiple: true, required: true, submitOnChange: true)
if (dimmers) {
if (dimmersContainUnsupportedDevices()) {
href(name: "toUnsupportedDevicesPage", page: "unsupportedDevicesPage", title: "Some of your selected dimmers don't seem to be supported", description: "Tap here to fix it", required: true)
}
href(name: "toNumbersPage", page: "numbersPage", title: "Duration & Direction", description: numbersPageHrefDescription(), state: "complete")
}
}
@@ -71,6 +75,31 @@ def rootPage() {
}
}
def unsupportedDevicesPage() {
def unsupportedDimmers = dimmers.findAll { !hasSetLevelCommand(it) }
dynamicPage(name: "unsupportedDevicesPage") {
if (unsupportedDimmers) {
section("These devices do not support the setLevel command") {
unsupportedDimmers.each {
paragraph deviceLabel(it)
}
}
section {
input(name: "dimmers", type: "capability.sensor", title: "Please remove the above devices from this list.", submitOnChange: true, multiple: true)
}
section {
paragraph "If you think there is a mistake here, please contact support."
}
} else {
section {
paragraph "You're all set. You can hit the back button, now. Thanks for cleaning up your settings :)"
}
}
}
}
def controllerExplanationPage() {
dynamicPage(name: "controllerExplanationPage", title: "How To Control Gentle Wake Up") {
@@ -528,14 +557,16 @@ def updateDimmers(percentComplete) {
} else {
def shouldChangeColors = (colorize && colorize != "false")
def canChangeColors = hasSetColorCommand(dimmer)
log.debug "Setting ${deviceLabel(dimmer)} to ${nextLevel}"
if (shouldChangeColors && canChangeColors) {
dimmer.setColor([hue: getHue(dimmer, nextLevel), saturation: 100, level: nextLevel])
} else {
if (shouldChangeColors && hasSetColorCommand(dimmer)) {
def hue = getHue(dimmer, nextLevel)
log.debug "Setting ${deviceLabel(dimmer)} level to ${nextLevel} and hue to ${hue}"
dimmer.setColor([hue: hue, saturation: 100, level: nextLevel])
} else if (hasSetLevelCommand(dimmer)) {
log.debug "Setting ${deviceLabel(dimmer)} level to ${nextLevel}"
dimmer.setLevel(nextLevel)
} else {
log.warn "${deviceLabel(dimmer)} does not have setColor or setLevel commands."
}
}
@@ -689,7 +720,7 @@ def completionPercentage() {
def now = new Date().getTime()
def timeElapsed = now - atomicState.start
def totalRunTime = totalRunTimeMillis()
def totalRunTime = totalRunTimeMillis() ?: 1
def percentComplete = timeElapsed / totalRunTime * 100
log.debug "percentComplete: ${percentComplete}"
@@ -817,24 +848,21 @@ private getRedHue(level) {
if (level >= 96) return 17
}
private dimmersContainUnsupportedDevices() {
def found = dimmers.find { hasSetLevelCommand(it) == false }
return found != null
}
private hasSetLevelCommand(device) {
def isDimmer = false
device.supportedCommands.each {
if (it.name.contains("setLevel")) {
isDimmer = true
}
}
return isDimmer
return hasCommand(device, "setLevel")
}
private hasSetColorCommand(device) {
def hasColor = false
device.supportedCommands.each {
if (it.name.contains("setColor")) {
hasColor = true
}
}
return hasColor
return hasCommand(device, "setColor")
}
private hasCommand(device, String command) {
return (device.supportedCommands.find { it.name == command } != null)
}
private dimmersWithSetColorCommand() {
@@ -1073,4 +1101,4 @@ def hasStartLevel() {
def hasEndLevel() {
return (endLevel != null && endLevel != "")
}
}

View File

@@ -689,7 +689,7 @@ def parse(childDevice, description) {
log.warn "Parsing Body failed - trying again..."
poll()
}
if (body instanceof java.util.HashMap) {
if (body instanceof java.util.Map) {
//poll response
def bulbs = getChildDevices()
for (bulb in body) {
@@ -830,22 +830,22 @@ def setColorTemperature(childDevice, huesettings) {
def setColor(childDevice, huesettings) {
log.debug "Executing 'setColor($huesettings)'"
def value = [:]
def hue = null
def sat = null
def xy = null
if (huesettings.hex != null) {
value.xy = getHextoXY(huesettings.hex)
} else {
if (huesettings.hue != null)
value.hue = Math.min(Math.round(huesettings.hue * 65535 / 100), 65535)
if (huesettings.saturation != null)
if (huesettings.saturation != null)
value.sat = Math.min(Math.round(huesettings.saturation * 255 / 100), 255)
}
// Default behavior is to turn light on
// Default behavior is to turn light on
value.on = true
if (huesettings.level != null) {
@@ -853,7 +853,7 @@ def setColor(childDevice, huesettings) {
value.on = false
else if (huesettings.level == 1)
value.bri = 1
else
else
value.bri = Math.min(Math.round(huesettings.level * 255 / 100), 255)
}
value.alert = huesettings.alert ? huesettings.alert : "none"

View File

@@ -688,7 +688,7 @@ def validateCommand(device, command) {
def capabilityCommands = getDeviceCapabilityCommands(device.capabilities)
def currentDeviceCapability = getCapabilityName(device)
if (currentDeviceCapability != "" && capabilityCommands[currentDeviceCapability]) {
return command in capabilityCommands[currentDeviceCapability] ? true : false
return (command in capabilityCommands[currentDeviceCapability] || (currentDeviceCapability == "Switch" && command == "setLevel" && device.hasCommand("setLevel"))) ? true : false
} else {
// Handling other device types here, which don't accept commands
httpError(400, "Bad request.")
@@ -823,8 +823,8 @@ def deviceHandler(evt) {
}
def sendToHarmony(evt, String callbackUrl) {
def callback = new URI(callbackUrl)
if(isIP(callback.host)){
def callback = new URI(callbackUrl)
if (callback.port != -1) {
def host = callback.port != -1 ? "${callback.host}:${callback.port}" : callback.host
def path = callback.query ? "${callback.path}?${callback.query}".toString() : callback.path
sendHubCommand(new physicalgraph.device.HubAction(
@@ -852,25 +852,6 @@ def sendToHarmony(evt, String callbackUrl) {
}
}
public static boolean isIP(String str) {
try {
String[] parts = str.split("\\.");
if (parts.length != 4) return false;
for (int i = 0; i < 4; ++i) {
int p
try {
p = Integer.parseInt(parts[i]);
} catch (Exception e) {
return false;
}
if (p > 255 || p < 0) return false;
}
return true;
} catch (Exception e) {
return false;
}
}
def listHubs() {
location.hubs?.findAll { it.type.toString() == "PHYSICAL" }?.collect { hubItem(it) }
}