mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-10 05:11:51 +00:00
Compare commits
62 Commits
MSA-1864-1
...
PROD_2017.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
264e822c9f | ||
|
|
e4642e300f | ||
|
|
b4eed54ddd | ||
|
|
b2b03604a7 | ||
|
|
2b05817843 | ||
|
|
1f6a27f381 | ||
|
|
157bc3ef56 | ||
|
|
096f4f767f | ||
|
|
c15a21b8bf | ||
|
|
daefec9d1f | ||
|
|
a28c90e492 | ||
|
|
664b300b37 | ||
|
|
2b6d978d13 | ||
|
|
8197097e1d | ||
|
|
4644362465 | ||
|
|
2c25e293c0 | ||
|
|
36fe6428ab | ||
|
|
2bc44e0205 | ||
|
|
24d079db7c | ||
|
|
283ed425d8 | ||
|
|
1545707ae3 | ||
|
|
2fd8cf1416 | ||
|
|
7f3a99d889 | ||
|
|
a397fe9fc3 | ||
|
|
f83500fbf8 | ||
|
|
a297e79b0e | ||
|
|
69d52093dc | ||
|
|
fda743a801 | ||
|
|
f7a5ea4820 | ||
|
|
d51ec9e518 | ||
|
|
fe4a5239c7 | ||
|
|
ae41b4adbe | ||
|
|
bdcaf175f0 | ||
|
|
ba10869dd5 | ||
|
|
6f411e1a3e | ||
|
|
4cc41d9d9b | ||
|
|
66875170f4 | ||
|
|
9e80a188df | ||
|
|
ec781b18be | ||
|
|
43bedd41a8 | ||
|
|
f75e8a6b2d | ||
|
|
ce10bcf2cd | ||
|
|
0c8de4402b | ||
|
|
a112d4b00e | ||
|
|
515fab9fa4 | ||
|
|
100e696d02 | ||
|
|
3e988ce657 | ||
|
|
fe887121d3 | ||
|
|
7375abf9c0 | ||
|
|
00224c2d0b | ||
|
|
e985f38cf4 | ||
|
|
a79e0f70fd | ||
|
|
f05daf2f34 | ||
|
|
f26b9ce6b2 | ||
|
|
ac4c353287 | ||
|
|
ed40ca7017 | ||
|
|
7aa8be4322 | ||
|
|
23a0b26cb9 | ||
|
|
9f944df598 | ||
|
|
6fae023f7a | ||
|
|
a06dba0b90 | ||
|
|
ef8611d2ea |
@@ -14,13 +14,13 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Fibaro Door/Window Sensor ZW5 with Temperature", namespace: "fibargroup", author: "Fibar Group S.A.") {
|
||||
definition (name: "Fibaro Door/Window Sensor ZW5 with Temperature", namespace: "fibargroup", author: "Fibar Group S.A.", ocfDeviceType: "x.com.st.d.sensor.contact") {
|
||||
capability "Battery"
|
||||
capability "Contact Sensor"
|
||||
capability "Sensor"
|
||||
capability "Configuration"
|
||||
capability "Tamper Alert"
|
||||
|
||||
|
||||
capability "Temperature Measurement"
|
||||
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x85, 0x59, 0x22, 0x20, 0x80, 0x70, 0x56, 0x5A, 0x7A, 0x72, 0x8E, 0x71, 0x73, 0x98, 0x2B, 0x9C, 0x30, 0x31, 0x86", outClusters: ""
|
||||
@@ -28,26 +28,26 @@ metadata {
|
||||
}
|
||||
|
||||
simulator {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"FGK", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app
|
||||
tileAttribute("device.contact", key:"PRIMARY_CONTROL") {
|
||||
attributeState("open", icon:"st.contact.contact.open", backgroundColor:"#e86d13")
|
||||
attributeState("closed", icon:"st.contact.contact.closed", backgroundColor:"#00a0dc")
|
||||
}
|
||||
|
||||
|
||||
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
|
||||
attributeState("active", label:'tamper active', backgroundColor:"#53a7c0")
|
||||
attributeState("inactive", label:'tamper inactive', backgroundColor:"#ffffff")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, width: 2, height: 2, decoration: "flat") {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
}
|
||||
|
||||
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
|
||||
state "temperature", label:'${currentValue}°',
|
||||
backgroundColors:[
|
||||
@@ -60,7 +60,7 @@ metadata {
|
||||
[value: 96, color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
main "FGK"
|
||||
details(["FGK","battery", "temperature"])
|
||||
}
|
||||
@@ -68,9 +68,9 @@ metadata {
|
||||
|
||||
// parse events into attributes
|
||||
def parse(String description) {
|
||||
log.debug "Parsing '${description}'"
|
||||
log.debug "Parsing '${description}'"
|
||||
def result = []
|
||||
|
||||
|
||||
if (description.startsWith("Err 106")) {
|
||||
if (state.sec) {
|
||||
result = createEvent(descriptionText:description, displayed:false)
|
||||
@@ -87,7 +87,7 @@ def parse(String description) {
|
||||
return null
|
||||
} else {
|
||||
def cmd = zwave.parse(description, [0x31: 5, 0x56: 1, 0x71: 3, 0x72: 2, 0x80: 1, 0x84: 2, 0x85: 2, 0x86: 1, 0x98: 1])
|
||||
|
||||
|
||||
if (cmd) {
|
||||
log.debug "Parsed '${cmd}'"
|
||||
zwaveEvent(cmd)
|
||||
@@ -125,13 +125,13 @@ def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cm
|
||||
//(parameter 20 was not changed before device's re-inclusion)
|
||||
def map = [:]
|
||||
if (cmd.notificationType == 6) {
|
||||
switch (cmd.event) {
|
||||
switch (cmd.event) {
|
||||
case 22:
|
||||
map.name = "contact"
|
||||
map.value = "open"
|
||||
map.descriptionText = "${device.displayName}: is open"
|
||||
break
|
||||
|
||||
|
||||
case 23:
|
||||
map.name = "contact"
|
||||
map.value = "closed"
|
||||
@@ -145,7 +145,7 @@ def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cm
|
||||
map.value = "inactive"
|
||||
map.descriptionText = "${device.displayName}: tamper alarm has been deactivated"
|
||||
break
|
||||
|
||||
|
||||
case 3:
|
||||
map.name = "tamper"
|
||||
map.value = "active"
|
||||
@@ -153,7 +153,7 @@ def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cm
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
|
||||
def event = createEvent(descriptionText: "${device.displayName} woke up", displayed: false)
|
||||
def cmds = []
|
||||
cmds << encap(zwave.batteryV1.batteryGet())
|
||||
@@ -177,32 +177,32 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
|
||||
[event, response(cmds)]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
|
||||
log.debug "manufacturerId: ${cmd.manufacturerId}"
|
||||
log.debug "manufacturerName: ${cmd.manufacturerName}"
|
||||
log.debug "productId: ${cmd.productId}"
|
||||
log.debug "productTypeId: ${cmd.productTypeId}"
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
|
||||
log.debug "deviceIdData: ${cmd.deviceIdData}"
|
||||
log.debug "deviceIdDataFormat: ${cmd.deviceIdDataFormat}"
|
||||
log.debug "deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}"
|
||||
log.debug "deviceIdType: ${cmd.deviceIdType}"
|
||||
|
||||
|
||||
if (cmd.deviceIdType == 1 && cmd.deviceIdDataFormat == 1) {//serial number in binary format
|
||||
String serialNumber = "h'"
|
||||
|
||||
|
||||
cmd.deviceIdData.each{ data ->
|
||||
serialNumber += "${String.format("%02X", data)}"
|
||||
}
|
||||
|
||||
|
||||
updateDataValue("serialNumber", serialNumber)
|
||||
log.debug "${device.displayName} - serial number: ${serialNumber}"
|
||||
}
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
|
||||
updateDataValue("version", "${cmd.applicationVersion}.${cmd.applicationSubVersion}")
|
||||
log.debug "applicationVersion: ${cmd.applicationVersion}"
|
||||
log.debug "applicationSubVersion: ${cmd.applicationSubVersion}"
|
||||
@@ -221,7 +221,7 @@ def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelR
|
||||
map.name = "temperature"
|
||||
map.displayed = true
|
||||
}
|
||||
|
||||
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
@@ -231,9 +231,9 @@ def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLoca
|
||||
|
||||
def configure() {
|
||||
log.debug "Executing 'configure'"
|
||||
|
||||
|
||||
def cmds = []
|
||||
|
||||
|
||||
cmds += zwave.wakeUpV2.wakeUpIntervalSet(seconds:21600, nodeid: zwaveHubNodeId)//FGK's default wake up interval
|
||||
cmds += zwave.manufacturerSpecificV2.manufacturerSpecificGet()
|
||||
cmds += zwave.manufacturerSpecificV2.deviceSpecificGet()
|
||||
@@ -242,7 +242,7 @@ def configure() {
|
||||
cmds += zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0)
|
||||
cmds += zwave.associationV2.associationSet(groupingIdentifier:1, nodeId: [zwaveHubNodeId])
|
||||
cmds += zwave.wakeUpV2.wakeUpNoMoreInformation()
|
||||
|
||||
|
||||
encapSequence(cmds, 500)
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ private encapSequence(commands, delay=200) {
|
||||
|
||||
private encap(physicalgraph.zwave.Command cmd) {
|
||||
def secureClasses = [0x20, 0x2B, 0x30, 0x5A, 0x70, 0x71, 0x84, 0x85, 0x8E, 0x9C]
|
||||
|
||||
|
||||
//todo: check if secure inclusion was successful
|
||||
//if not do not send security-encapsulated command
|
||||
if (secureClasses.find{ it == cmd.commandClassId }) {
|
||||
@@ -269,4 +269,4 @@ private encap(physicalgraph.zwave.Command cmd) {
|
||||
} else {
|
||||
crc16(cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.st-ignore
|
||||
README.md
|
||||
@@ -0,0 +1,41 @@
|
||||
# Fibaro Door Window Sensor ZW5
|
||||
|
||||
Cloud Execution
|
||||
|
||||
Works with:
|
||||
|
||||
* [Fibaro Door/Window Sensor ZW5](https://www.smartthings.com/works-with-smartthings/sensors/fibaro-doorwindow-sensor)
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Capabilities](#capabilities)
|
||||
* [Health](#device-health)
|
||||
* [Battery](#battery-specification)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Capabilities
|
||||
|
||||
* **Battery** - defines device uses a battery
|
||||
* **Contact Sensor** - can detect contact (possible values: open,closed)
|
||||
* **Sensor** - detects sensor events
|
||||
* **Tamper Alert** - detects tampers
|
||||
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
|
||||
* **Health Check** - indicates ability to get device health notifications
|
||||
|
||||
## Device Health
|
||||
|
||||
Fibaro Door/Window Sensor ZW5 is a Z-wave sleepy device and wakes up every 4 hours.
|
||||
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*4*60 + 2)mins = 482 mins.
|
||||
|
||||
* __482min__ checkInterval
|
||||
|
||||
## Battery Specification
|
||||
|
||||
One 1/2AA 3.6V battery is required.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
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.
|
||||
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
|
||||
* [Fibaro Door/Window Sensor ZW5 Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204075194-Fibaro-Door-Window-Sensor)
|
||||
@@ -14,37 +14,38 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Fibaro Door/Window Sensor ZW5", namespace: "fibargroup", author: "Fibar Group S.A.") {
|
||||
definition (name: "Fibaro Door/Window Sensor ZW5", namespace: "fibargroup", author: "Fibar Group S.A.", ocfDeviceType: "x.com.st.d.sensor.contact") {
|
||||
capability "Battery"
|
||||
capability "Contact Sensor"
|
||||
capability "Sensor"
|
||||
capability "Configuration"
|
||||
capability "Tamper Alert"
|
||||
capability "Health Check"
|
||||
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x85, 0x59, 0x22, 0x20, 0x80, 0x70, 0x56, 0x5A, 0x7A, 0x72, 0x8E, 0x71, 0x73, 0x98, 0x2B, 0x9C, 0x30, 0x86, 0x84", outClusters: ""
|
||||
}
|
||||
|
||||
simulator {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"FGK", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app
|
||||
tileAttribute("device.contact", key:"PRIMARY_CONTROL") {
|
||||
attributeState("open", icon:"st.contact.contact.open", backgroundColor:"#e86d13")
|
||||
attributeState("closed", icon:"st.contact.contact.closed", backgroundColor:"#00a0dc")
|
||||
}
|
||||
|
||||
|
||||
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
|
||||
attributeState("active", label:'tamper active', backgroundColor:"#53a7c0")
|
||||
attributeState("inactive", label:'tamper inactive', backgroundColor:"#ffffff")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, width: 2, height: 2, decoration: "flat") {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
}
|
||||
|
||||
|
||||
main "FGK"
|
||||
details(["FGK","battery"])
|
||||
}
|
||||
@@ -52,9 +53,9 @@ metadata {
|
||||
|
||||
// parse events into attributes
|
||||
def parse(String description) {
|
||||
log.debug "Parsing '${description}'"
|
||||
log.debug "Parsing '${description}'"
|
||||
def result = []
|
||||
|
||||
|
||||
if (description.startsWith("Err 106")) {
|
||||
if (state.sec) {
|
||||
result = createEvent(descriptionText:description, displayed:false)
|
||||
@@ -71,7 +72,7 @@ def parse(String description) {
|
||||
return null
|
||||
} else {
|
||||
def cmd = zwave.parse(description, [0x56: 1, 0x71: 3, 0x72: 2, 0x80: 1, 0x84: 2, 0x85: 2, 0x86: 1, 0x98: 1])
|
||||
|
||||
|
||||
if (cmd) {
|
||||
log.debug "Parsed '${cmd}'"
|
||||
zwaveEvent(cmd)
|
||||
@@ -109,13 +110,13 @@ def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cm
|
||||
//(parameter 20 was not changed before device's re-inclusion)
|
||||
def map = [:]
|
||||
if (cmd.notificationType == 6) {
|
||||
switch (cmd.event) {
|
||||
switch (cmd.event) {
|
||||
case 22:
|
||||
map.name = "contact"
|
||||
map.value = "open"
|
||||
map.descriptionText = "${device.displayName}: is open"
|
||||
break
|
||||
|
||||
|
||||
case 23:
|
||||
map.name = "contact"
|
||||
map.value = "closed"
|
||||
@@ -129,7 +130,7 @@ def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cm
|
||||
map.value = "inactive"
|
||||
map.descriptionText = "${device.displayName}: tamper alarm has been deactivated"
|
||||
break
|
||||
|
||||
|
||||
case 3:
|
||||
map.name = "tamper"
|
||||
map.value = "active"
|
||||
@@ -137,7 +138,7 @@ def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cm
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
@@ -150,7 +151,7 @@ def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
|
||||
def event = createEvent(descriptionText: "${device.displayName} woke up", displayed: false)
|
||||
def cmds = []
|
||||
cmds << encap(zwave.batteryV1.batteryGet())
|
||||
@@ -159,32 +160,32 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) {
|
||||
[event, response(cmds)]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
|
||||
log.debug "manufacturerId: ${cmd.manufacturerId}"
|
||||
log.debug "manufacturerName: ${cmd.manufacturerName}"
|
||||
log.debug "productId: ${cmd.productId}"
|
||||
log.debug "productTypeId: ${cmd.productTypeId}"
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
|
||||
log.debug "deviceIdData: ${cmd.deviceIdData}"
|
||||
log.debug "deviceIdDataFormat: ${cmd.deviceIdDataFormat}"
|
||||
log.debug "deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}"
|
||||
log.debug "deviceIdType: ${cmd.deviceIdType}"
|
||||
|
||||
|
||||
if (cmd.deviceIdType == 1 && cmd.deviceIdDataFormat == 1) {//serial number in binary format
|
||||
String serialNumber = "h'"
|
||||
|
||||
|
||||
cmd.deviceIdData.each{ data ->
|
||||
serialNumber += "${String.format("%02X", data)}"
|
||||
}
|
||||
|
||||
|
||||
updateDataValue("serialNumber", serialNumber)
|
||||
log.debug "${device.displayName} - serial number: ${serialNumber}"
|
||||
}
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
|
||||
updateDataValue("version", "${cmd.applicationVersion}.${cmd.applicationSubVersion}")
|
||||
log.debug "applicationVersion: ${cmd.applicationVersion}"
|
||||
log.debug "applicationSubVersion: ${cmd.applicationSubVersion}"
|
||||
@@ -199,9 +200,11 @@ def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLoca
|
||||
|
||||
def configure() {
|
||||
log.debug "Executing 'configure'"
|
||||
|
||||
// Device wakes up every 4 hours, this interval allows us to miss one wakeup notification before marking offline
|
||||
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
def cmds = []
|
||||
|
||||
|
||||
cmds += zwave.wakeUpV2.wakeUpIntervalSet(seconds:21600, nodeid: zwaveHubNodeId)//FGK's default wake up interval
|
||||
cmds += zwave.manufacturerSpecificV2.manufacturerSpecificGet()
|
||||
cmds += zwave.manufacturerSpecificV2.deviceSpecificGet()
|
||||
@@ -209,7 +212,7 @@ def configure() {
|
||||
cmds += zwave.batteryV1.batteryGet()
|
||||
cmds += zwave.associationV2.associationSet(groupingIdentifier:1, nodeId: [zwaveHubNodeId])
|
||||
cmds += zwave.wakeUpV2.wakeUpNoMoreInformation()
|
||||
|
||||
|
||||
encapSequence(cmds, 500)
|
||||
}
|
||||
|
||||
@@ -228,7 +231,7 @@ private encapSequence(commands, delay=200) {
|
||||
|
||||
private encap(physicalgraph.zwave.Command cmd) {
|
||||
def secureClasses = [0x20, 0x2B, 0x30, 0x5A, 0x70, 0x71, 0x84, 0x85, 0x8E, 0x9C]
|
||||
|
||||
|
||||
//todo: check if secure inclusion was successful
|
||||
//if not do not send security-encapsulated command
|
||||
if (secureClasses.find{ it == cmd.commandClassId }) {
|
||||
@@ -236,4 +239,4 @@ private encap(physicalgraph.zwave.Command cmd) {
|
||||
} else {
|
||||
crc16(cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Fibaro Flood Sensor ZW5", namespace: "fibargroup", author: "Fibar Group S.A.") {
|
||||
definition (name: "Fibaro Flood Sensor ZW5", namespace: "fibargroup", author: "Fibar Group S.A.", ocfDeviceType: "x.com.st.d.sensor.moisture") {
|
||||
capability "Battery"
|
||||
capability "Configuration"
|
||||
capability "Sensor"
|
||||
@@ -34,16 +34,16 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"FGFS", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app
|
||||
tileAttribute("device.water", key:"PRIMARY_CONTROL") {
|
||||
attributeState("dry", icon:"st.alarm.water.dry", backgroundColor:"#00a0dc")
|
||||
attributeState("wet", icon:"st.alarm.water.wet", backgroundColor:"#e86d13")
|
||||
attributeState("dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff")
|
||||
attributeState("wet", icon:"st.alarm.water.wet", backgroundColor:"#00a0dc")
|
||||
}
|
||||
|
||||
|
||||
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
|
||||
attributeState("active", label:'tamper active', backgroundColor:"#00a0dc")
|
||||
attributeState("inactive", label:'tamper inactive', backgroundColor:"#cccccc")
|
||||
attributeState("active", label:'tamper active', backgroundColor:"#cccccc")
|
||||
attributeState("inactive", label:'tamper inactive', backgroundColor:"#00A0DC")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
|
||||
state "temperature", label:'${currentValue}°',
|
||||
backgroundColors:[
|
||||
@@ -130,14 +130,14 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd)
|
||||
[event, response(cmds)]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
|
||||
log.debug "manufacturerId: ${cmd.manufacturerId}"
|
||||
log.debug "manufacturerName: ${cmd.manufacturerName}"
|
||||
log.debug "productId: ${cmd.productId}"
|
||||
log.debug "productTypeId: ${cmd.productTypeId}"
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
|
||||
log.debug "deviceIdData: ${cmd.deviceIdData}"
|
||||
log.debug "deviceIdDataFormat: ${cmd.deviceIdDataFormat}"
|
||||
log.debug "deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Fibaro Motion Sensor ZW5", namespace: "fibargroup", author: "Fibar Group S.A.") {
|
||||
definition (name: "Fibaro Motion Sensor ZW5", namespace: "fibargroup", author: "Fibar Group S.A.", ocfDeviceType: "x.com.st.d.sensor.motion") {
|
||||
capability "Battery"
|
||||
capability "Configuration"
|
||||
capability "Illuminance Measurement"
|
||||
@@ -23,27 +23,27 @@ metadata {
|
||||
capability "Tamper Alert"
|
||||
capability "Temperature Measurement"
|
||||
capability "Health Check"
|
||||
|
||||
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x20, 0x86, 0x72, 0x5A, 0x59, 0x85, 0x73, 0x84, 0x80, 0x71, 0x56, 0x70, 0x31, 0x8E, 0x22, 0x30, 0x9C, 0x98, 0x7A", outClusters: ""
|
||||
}
|
||||
|
||||
|
||||
simulator {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"FGMS", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app
|
||||
tileAttribute("device.motion", key:"PRIMARY_CONTROL") {
|
||||
attributeState("inactive", label:"no motion", icon:"st.motion.motion.inactive", backgroundColor:"#79b821")
|
||||
attributeState("active", label:"motion", icon:"st.motion.motion.active", backgroundColor:"#ffa81e")
|
||||
attributeState("active", label:"motion", icon:"st.motion.motion.active", backgroundColor:"#ffa81e")
|
||||
}
|
||||
|
||||
|
||||
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
|
||||
attributeState("active", label:'tamper active', backgroundColor:"#00a0dc")
|
||||
attributeState("inactive", label:'tamper inactive', backgroundColor:"#cccccc")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
|
||||
state "temperature", label:'${currentValue}°',
|
||||
backgroundColors:[
|
||||
@@ -56,15 +56,15 @@ metadata {
|
||||
[value: 96, color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
valueTile("illuminance", "device.illuminance", inactiveLabel: false, width: 2, height: 2) {
|
||||
state "luminosity", label:'${currentValue} ${unit}', unit:"lux"
|
||||
}
|
||||
|
||||
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, width: 2, height: 2, decoration: "flat") {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
}
|
||||
|
||||
|
||||
main "FGMS"
|
||||
details(["FGMS","battery","temperature","illuminance"])
|
||||
}
|
||||
@@ -72,9 +72,9 @@ metadata {
|
||||
|
||||
// parse events into attributes
|
||||
def parse(String description) {
|
||||
log.debug "Parsing '${description}'"
|
||||
log.debug "Parsing '${description}'"
|
||||
def result = []
|
||||
|
||||
|
||||
if (description.startsWith("Err 106")) {
|
||||
if (state.sec) {
|
||||
result = createEvent(descriptionText:description, displayed:false)
|
||||
@@ -91,7 +91,7 @@ def parse(String description) {
|
||||
return null
|
||||
} else {
|
||||
def cmd = zwave.parse(description, [0x31: 5, 0x56: 1, 0x71: 3, 0x72: 2, 0x80: 1, 0x84: 2, 0x85: 2, 0x86: 1, 0x98: 1])
|
||||
|
||||
|
||||
if (cmd) {
|
||||
log.debug "Parsed '${cmd}'"
|
||||
zwaveEvent(cmd)
|
||||
@@ -159,13 +159,13 @@ def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cm
|
||||
map.descriptionText = "${device.displayName}: motion has stopped"
|
||||
}
|
||||
break
|
||||
|
||||
|
||||
case 3:
|
||||
map.name = "tamper"
|
||||
map.value = "active"
|
||||
map.descriptionText = "${device.displayName}: tamper alarm activated"
|
||||
break
|
||||
|
||||
|
||||
case 8:
|
||||
map.name = "motion"
|
||||
map.value = "active"
|
||||
@@ -173,7 +173,7 @@ def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cm
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
@@ -194,39 +194,39 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd)
|
||||
cmds << "delay 500"
|
||||
cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0))
|
||||
cmds << "delay 500"
|
||||
cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 3, scale: 1))
|
||||
cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 3, scale: 1))
|
||||
cmds << "delay 1200"
|
||||
cmds << encap(zwave.wakeUpV1.wakeUpNoMoreInformation())
|
||||
[event, response(cmds)]
|
||||
|
||||
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
|
||||
log.debug "manufacturerId: ${cmd.manufacturerId}"
|
||||
log.debug "manufacturerName: ${cmd.manufacturerName}"
|
||||
log.debug "productId: ${cmd.productId}"
|
||||
log.debug "productTypeId: ${cmd.productTypeId}"
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
|
||||
log.debug "deviceIdData: ${cmd.deviceIdData}"
|
||||
log.debug "deviceIdDataFormat: ${cmd.deviceIdDataFormat}"
|
||||
log.debug "deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}"
|
||||
log.debug "deviceIdType: ${cmd.deviceIdType}"
|
||||
|
||||
|
||||
if (cmd.deviceIdType == 1 && cmd.deviceIdDataFormat == 1) {//serial number in binary format
|
||||
String serialNumber = "h'"
|
||||
|
||||
|
||||
cmd.deviceIdData.each{ data ->
|
||||
serialNumber += "${String.format("%02X", data)}"
|
||||
}
|
||||
|
||||
|
||||
updateDataValue("serialNumber", serialNumber)
|
||||
log.debug "${device.displayName} - serial number: ${serialNumber}"
|
||||
}
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
|
||||
updateDataValue("version", "${cmd.applicationVersion}.${cmd.applicationSubVersion}")
|
||||
log.debug "applicationVersion: ${cmd.applicationVersion}"
|
||||
log.debug "applicationSubVersion: ${cmd.applicationSubVersion}"
|
||||
@@ -245,7 +245,7 @@ def configure() {
|
||||
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
def cmds = []
|
||||
|
||||
|
||||
cmds += zwave.wakeUpV2.wakeUpIntervalSet(seconds: 7200, nodeid: zwaveHubNodeId)//FGMS' default wake up interval
|
||||
cmds += zwave.manufacturerSpecificV2.manufacturerSpecificGet()
|
||||
cmds += zwave.manufacturerSpecificV2.deviceSpecificGet()
|
||||
@@ -255,7 +255,7 @@ def configure() {
|
||||
cmds += zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0)
|
||||
cmds += zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 3, scale: 1)
|
||||
cmds += zwave.wakeUpV2.wakeUpNoMoreInformation()
|
||||
|
||||
|
||||
encapSequence(cmds, 500)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ metadata {
|
||||
command "clearObstruction"
|
||||
|
||||
fingerprint endpoint: "1", profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0006,0008,0020,0402,0403,0B05,FC01,FC02", outClusters: "0019"
|
||||
fingerprint endpoint: "1", profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0006,0008,0020,0402,0403,0B05,FC01,FC02", outClusters: "0019", manufacturer: "Keen Home Inc", model: "SV01-410-DV-1.0", deviceJoinName: "Keen Home Smart Vent"
|
||||
}
|
||||
|
||||
// simulator metadata
|
||||
|
||||
@@ -100,6 +100,11 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def installed(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
@@ -58,6 +58,11 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "Cree Bulb", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Cree Bulb", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
|
||||
capability "Actuator"
|
||||
capability "Configuration"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Dimmer Switch", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Dimmer Switch", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.switch") {
|
||||
capability "Switch Level"
|
||||
capability "Actuator"
|
||||
capability "Indicator"
|
||||
@@ -84,6 +84,11 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
@@ -32,7 +32,7 @@ metadata {
|
||||
command "switchMode"
|
||||
command "switchFanMode"
|
||||
|
||||
attribute "thermostatSetpoint", "number"
|
||||
attribute "displayThermostatSetpoint", "string" // Added to be able to show "Auto"/"Off" keeping attribute thermostatSetpoint a number
|
||||
attribute "thermostatStatus", "string"
|
||||
attribute "maxHeatingSetpoint", "number"
|
||||
attribute "minHeatingSetpoint", "number"
|
||||
@@ -43,8 +43,8 @@ metadata {
|
||||
}
|
||||
|
||||
tiles {
|
||||
valueTile("temperature", "device.temperature", width: 2, height: 2) {
|
||||
state("temperature", label:'${currentValue}°', unit:"F",
|
||||
standardTile("temperature", "device.temperature", width: 2, height: 2, decoration: "flat") {
|
||||
state("temperature", label:'${currentValue}°', unit:"F", icon: "st.thermostat.ac.air-conditioning",
|
||||
backgroundColors:[
|
||||
// Celsius
|
||||
[value: 0, color: "#153591"],
|
||||
@@ -70,7 +70,7 @@ metadata {
|
||||
state "heat", action:"switchMode", nextState: "updating", icon: "st.thermostat.heat"
|
||||
state "cool", action:"switchMode", nextState: "updating", icon: "st.thermostat.cool"
|
||||
state "auto", action:"switchMode", nextState: "updating", icon: "st.thermostat.auto"
|
||||
state "auxHeatOnly", action:"switchMode", icon: "st.thermostat.emergency-heat"
|
||||
state "emergency heat", action:"switchMode", icon: "st.thermostat.emergency-heat" // emergency heat = auxHeatOnly
|
||||
state "updating", label:"Working", icon: "st.secondary.secondary"
|
||||
}
|
||||
standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") {
|
||||
@@ -81,8 +81,8 @@ metadata {
|
||||
standardTile("upButtonControl", "device.thermostatSetpoint", inactiveLabel: false, decoration: "flat") {
|
||||
state "setpoint", action:"raiseSetpoint", icon:"st.thermostat.thermostat-up"
|
||||
}
|
||||
valueTile("thermostatSetpoint", "device.thermostatSetpoint", width: 1, height: 1, decoration: "flat") {
|
||||
state "thermostatSetpoint", label:'${currentValue}'
|
||||
valueTile("displayThermostatSetpoint", "device.displayThermostatSetpoint", width: 1, height: 1, decoration: "flat") {
|
||||
state "displayThermostatSetpoint", label:'${currentValue}'
|
||||
}
|
||||
valueTile("currentStatus", "device.thermostatStatus", height: 1, width: 2, decoration: "flat") {
|
||||
state "thermostatStatus", label:'${currentValue}', backgroundColor:"#ffffff"
|
||||
@@ -113,7 +113,7 @@ metadata {
|
||||
state "humidity", label:'${currentValue}%'
|
||||
}
|
||||
main "temperature"
|
||||
details(["temperature", "upButtonControl", "thermostatSetpoint", "currentStatus", "downButtonControl", "mode", "fanMode","humidity", "resumeProgram", "refresh"])
|
||||
details(["temperature", "upButtonControl", "displayThermostatSetpoint", "currentStatus", "downButtonControl", "mode", "fanMode","humidity", "resumeProgram", "refresh"])
|
||||
}
|
||||
|
||||
preferences {
|
||||
@@ -185,6 +185,11 @@ def generateEvent(Map results) {
|
||||
isChange = isStateChange(device, name, value.toString())
|
||||
event['isStateChange'] = isChange
|
||||
event['displayed'] = false
|
||||
} else if (name == "thermostatMode") {
|
||||
def mode = value.toString()
|
||||
mode = (mode == "auxHeatOnly") ? "emergency heat" : mode
|
||||
isChange = isStateChange(device, name, mode)
|
||||
event << [value: mode, isStateChange: isChange, displayed: isDisplayed]
|
||||
} else {
|
||||
isChange = isStateChange(device, name, value.toString())
|
||||
isDisplayed = isChange
|
||||
@@ -452,10 +457,10 @@ def emergencyHeat() {
|
||||
}
|
||||
|
||||
def auxHeatOnly() {
|
||||
log.debug "auxHeatOnly"
|
||||
log.debug "auxHeatOnly = emergency heat"
|
||||
def deviceId = device.deviceNetworkId.split(/\./).last()
|
||||
if (parent.setMode ("auxHeatOnly", deviceId))
|
||||
generateModeEvent("auxHeatOnly")
|
||||
generateModeEvent("emergency heat") // emergency heat = auxHeatOnly
|
||||
else {
|
||||
log.debug "Error setting new mode."
|
||||
def currentMode = device.currentState("thermostatMode")?.value
|
||||
@@ -574,17 +579,23 @@ def generateSetpointEvent() {
|
||||
sendEvent("name":"heatingSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
|
||||
sendEvent("name":"coolingSetpoint", "value":coolingSetpoint, "unit":location.temperatureScale)
|
||||
|
||||
def averageSetpoint = roundC((heatingSetpoint + coolingSetpoint) / 2)
|
||||
if (mode == "heat") {
|
||||
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
|
||||
sendEvent("name":"displayThermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale, displayed: false)
|
||||
}
|
||||
else if (mode == "cool") {
|
||||
sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint, "unit":location.temperatureScale)
|
||||
sendEvent("name":"displayThermostatSetpoint", "value":coolingSetpoint, "unit":location.temperatureScale, displayed: false)
|
||||
} else if (mode == "auto") {
|
||||
sendEvent("name":"thermostatSetpoint", "value":"Auto")
|
||||
sendEvent("name":"thermostatSetpoint", "value":averageSetpoint, "unit":location.temperatureScale)
|
||||
sendEvent("name":"displayThermostatSetpoint", "value":"Auto", displayed: false)
|
||||
} else if (mode == "off") {
|
||||
sendEvent("name":"thermostatSetpoint", "value":"Off")
|
||||
} else if (mode == "auxHeatOnly") {
|
||||
sendEvent("name":"thermostatSetpoint", "value":averageSetpoint, "unit":location.temperatureScale)
|
||||
sendEvent("name":"displayThermostatSetpoint", "value":"Off", displayed: false)
|
||||
} else if (mode == "emergency heat") { // emergency heat = auxHeatOnly
|
||||
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
|
||||
sendEvent("name":"displayThermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale, displayed: false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -621,13 +632,14 @@ void raiseSetpoint() {
|
||||
targetvalue = thermostatSetpoint ? thermostatSetpoint : 0
|
||||
targetvalue = location.temperatureScale == "F"? targetvalue + 1 : targetvalue + 0.5
|
||||
|
||||
if ((mode == "heat" || mode == "auxHeatOnly") && targetvalue > maxHeatingSetpoint) {
|
||||
if ((mode == "heat" || mode == "emergency heat") && targetvalue > maxHeatingSetpoint) { // emergency heat = auxHeatOnly
|
||||
targetvalue = maxHeatingSetpoint
|
||||
} else if (mode == "cool" && targetvalue > maxCoolingSetpoint) {
|
||||
targetvalue = maxCoolingSetpoint
|
||||
}
|
||||
|
||||
sendEvent("name":"thermostatSetpoint", "value":targetvalue, "unit":location.temperatureScale, displayed: false)
|
||||
sendEvent("name":"displayThermostatSetpoint", "value":targetvalue, "unit":location.temperatureScale, displayed: false)
|
||||
log.info "In mode $mode raiseSetpoint() to $targetvalue"
|
||||
|
||||
runIn(3, "alterSetpoint", [data: [value:targetvalue], overwrite: true]) //when user click button this runIn will be overwrite
|
||||
@@ -666,13 +678,14 @@ void lowerSetpoint() {
|
||||
targetvalue = thermostatSetpoint ? thermostatSetpoint : 0
|
||||
targetvalue = location.temperatureScale == "F"? targetvalue - 1 : targetvalue - 0.5
|
||||
|
||||
if ((mode == "heat" || mode == "auxHeatOnly") && targetvalue < minHeatingSetpoint) {
|
||||
if ((mode == "heat" || mode == "emergency heat") && targetvalue < minHeatingSetpoint) { // emergency heat = auxHeatOnly
|
||||
targetvalue = minHeatingSetpoint
|
||||
} else if (mode == "cool" && targetvalue < minCoolingSetpoint) {
|
||||
targetvalue = minCoolingSetpoint
|
||||
}
|
||||
|
||||
sendEvent("name":"thermostatSetpoint", "value":targetvalue, "unit":location.temperatureScale, displayed: false)
|
||||
sendEvent("name":"displayThermostatSetpoint", "value":targetvalue, "unit":location.temperatureScale, displayed: false)
|
||||
log.info "In mode $mode lowerSetpoint() to $targetvalue"
|
||||
|
||||
runIn(3, "alterSetpoint", [data: [value:targetvalue], overwrite: true]) //when user click button this runIn will be overwrite
|
||||
@@ -706,7 +719,7 @@ void alterSetpoint(temp) {
|
||||
}
|
||||
|
||||
//step1: check thermostatMode, enforce limits before sending request to cloud
|
||||
if (mode == "heat" || mode == "auxHeatOnly"){
|
||||
if (mode == "heat" || mode == "emergency heat"){ // emergency heat = auxHeatOnly
|
||||
if (temp.value > coolingSetpoint){
|
||||
targetHeatingSetpoint = temp.value
|
||||
targetCoolingSetpoint = temp.value
|
||||
@@ -735,15 +748,18 @@ void alterSetpoint(temp) {
|
||||
|
||||
if (parent.setHold(heatingValue, coolingValue, deviceId, sendHoldType)) {
|
||||
sendEvent("name": "thermostatSetpoint", "value": temp.value, displayed: false)
|
||||
sendEvent("name": "displayThermostatSetpoint", "value": temp.value, displayed: false)
|
||||
sendEvent("name": "heatingSetpoint", "value": targetHeatingSetpoint, "unit": location.temperatureScale)
|
||||
sendEvent("name": "coolingSetpoint", "value": targetCoolingSetpoint, "unit": location.temperatureScale)
|
||||
log.debug "alterSetpoint in mode $mode succeed change setpoint to= ${temp.value}"
|
||||
} else {
|
||||
log.error "Error alterSetpoint()"
|
||||
if (mode == "heat" || mode == "auxHeatOnly"){
|
||||
if (mode == "heat" || mode == "emergency heat"){ // emergency heat = auxHeatOnly
|
||||
sendEvent("name": "thermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
|
||||
sendEvent("name": "displayThermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
|
||||
} else if (mode == "cool") {
|
||||
sendEvent("name": "thermostatSetpoint", "value": coolingSetpoint.toString(), displayed: false)
|
||||
sendEvent("name": "displayThermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,6 +775,7 @@ def generateStatusEvent() {
|
||||
def coolingSetpoint = device.currentValue("coolingSetpoint")
|
||||
def temperature = device.currentValue("temperature")
|
||||
def statusText
|
||||
def operatingState = "idle"
|
||||
|
||||
log.debug "Generate Status Event for Mode = ${mode}"
|
||||
log.debug "Temperature = ${temperature}"
|
||||
@@ -767,20 +784,29 @@ def generateStatusEvent() {
|
||||
log.debug "HVAC Mode = ${mode}"
|
||||
|
||||
if (mode == "heat") {
|
||||
if (temperature >= heatingSetpoint)
|
||||
if (temperature >= heatingSetpoint) {
|
||||
statusText = "Right Now: Idle"
|
||||
else
|
||||
} else {
|
||||
statusText = "Heating to ${heatingSetpoint} ${location.temperatureScale}"
|
||||
operatingState = "heating"
|
||||
}
|
||||
} else if (mode == "cool") {
|
||||
if (temperature <= coolingSetpoint)
|
||||
if (temperature <= coolingSetpoint) {
|
||||
statusText = "Right Now: Idle"
|
||||
else
|
||||
} else {
|
||||
statusText = "Cooling to ${coolingSetpoint} ${location.temperatureScale}"
|
||||
operatingState = "cooling"
|
||||
}
|
||||
} else if (mode == "auto") {
|
||||
statusText = "Right Now: Auto"
|
||||
if (temperature < heatingSetpoint) {
|
||||
operatingState = "heating"
|
||||
} else if (temperature > coolingSetpoint) {
|
||||
operatingState = "cooling"
|
||||
}
|
||||
} else if (mode == "off") {
|
||||
statusText = "Right Now: Off"
|
||||
} else if (mode == "auxHeatOnly") {
|
||||
} else if (mode == "emergency heat") { // emergency heat = auxHeatOnly
|
||||
statusText = "Emergency Heat"
|
||||
} else {
|
||||
statusText = "?"
|
||||
@@ -788,6 +814,7 @@ def generateStatusEvent() {
|
||||
|
||||
log.debug "Generate Status Event = ${statusText}"
|
||||
sendEvent("name":"thermostatStatus", "value":statusText, "description":statusText, displayed: true)
|
||||
sendEvent("name":"thermostatOperatingState", "value":operatingState, "description":operatingState, displayed: false)
|
||||
}
|
||||
|
||||
def generateActivityFeedsEvent(notificationMessage) {
|
||||
|
||||
@@ -85,6 +85,11 @@ def parse(String description) {
|
||||
result
|
||||
}
|
||||
|
||||
def installed() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
//send the command to stop polling
|
||||
def updated() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.st-ignore
|
||||
README.md
|
||||
@@ -0,0 +1,40 @@
|
||||
# Everspring Flood Sensor
|
||||
|
||||
Cloud Execution
|
||||
|
||||
Works with:
|
||||
|
||||
* [Everspring Water Detector](https://www.smartthings.com/works-with-smartthings/sensors/everspring-water-detector)
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Capabilities](#capabilities)
|
||||
* [Health](#device-health)
|
||||
* [Battery](#battery-specification)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Capabilities
|
||||
|
||||
* **Water Sensor** - can detect presence of water (dry or wet)
|
||||
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
|
||||
* **Sensor** - detects sensor events
|
||||
* **Battery** - defines device uses a battery
|
||||
* **Health Check** - indicates ability to get device health notifications
|
||||
|
||||
## Device Health
|
||||
|
||||
Everspring Water Detector is a Z-wave sleepy device and wakes up every 4 hours.
|
||||
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*4*60 + 2)mins = 482 mins.
|
||||
|
||||
* __482min__ checkInterval
|
||||
|
||||
## Battery Specification
|
||||
|
||||
Three AA 1.5V batteries are required.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
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.
|
||||
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
|
||||
* [Everspring Water Detector Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202088304-Everspring-Water-Detector)
|
||||
@@ -12,11 +12,12 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Everspring Flood Sensor", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Everspring Flood Sensor", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.moisture") {
|
||||
capability "Water Sensor"
|
||||
capability "Configuration"
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
capability "Health Check"
|
||||
|
||||
fingerprint deviceId: "0xA102", inClusters: "0x86,0x72,0x85,0x84,0x80,0x70,0x9C,0x20,0x71"
|
||||
}
|
||||
@@ -28,7 +29,7 @@ metadata {
|
||||
status "battery ${i}%": new physicalgraph.zwave.Zwave().batteryV1.batteryReport(batteryLevel: i).incomingMessage()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"water", type: "generic", width: 6, height: 4){
|
||||
tileAttribute ("device.water", key: "PRIMARY_CONTROL") {
|
||||
@@ -138,6 +139,8 @@ def zwaveEvent(physicalgraph.zwave.Command cmd)
|
||||
|
||||
def configure()
|
||||
{
|
||||
// Device wakes up every 4 hours, this interval allows us to miss one wakeup notification before marking offline
|
||||
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
if (!device.currentState("battery")) {
|
||||
sendEvent(name: "battery", value:100, unit:"%", descriptionText:"(Default battery event)", displayed:false)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
* 2. 20150125 Todd Wackford
|
||||
* Leaned out parse and moved most device info getting into configuration method.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Sets up metadata, simulator info and tile definition.
|
||||
*
|
||||
@@ -38,7 +38,7 @@
|
||||
* @return none
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Fibaro Motion Sensor", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Fibaro Motion Sensor", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.motion") {
|
||||
capability "Motion Sensor"
|
||||
capability "Temperature Measurement"
|
||||
capability "Acceleration Sensor"
|
||||
@@ -47,7 +47,7 @@
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
capability "Health Check"
|
||||
|
||||
|
||||
command "resetParams2StDefaults"
|
||||
command "listCurrentParams"
|
||||
command "updateZwaveParam"
|
||||
@@ -110,7 +110,7 @@
|
||||
state("active", label:'vibration', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0")
|
||||
state("inactive", label:'still', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
|
||||
}
|
||||
|
||||
|
||||
|
||||
main(["motion", "temperature", "acceleration", "illuminance"])
|
||||
details(["motion", "temperature", "acceleration", "battery", "illuminance", "configure"])
|
||||
@@ -130,18 +130,18 @@ def configure() {
|
||||
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
def cmds = []
|
||||
|
||||
|
||||
// send associate to group 3 to get sensor data reported only to hub
|
||||
cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()
|
||||
|
||||
// turn on tamper sensor with active/inactive reports (use it as an acceleration sensor) default is 0, or off
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [4], parameterNumber: 24, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 24).format()
|
||||
|
||||
|
||||
// temperature change report threshold (0-255 = 0.1 to 25.5C) default is 1.0 Celcius, setting to .5 Celcius
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [5], parameterNumber: 60, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 60).format()
|
||||
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 60).format()
|
||||
|
||||
cmds << response(zwave.batteryV1.batteryGet())
|
||||
cmds << response(zwave.versionV1.versionGet().format())
|
||||
cmds << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet().format())
|
||||
@@ -155,20 +155,20 @@ def parse(String description)
|
||||
{
|
||||
def result = []
|
||||
def cmd = zwave.parse(description, [0x72: 2, 0x31: 2, 0x30: 1, 0x84: 1, 0x9C: 1, 0x70: 2, 0x80: 1, 0x86: 1, 0x7A: 1, 0x56: 1])
|
||||
|
||||
|
||||
if (description == "updated") {
|
||||
result << response(zwave.wakeUpV1.wakeUpIntervalSet(seconds: 7200, nodeid:zwaveHubNodeId))
|
||||
result << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
|
||||
result << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
|
||||
}
|
||||
|
||||
|
||||
if (cmd) {
|
||||
if( cmd.CMD == "8407" ) {
|
||||
if( cmd.CMD == "8407" ) {
|
||||
result << response(zwave.batteryV1.batteryGet().format())
|
||||
result << new physicalgraph.device.HubAction(zwave.wakeUpV1.wakeUpNoMoreInformation().format())
|
||||
result << new physicalgraph.device.HubAction(zwave.wakeUpV1.wakeUpNoMoreInformation().format())
|
||||
}
|
||||
result << createEvent(zwaveEvent(cmd))
|
||||
}
|
||||
|
||||
|
||||
if ( result[0] != null ) {
|
||||
log.debug "Parse returned ${result}"
|
||||
result
|
||||
@@ -189,14 +189,14 @@ def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd)
|
||||
}
|
||||
}
|
||||
|
||||
def createEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd, Map item1) {
|
||||
def createEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd, Map item1) {
|
||||
log.debug "manufacturerId: ${cmd.manufacturerId}"
|
||||
log.debug "manufacturerName: ${cmd.manufacturerName}"
|
||||
log.debug "productId: ${cmd.productId}"
|
||||
log.debug "productTypeId: ${cmd.productTypeId}"
|
||||
}
|
||||
|
||||
def createEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd, Map item1) {
|
||||
def createEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd, Map item1) {
|
||||
updateDataValue("applicationVersion", "${cmd.applicationVersion}")
|
||||
log.debug "applicationVersion: ${cmd.applicationVersion}"
|
||||
log.debug "applicationSubVersion: ${cmd.applicationSubVersion}"
|
||||
@@ -205,7 +205,7 @@ def createEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd, Map it
|
||||
log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}"
|
||||
}
|
||||
|
||||
def createEvent(physicalgraph.zwave.commands.firmwareupdatemdv1.FirmwareMdReport cmd, Map item1) {
|
||||
def createEvent(physicalgraph.zwave.commands.firmwareupdatemdv1.FirmwareMdReport cmd, Map item1) {
|
||||
log.debug "checksum: ${cmd.checksum}"
|
||||
log.debug "firmwareId: ${cmd.firmwareId}"
|
||||
log.debug "manufacturerId: ${cmd.manufacturerId}"
|
||||
@@ -304,7 +304,7 @@ def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerS
|
||||
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
|
||||
log.debug "msr: $msr"
|
||||
updateDataValue("MSR", msr)
|
||||
|
||||
|
||||
if ( msr == "010F-0800-2001" ) { //this is the msr and device type for the fibaro motion sensor
|
||||
configure()
|
||||
}
|
||||
@@ -334,7 +334,7 @@ def test() {
|
||||
* @return none
|
||||
*/
|
||||
def updateZwaveParam(params) {
|
||||
if ( params ) {
|
||||
if ( params ) {
|
||||
def pNumber = params.paramNumber
|
||||
def pSize = params.size
|
||||
def pValue = [params.value]
|
||||
@@ -344,7 +344,7 @@ def updateZwaveParam(params) {
|
||||
def cmds = []
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: pValue, parameterNumber: pNumber, size: pSize).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: pNumber).format()
|
||||
delayBetween(cmds, 1000)
|
||||
delayBetween(cmds, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,13 +388,13 @@ def resetParams2StDefaults() {
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [18], parameterNumber: 86, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [28], parameterNumber: 87, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 89, size: 1).format()
|
||||
|
||||
|
||||
delayBetween(cmds, 500)
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all of available Fibaro parameters and thier current settings out to the
|
||||
* logging window in the IDE This will be called from the "Fibaro Tweaker" or
|
||||
* Lists all of available Fibaro parameters and thier current settings out to the
|
||||
* logging window in the IDE This will be called from the "Fibaro Tweaker" or
|
||||
* user's own app.
|
||||
*
|
||||
* <p>THIS IS AN ADVANCED OPERATION. USE AT YOUR OWN RISK! READ OEM DOCUMENTATION!
|
||||
@@ -433,7 +433,6 @@ def listCurrentParams() {
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 86).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 87).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 89).format()
|
||||
|
||||
|
||||
delayBetween(cmds, 500)
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,11 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def installed(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "GE Link Bulb", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "GE Link Bulb", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
|
||||
capability "Actuator"
|
||||
capability "Configuration"
|
||||
|
||||
@@ -57,10 +57,20 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
void installed() {
|
||||
def initialize() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false)
|
||||
}
|
||||
|
||||
void installed() {
|
||||
log.debug "installed()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "updated()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
// parse events into attributes
|
||||
def parse(description) {
|
||||
log.debug "parse() - $description"
|
||||
|
||||
@@ -45,10 +45,20 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
void installed() {
|
||||
def initialize() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false)
|
||||
}
|
||||
|
||||
void installed() {
|
||||
log.debug "installed()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "updated()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
// parse events into attributes
|
||||
def parse(description) {
|
||||
log.debug "Parsing '${description}'"
|
||||
|
||||
@@ -66,10 +66,20 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
void installed() {
|
||||
def initialize() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false)
|
||||
}
|
||||
|
||||
void installed() {
|
||||
log.debug "installed()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "updated()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
// parse events into attributes
|
||||
def parse(description) {
|
||||
log.debug "parse() - $description"
|
||||
|
||||
@@ -50,10 +50,19 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
void installed() {
|
||||
def initialize() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false)
|
||||
}
|
||||
|
||||
void installed() {
|
||||
log.debug "installed()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
initialize()
|
||||
}
|
||||
|
||||
// parse events into attributes
|
||||
def parse(description) {
|
||||
log.debug "parse() - $description"
|
||||
|
||||
@@ -55,10 +55,20 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
void installed() {
|
||||
def initialize() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false)
|
||||
}
|
||||
|
||||
void installed() {
|
||||
log.debug "installed()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "updated()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
// parse events into attributes
|
||||
def parse(description) {
|
||||
log.debug "parse() - $description"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "LIFX Color Bulb", namespace: "smartthings", author: "LIFX") {
|
||||
definition (name: "LIFX Color Bulb", namespace: "smartthings", author: "LIFX", ocfDeviceType: "oic.d.light") {
|
||||
capability "Actuator"
|
||||
capability "Color Control"
|
||||
capability "Color Temperature"
|
||||
@@ -64,8 +64,18 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"cloud\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device?.hub?.hardwareID}\"}", displayed: false)
|
||||
}
|
||||
|
||||
void installed() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"cloud\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device?.hub?.hardwareID}\"}")
|
||||
log.debug "installed()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "updated()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
// handle commands
|
||||
@@ -190,7 +200,7 @@ def off() {
|
||||
|
||||
def refresh() {
|
||||
log.debug "Executing 'refresh'"
|
||||
|
||||
|
||||
def resp = parent.apiGET("/lights/${selector()}")
|
||||
if (resp.status == 404) {
|
||||
state.online = false
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "LIFX White Bulb", namespace: "smartthings", author: "LIFX") {
|
||||
definition (name: "LIFX White Bulb", namespace: "smartthings", author: "LIFX", ocfDeviceType: "oic.d.light") {
|
||||
capability "Actuator"
|
||||
capability "Color Temperature"
|
||||
capability "Switch"
|
||||
@@ -55,8 +55,18 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"cloud\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device?.hub?.hardwareID}\"}", displayed: false)
|
||||
}
|
||||
|
||||
void installed() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"cloud\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device?.hub?.hardwareID}\"}")
|
||||
log.debug "installed()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "updated()"
|
||||
initialize()
|
||||
}
|
||||
|
||||
// handle commands
|
||||
@@ -119,7 +129,7 @@ def off() {
|
||||
|
||||
def refresh() {
|
||||
log.debug "Executing 'refresh'"
|
||||
|
||||
|
||||
def resp = parent.apiGET("/lights/${selector()}")
|
||||
if (resp.status == 404) {
|
||||
state.online = false
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import groovy.json.JsonOutput
|
||||
/**
|
||||
* Logitech Harmony Hub
|
||||
*
|
||||
@@ -39,14 +40,18 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "cloud", scheme:"untracked"]), displayed: false)
|
||||
}
|
||||
|
||||
def installed() {
|
||||
log.debug "installed()"
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "cloud", scheme:"untracked"]), displayed: false)
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "updated()"
|
||||
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "cloud", scheme:"untracked"]), displayed: false)
|
||||
initialize()
|
||||
}
|
||||
|
||||
def startActivity(String activityId) {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Open/Closed Sensor", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Open/Closed Sensor", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.contact") {
|
||||
capability "Contact Sensor"
|
||||
capability "Sensor"
|
||||
|
||||
@@ -44,7 +44,7 @@ def parse(String description) {
|
||||
if (description.startsWith("zone")) {
|
||||
resMap = createEvent(name: "contact", value: zigbee.parseZoneStatus(description).isAlarm1Set() ? "open" : "closed")
|
||||
}
|
||||
|
||||
|
||||
log.debug "Parse returned $resMap"
|
||||
return resMap
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "RGBW Light", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "RGBW Light", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
capability "Switch Level"
|
||||
capability "Color Control"
|
||||
capability "Color Temperature"
|
||||
|
||||
@@ -91,6 +91,11 @@ def parse(String description) {
|
||||
return result
|
||||
}
|
||||
|
||||
def installed() {
|
||||
// Device-Watch simply pings if no device events received for 482min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 4 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated() {
|
||||
// Device-Watch simply pings if no device events received for 482min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 4 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
@@ -135,10 +135,7 @@ def refresh() {
|
||||
return zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0x104E]) + // New firmware
|
||||
zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0xC2DF]) + // Original firmware
|
||||
zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
|
||||
zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) +
|
||||
zigbee.configureReporting(0xFC45, 0x0000, DataType.INT16, 30, 3600, 100) +
|
||||
zigbee.batteryConfig() +
|
||||
zigbee.temperatureConfig(30, 300)
|
||||
zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020)
|
||||
}
|
||||
|
||||
def configure() {
|
||||
@@ -150,5 +147,10 @@ def configure() {
|
||||
|
||||
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||
// battery minReport 30 seconds, maxReportTime 6 hrs by default
|
||||
return refresh()
|
||||
return refresh() +
|
||||
zigbee.configureReporting(0xFC45, 0x0000, DataType.UINT16, 30, 3600, 100, ["mfgCode": 0x104E]) + // New firmware
|
||||
zigbee.configureReporting(0xFC45, 0x0000, DataType.UINT16, 30, 3600, 100, ["mfgCode": 0xC2DF]) + // Original firmware
|
||||
zigbee.batteryConfig() +
|
||||
zigbee.temperatureConfig(30, 300)
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
//DEPRECATED - Using the generic DTH for this device. Users need to be moved before deleting this DTH
|
||||
|
||||
metadata {
|
||||
definition (name: "Sylvania Ultra iQ", namespace:"smartthings", author: "SmartThings") {
|
||||
definition (name: "Sylvania Ultra iQ", namespace:"smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
capability "Switch Level"
|
||||
capability "Configuration"
|
||||
capability "Switch"
|
||||
|
||||
@@ -20,6 +20,7 @@ metadata {
|
||||
definition(name: "Wattvision", namespace: "smartthings", author: "Steve Vlaminck") {
|
||||
capability "Power Meter"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
attribute "powerContent", "string"
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
//DEPRECATED - Using the generic DTH for this device. Users need to be moved before deleting this DTH
|
||||
|
||||
metadata {
|
||||
definition (name: "WeMo Bulb", namespace: "smartthings", author: "SmartThings") {
|
||||
|
||||
definition (name: "WeMo Bulb", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
|
||||
capability "Actuator"
|
||||
capability "Configuration"
|
||||
capability "Refresh"
|
||||
@@ -57,7 +57,7 @@ metadata {
|
||||
valueTile("level", "device.level", inactiveLabel: false, decoration: "flat") {
|
||||
state "level", label: 'Level ${currentValue}%'
|
||||
}
|
||||
|
||||
|
||||
|
||||
main(["switch"])
|
||||
details(["switch", "level", "levelSliderControl", "refresh"])
|
||||
@@ -87,11 +87,11 @@ def parse(String description) {
|
||||
if (description?.startsWith("read attr")) {
|
||||
log.debug description[-2..-1]
|
||||
def i = Math.round(convertHexToInt(description[-2..-1]) / 256 * 100 )
|
||||
|
||||
|
||||
sendEvent( name: "level", value: i )
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
def on() {
|
||||
@@ -136,16 +136,16 @@ def setLevel(value) {
|
||||
def configure() {
|
||||
|
||||
log.debug "Configuring Reporting and Bindings."
|
||||
def configCmds = [
|
||||
|
||||
def configCmds = [
|
||||
|
||||
//Switch Reporting
|
||||
"zcl global send-me-a-report 6 0 0x10 0 3600 {01}", "delay 500",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 1000",
|
||||
|
||||
|
||||
//Level Control Reporting
|
||||
"zcl global send-me-a-report 8 0 0x20 5 3600 {0010}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
||||
|
||||
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 1 6 {${device.zigbeeId}} {}", "delay 1000",
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 1 8 {${device.zigbeeId}} {}", "delay 500",
|
||||
]
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
|
||||
metadata {
|
||||
definition (name: "Wemo Light Switch", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Wemo Light Switch", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.switch") {
|
||||
capability "Actuator"
|
||||
capability "Switch"
|
||||
capability "Polling"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* Date: 2015-10-11
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Wemo Switch", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Wemo Switch", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.smartplug") {
|
||||
capability "Actuator"
|
||||
capability "Switch"
|
||||
capability "Polling"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "ZigBee Dimmer Power", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.switch") {
|
||||
definition (name: "ZigBee Dimmer Power", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
capability "Actuator"
|
||||
capability "Configuration"
|
||||
capability "Refresh"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "ZigBee Dimmer", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "ZigBee Dimmer", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
capability "Actuator"
|
||||
capability "Configuration"
|
||||
capability "Refresh"
|
||||
|
||||
46
devicetypes/smartthings/zigbee-lock.src/README.md
Normal file
46
devicetypes/smartthings/zigbee-lock.src/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Zigbee Lock
|
||||
|
||||
Cloud Execution
|
||||
|
||||
Works with:
|
||||
|
||||
* [Yale Push Button Deadbolt (YRD210-HA)](https://www.smartthings.com/works-with-smartthings/door-locks/yale-push-button-deadbolt-yrd210)
|
||||
* [Yale Touchscreen Lever (YRL220-ZB)](https://www.smartthings.com/works-with-smartthings/door-locks/yale-touchscreen-lever-yrl220)
|
||||
* [Yale Touchscreen Deadbolt (YRD220-HA))](https://www.smartthings.com/works-with-smartthings/door-locks/yale-touchscreen-deadbolt-yrd220)
|
||||
* [Yale Key Free Touchscreen Deadbolt (YRD240-HA)](https://www.smartthings.com/works-with-smartthings/door-locks/yale-key-free-touchscreen-deadbolt-yrd240)
|
||||
* [Yale Push Button Lever Lock (YRL210-HA)](https://www.smartthings.com/works-with-smartthings/door-locks/yale-push-button-lever-lock-yrl210)
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Capabilities](#capabilities)
|
||||
* [Health](#device-health)
|
||||
* [Battery](#battery-specification)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Capabilities
|
||||
|
||||
* **Actuator** - represents that a Device has commands
|
||||
* **Lock** - allows for the control of a lock device
|
||||
* **Refresh** - _refresh()_ command for status updates
|
||||
* **Sensor** - detects sensor events
|
||||
* **Battery** - defines device uses a battery
|
||||
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
|
||||
* **Health Check** - indicates ability to get device health notifications
|
||||
|
||||
## Device Health
|
||||
|
||||
Yale Push Button Deadbolt (YRD210-HA) is a Zigbee device and checks in every 1 hour.
|
||||
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*60 + 2)mins = 122 mins.
|
||||
|
||||
* __122min__ checkInterval
|
||||
|
||||
## Battery Specification
|
||||
|
||||
Four AA 1.5V batteries are required.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
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.
|
||||
Instructions related to pairing, resetting and removing the sensor from SmartThings can be found in the following link:
|
||||
* [Yale Locks Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/205138400)
|
||||
@@ -24,6 +24,7 @@ import physicalgraph.zigbee.zcl.DataType
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
capability "Configuration"
|
||||
capability "Health Check"
|
||||
|
||||
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0009,0020,0101,0402,0B05,FDBD", outClusters: "000A,0019", manufacturer: "Kwikset", model: "SMARTCODE_DEADBOLT_5", deviceJoinName: "Kwikset 5-Button Deadbolt"
|
||||
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0009,0020,0101,0402,0B05,FDBD", outClusters: "000A,0019", manufacturer: "Kwikset", model: "SMARTCODE_LEVER_5", deviceJoinName: "Kwikset 5-Button Lever"
|
||||
@@ -83,6 +84,9 @@ def uninstalled() {
|
||||
}
|
||||
|
||||
def configure() {
|
||||
// Device-Watch allows 2 check-in misses from device + ping (plus 2 min lag time)
|
||||
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
def cmds =
|
||||
zigbee.configureReporting(CLUSTER_DOORLOCK, DOORLOCK_ATTR_LOCKSTATE,
|
||||
DataType.ENUM8, 0, 3600, null) +
|
||||
@@ -92,6 +96,13 @@ def configure() {
|
||||
return refresh() + cmds // send refresh cmds as part of config
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
zigbee.readAttribute(CLUSTER_DOORLOCK, DOORLOCK_ATTR_LOCKSTATE)
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
def cmds =
|
||||
zigbee.readAttribute(CLUSTER_DOORLOCK, DOORLOCK_ATTR_LOCKSTATE) +
|
||||
|
||||
@@ -16,7 +16,7 @@ import groovy.transform.Field
|
||||
@Field Boolean hasConfiguredHealthCheck = false
|
||||
|
||||
metadata {
|
||||
definition (name: "ZLL Dimmer Bulb", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "ZLL Dimmer Bulb", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
|
||||
capability "Actuator"
|
||||
capability "Configuration"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import physicalgraph.zigbee.zcl.DataType
|
||||
|
||||
metadata {
|
||||
definition (name: "ZLL RGB Bulb", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "ZLL RGB Bulb", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
|
||||
capability "Actuator"
|
||||
capability "Color Control"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import physicalgraph.zigbee.zcl.DataType
|
||||
|
||||
metadata {
|
||||
definition (name: "ZLL RGBW Bulb", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "ZLL RGBW Bulb", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
|
||||
capability "Actuator"
|
||||
capability "Color Control"
|
||||
|
||||
@@ -16,7 +16,7 @@ import groovy.transform.Field
|
||||
@Field Boolean hasConfiguredHealthCheck = false
|
||||
|
||||
metadata {
|
||||
definition (name: "ZLL White Color Temperature Bulb 5000K", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "ZLL White Color Temperature Bulb 5000K", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
|
||||
capability "Actuator"
|
||||
capability "Color Temperature"
|
||||
@@ -101,7 +101,7 @@ def refresh() {
|
||||
if (!((device.getDataValue("manufacturer") == "Eaton") && (device.getDataValue("model") == "Halo_LT01"))) {
|
||||
cmds = cmds + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig()
|
||||
}
|
||||
|
||||
|
||||
cmds
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import groovy.transform.Field
|
||||
@Field Boolean hasConfiguredHealthCheck = false
|
||||
|
||||
metadata {
|
||||
definition (name: "ZLL White Color Temperature Bulb", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "ZLL White Color Temperature Bulb", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
|
||||
capability "Actuator"
|
||||
capability "Color Temperature"
|
||||
|
||||
@@ -25,6 +25,7 @@ metadata {
|
||||
capability "Refresh"
|
||||
capability "Actuator"
|
||||
capability "Sensor"
|
||||
capability "Configuration"
|
||||
|
||||
fingerprint manufacturer: "015D", prod: "0651", model: "F51C", deviceJoinName: "Zooz ZEN 20 Power Strip"
|
||||
}
|
||||
@@ -65,6 +66,10 @@ def updated() {
|
||||
}
|
||||
}
|
||||
|
||||
def configure() {
|
||||
refresh()
|
||||
}
|
||||
|
||||
|
||||
//////////////////////
|
||||
// Event Generation //
|
||||
@@ -107,15 +112,17 @@ def zwaveBinaryEvent(cmd, endpoint) {
|
||||
def result = []
|
||||
def children = childDevices
|
||||
def childDevice = children.find{it.deviceNetworkId.endsWith("$endpoint")}
|
||||
childDevice.sendEvent(name: "switch", value: cmd.value ? "on" : "off")
|
||||
if (childDevice) {
|
||||
childDevice.sendEvent(name: "switch", value: cmd.value ? "on" : "off")
|
||||
|
||||
if (cmd.value) {
|
||||
// One on and the strip is on
|
||||
result << createEvent(name: "switch", value: "on")
|
||||
} else {
|
||||
// All off and the strip is off
|
||||
if (! children.any { it.currentValue("switch") == "on" }) {
|
||||
result << createEvent(name: "switch", value: "off")
|
||||
if (cmd.value) {
|
||||
// One on and the strip is on
|
||||
result << createEvent(name: "switch", value: "on")
|
||||
} else {
|
||||
// All off and the strip is off
|
||||
if (!children.any { it.currentValue("switch") == "on" }) {
|
||||
result << createEvent(name: "switch", value: "off")
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Z-Wave Dimmer Switch Generic", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Z-Wave Dimmer Switch Generic", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
|
||||
capability "Switch Level"
|
||||
capability "Actuator"
|
||||
capability "Health Check"
|
||||
@@ -78,6 +78,11 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def installed(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "Z-Wave Door/Window Sensor", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Z-Wave Door/Window Sensor", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.contact") {
|
||||
capability "Contact Sensor"
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
@@ -79,6 +79,11 @@ def parse(String description) {
|
||||
return result
|
||||
}
|
||||
|
||||
def installed() {
|
||||
// Device-Watch simply pings if no device events received for 482min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 4 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated() {
|
||||
// Device-Watch simply pings if no device events received for 482min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 4 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
@@ -65,6 +65,11 @@ metadata {
|
||||
|
||||
import physicalgraph.zwave.commands.barrieroperatorv1.*
|
||||
|
||||
def installed(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
@@ -68,6 +68,11 @@ metadata {
|
||||
import physicalgraph.zwave.commands.doorlockv1.*
|
||||
import physicalgraph.zwave.commands.usercodev1.*
|
||||
|
||||
def installed() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Z-Wave Metering Dimmer", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Z-Wave Metering Dimmer", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.switch") {
|
||||
capability "Switch"
|
||||
capability "Polling"
|
||||
capability "Power Meter"
|
||||
@@ -25,11 +25,13 @@ metadata {
|
||||
capability "Switch Level"
|
||||
capability "Sensor"
|
||||
capability "Actuator"
|
||||
capability "Health Check"
|
||||
capability "Light"
|
||||
|
||||
command "reset"
|
||||
|
||||
fingerprint inClusters: "0x26,0x32"
|
||||
fingerprint mfr:"0086", prod:"0003", model:"001B", deviceJoinName: "Aeon Labs Micro Smart Dimmer 2E"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -98,7 +100,15 @@ def parse(String description) {
|
||||
result
|
||||
}
|
||||
|
||||
def installed() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
response(refresh())
|
||||
}
|
||||
|
||||
@@ -163,6 +173,14 @@ def poll() {
|
||||
], 1000)
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
log.debug "ping() called"
|
||||
refresh()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
delayBetween([
|
||||
zwave.switchMultilevelV1.switchMultilevelGet().format(),
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Z-Wave Metering Switch", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Z-Wave Metering Switch", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.switch") {
|
||||
capability "Energy Meter"
|
||||
capability "Actuator"
|
||||
capability "Switch"
|
||||
@@ -27,7 +27,7 @@ metadata {
|
||||
command "reset"
|
||||
|
||||
fingerprint inClusters: "0x25,0x32"
|
||||
fingerprint mfr:"0086", prod:"0003", model:"0012", deviceJoinName: "Aeon Labs Micro Smart Switch 2E"
|
||||
fingerprint mfr:"0086", prod:"0003", model:"0012", deviceJoinName: "Aeon Labs Micro Smart Switch"
|
||||
}
|
||||
|
||||
// simulator metadata
|
||||
@@ -74,6 +74,11 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
@@ -86,7 +91,7 @@ def updated() {
|
||||
|
||||
def parse(String description) {
|
||||
def result = null
|
||||
if(description == "updated") return
|
||||
if(description == "updated") return
|
||||
def cmd = zwave.parse(description, [0x20: 1, 0x32: 1, 0x72: 2])
|
||||
if (cmd) {
|
||||
result = zwaveEvent(cmd)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "Z-Wave Motion Sensor", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Z-Wave Motion Sensor", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.motion") {
|
||||
capability "Motion Sensor"
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
@@ -36,7 +36,7 @@ metadata {
|
||||
status "inactive": "command: 3003, payload: 00"
|
||||
status "active": "command: 3003, payload: FF"
|
||||
}
|
||||
|
||||
|
||||
tiles {
|
||||
standardTile("motion", "device.motion", width: 2, height: 2) {
|
||||
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC")
|
||||
@@ -51,7 +51,12 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def updated(){
|
||||
def installed() {
|
||||
// Device wakes up every 4 hours, this interval allows us to miss one wakeup notification before marking offline
|
||||
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated() {
|
||||
// Device wakes up every 4 hours, this interval allows us to miss one wakeup notification before marking offline
|
||||
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
@@ -197,4 +202,4 @@ def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerS
|
||||
|
||||
result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "Z-Wave Plus Door/Window Sensor", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Z-Wave Plus Door/Window Sensor", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.contact") {
|
||||
capability "Contact Sensor"
|
||||
capability "Configuration"
|
||||
capability "Battery"
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
# Z-wave Siren
|
||||
|
||||
Cloud Execution
|
||||
|
||||
Works with:
|
||||
|
||||
* [FortrezZ Siren Strobe Alarm](https://www.smartthings.com/works-with-smartthings/other/fortrezz-water-valve)
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Capabilities](#capabilities)
|
||||
* [Health](#device-health)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Capabilities
|
||||
|
||||
* **Actuator** - represents that a Device has commands
|
||||
* **Alarm** - allows for interacting with devices that serve as alarms
|
||||
* **Battery** - defines device uses a battery
|
||||
* **Health Check** - indicates ability to get device health notifications
|
||||
* **Polling** - represents that poll() can be implemented for the device
|
||||
* **Refresh** - _refresh()_ command for status updates
|
||||
* **Sensor** - detects sensor events
|
||||
* **Switch** - can detect state (possible values: on/off)
|
||||
|
||||
## Device Health
|
||||
|
||||
FortrezZ Siren Strobe Alarm is 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.
|
||||
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
|
||||
the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row,
|
||||
it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time.
|
||||
|
||||
* __32min__ checkInterval
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
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.
|
||||
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
|
||||
* [FortrezZ Siren Strobe Alarm Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202294760-FortrezZ-Siren-Strobe-Alarm)
|
||||
@@ -20,7 +20,6 @@ metadata {
|
||||
capability "Actuator"
|
||||
capability "Alarm"
|
||||
capability "Battery"
|
||||
capability "Health Check"
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
@@ -28,7 +27,6 @@ metadata {
|
||||
|
||||
|
||||
fingerprint inClusters: "0x20,0x25,0x86,0x80,0x85,0x72,0x71"
|
||||
fingerprint mfr:"0084", prod:"0313", model:"010B", deviceJoinName: "FortrezZ Siren Strobe Alarm"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -60,11 +58,6 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def updated(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def createEvents(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
|
||||
def map = [ name: "battery", unit: "%" ]
|
||||
if (cmd.batteryLevel == 0xFF) {
|
||||
@@ -126,13 +119,6 @@ def both() {
|
||||
on()
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
refresh()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
log.debug "sending battery refresh command"
|
||||
zwave.batteryV1.batteryGet().format()
|
||||
|
||||
@@ -53,7 +53,12 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def updated(){
|
||||
def installed() {
|
||||
// Device checks in every hour, this interval allows us to miss one check-in notification before marking offline
|
||||
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated() {
|
||||
// Device checks in every hour, this interval allows us to miss one check-in notification before marking offline
|
||||
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Z-Wave Switch Generic", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Z-Wave Switch Generic", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.switch") {
|
||||
capability "Actuator"
|
||||
capability "Health Check"
|
||||
capability "Switch"
|
||||
@@ -61,6 +61,11 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def installed(){
|
||||
// Device-Watch simply pings if no device events received for checkInterval duration of 32min = 2 * 15min + 2min lag time
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated(){
|
||||
// Device-Watch simply pings if no device events received for checkInterval duration of 32min = 2 * 15min + 2min lag time
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Z-Wave Switch Secure", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Z-Wave Switch Secure", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.switch") {
|
||||
capability "Switch"
|
||||
capability "Refresh"
|
||||
capability "Polling"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Z-Wave Switch", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Z-Wave Switch", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.switch") {
|
||||
capability "Actuator"
|
||||
capability "Indicator"
|
||||
capability "Switch"
|
||||
@@ -65,6 +65,11 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
@@ -42,9 +42,9 @@ metadata {
|
||||
status "auto" : "command: 4003, payload: 03"
|
||||
status "emergencyHeat" : "command: 4003, payload: 04"
|
||||
|
||||
status "fanAuto" : "command: 4403, payload: 00"
|
||||
status "fanOn" : "command: 4403, payload: 01"
|
||||
status "fanCirculate" : "command: 4403, payload: 06"
|
||||
status "auto" : "command: 4403, payload: 00" // "fanAuto"
|
||||
status "on" : "command: 4403, payload: 01" // "fanOn"
|
||||
status "circulate" : "command: 4403, payload: 06" // "fanCirculate
|
||||
|
||||
status "heat 60" : "command: 4303, payload: 01 09 3C"
|
||||
status "heat 68" : "command: 4303, payload: 01 09 44"
|
||||
@@ -74,8 +74,9 @@ metadata {
|
||||
}
|
||||
|
||||
tiles {
|
||||
valueTile("temperature", "device.temperature", width: 2, height: 2) {
|
||||
state("temperature", label:'${currentValue}°',
|
||||
// Using standardTile instead of valueTile as it renders the icon better
|
||||
standardTile("temperature", "device.temperature", width: 2, height: 2) {
|
||||
state("temperature", label:'${currentValue}°', icon: "st.thermostat.ac.air-conditioning",
|
||||
backgroundColors:[
|
||||
[value: 31, color: "#153591"],
|
||||
[value: 44, color: "#1e9cbb"],
|
||||
@@ -88,19 +89,20 @@ metadata {
|
||||
)
|
||||
}
|
||||
standardTile("mode", "device.thermostatMode", inactiveLabel: false, decoration: "flat") {
|
||||
state "off", label:'${name}', action:"switchMode", nextState:"to_heat"
|
||||
state "heat", label:'${name}', action:"switchMode", nextState:"to_cool"
|
||||
state "cool", label:'${name}', action:"switchMode", nextState:"..."
|
||||
state "auto", label:'${name}', action:"switchMode", nextState:"..."
|
||||
state "emergency heat", label:'${name}', action:"switchMode", nextState:"..."
|
||||
state "to_heat", label: "heat", action:"switchMode", nextState:"to_cool"
|
||||
state "to_cool", label: "cool", action:"switchMode", nextState:"..."
|
||||
state "off", action:"switchMode", nextState:"to_heat", icon: "st.thermostat.heating-cooling-off"
|
||||
state "heat", action:"switchMode", nextState:"to_cool", icon: "st.thermostat.heat"
|
||||
state "cool", action:"switchMode", nextState:"...", icon: "st.thermostat.cool"
|
||||
state "auto", action:"switchMode", nextState:"...", icon: "st.thermostat.auto"
|
||||
state "emergency heat", action:"switchMode", nextState:"...", icon: "st.thermostat.emergency-heat"
|
||||
state "to_heat", action:"switchMode", nextState:"to_cool", icon: "st.thermostat.heat"
|
||||
state "to_cool", action:"switchMode", nextState:"...", icon: "st.thermostat.cool"
|
||||
state "...", label: "...", action:"off", nextState:"off"
|
||||
}
|
||||
standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") {
|
||||
state "fanAuto", label:'${name}', action:"switchFanMode"
|
||||
state "fanOn", label:'${name}', action:"switchFanMode"
|
||||
state "fanCirculate", label:'${name}', action:"switchFanMode"
|
||||
state "auto", action:"switchFanMode", nextState:"...", icon: "st.thermostat.fan-auto" // "fanAuto"
|
||||
state "on", action:"switchFanMode", nextState:"...", icon: "st.thermostat.fan-on" // "fanOn"
|
||||
state "circulate", action:"switchFanMode", nextState:"...", icon: "st.thermostat.fan-circulate" // "fanCirculate"
|
||||
state "...", label: "...", nextState:"..."
|
||||
}
|
||||
controlTile("heatSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
|
||||
state "setHeatingSetpoint", action:"quickSetHeat", backgroundColor:"#d04e00"
|
||||
@@ -117,14 +119,16 @@ metadata {
|
||||
standardTile("refresh", "device.thermostatMode", inactiveLabel: false, decoration: "flat") {
|
||||
state "default", action:"polling.poll", icon:"st.secondary.refresh"
|
||||
}
|
||||
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") {
|
||||
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
|
||||
}
|
||||
main "temperature"
|
||||
details(["temperature", "mode", "fanMode", "heatSliderControl", "heatingSetpoint", "coolSliderControl", "coolingSetpoint", "refresh", "configure"])
|
||||
details(["temperature", "mode", "fanMode", "heatSliderControl", "heatingSetpoint", "coolSliderControl", "coolingSetpoint", "refresh"])
|
||||
}
|
||||
}
|
||||
|
||||
def installed(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
}
|
||||
|
||||
def updated(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
@@ -286,13 +290,13 @@ def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanMod
|
||||
def map = [:]
|
||||
switch (cmd.fanMode) {
|
||||
case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_AUTO_LOW:
|
||||
map.value = "fanAuto"
|
||||
map.value = "auto" // "fanAuto"
|
||||
break
|
||||
case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_LOW:
|
||||
map.value = "fanOn"
|
||||
map.value = "on" // "fanOn"
|
||||
break
|
||||
case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_CIRCULATION:
|
||||
map.value = "fanCirculate"
|
||||
map.value = "circulate" // "fanCirculate"
|
||||
break
|
||||
}
|
||||
map.name = "thermostatFanMode"
|
||||
@@ -309,15 +313,19 @@ def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeSuppo
|
||||
if(cmd.auto) { supportedModes += "auto " }
|
||||
|
||||
state.supportedModes = supportedModes
|
||||
// No events to be generated, return empty map
|
||||
return [:]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeSupportedReport cmd) {
|
||||
def supportedFanModes = ""
|
||||
if(cmd.auto) { supportedFanModes += "fanAuto " }
|
||||
if(cmd.low) { supportedFanModes += "fanOn " }
|
||||
if(cmd.circulation) { supportedFanModes += "fanCirculate " }
|
||||
if(cmd.auto) { supportedFanModes += "auto " } // "fanAuto "
|
||||
if(cmd.low) { supportedFanModes += "on " } // "fanOn"
|
||||
if(cmd.circulation) { supportedFanModes += "circulate " } // "fanCirculate"
|
||||
|
||||
state.supportedFanModes = supportedFanModes
|
||||
// No events to be generated, return empty map
|
||||
return [:]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
|
||||
@@ -412,7 +420,13 @@ def configure() {
|
||||
delayBetween([
|
||||
zwave.thermostatModeV2.thermostatModeSupportedGet().format(),
|
||||
zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format(),
|
||||
zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format()
|
||||
zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format(),
|
||||
zwave.sensorMultilevelV3.sensorMultilevelGet().format(), // current temperature
|
||||
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format(),
|
||||
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2).format(),
|
||||
zwave.thermostatModeV2.thermostatModeGet().format(),
|
||||
zwave.thermostatFanModeV3.thermostatFanModeGet().format(),
|
||||
zwave.thermostatOperatingStateV1.thermostatOperatingStateGet().format()
|
||||
], 2300)
|
||||
}
|
||||
|
||||
@@ -453,11 +467,11 @@ def switchToMode(nextMode) {
|
||||
def switchFanMode() {
|
||||
def currentMode = device.currentState("thermostatFanMode")?.value
|
||||
def lastTriedMode = state.lastTriedFanMode ?: currentMode ?: "off"
|
||||
def supportedModes = getDataByName("supportedFanModes") ?: "fanAuto fanOn"
|
||||
def modeOrder = ["fanAuto", "fanCirculate", "fanOn"]
|
||||
def supportedModes = getDataByName("supportedFanModes") ?: "auto on" // "fanAuto fanOn"
|
||||
def modeOrder = ["auto", "circulate", "on"] // "fanAuto", "fanCirculate", "fanOn"
|
||||
def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] }
|
||||
def nextMode = next(lastTriedMode)
|
||||
while (!supportedModes?.contains(nextMode) && nextMode != "fanAuto") {
|
||||
while (!supportedModes?.contains(nextMode) && nextMode != "auto") { // "fanAuto"
|
||||
nextMode = next(nextMode)
|
||||
}
|
||||
switchToFanMode(nextMode)
|
||||
@@ -468,11 +482,11 @@ def switchToFanMode(nextMode) {
|
||||
if(supportedFanModes && !supportedFanModes.contains(nextMode)) log.warn "thermostat mode '$nextMode' is not supported"
|
||||
|
||||
def returnCommand
|
||||
if (nextMode == "fanAuto") {
|
||||
if (nextMode == "auto") { // "fanAuto"
|
||||
returnCommand = fanAuto()
|
||||
} else if (nextMode == "fanOn") {
|
||||
} else if (nextMode == "on") { // "fanOn"
|
||||
returnCommand = fanOn()
|
||||
} else if (nextMode == "fanCirculate") {
|
||||
} else if (nextMode == "circulate") { // "fanCirculate"
|
||||
returnCommand = fanCirculate()
|
||||
} else {
|
||||
log.debug("no fan mode '$nextMode'")
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* Date: 2013-03-07
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Z-Wave Virtual Momentary Contact Switch", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Z-Wave Virtual Momentary Contact Switch", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.contact") {
|
||||
capability "Actuator"
|
||||
capability "Switch"
|
||||
capability "Refresh"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "Z-Wave Water Sensor", namespace: "smartthings", author: "SmartThings") {
|
||||
definition (name: "Z-Wave Water Sensor", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.moisture") {
|
||||
capability "Water Sensor"
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
@@ -29,7 +29,7 @@ metadata {
|
||||
status "dry": "command: 3003, payload: 00"
|
||||
status "wet": "command: 3003, payload: FF"
|
||||
}
|
||||
|
||||
|
||||
tiles {
|
||||
standardTile("water", "device.water", width: 2, height: 2) {
|
||||
state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
|
||||
|
||||
@@ -1,445 +0,0 @@
|
||||
/**
|
||||
* MediaRenderer Service Manager v 2.0.1
|
||||
*
|
||||
* Author: SmartThings - Ulises Mujica
|
||||
*/
|
||||
|
||||
definition(
|
||||
name: "MediaRenderer (Connect)",
|
||||
namespace: "mujica",
|
||||
author: "SmartThings - Ulises Mujica",
|
||||
description: "Allows you to control your Media Renderer from the SmartThings app. Perform basic functions like play, pause, stop, change track, and check artist and song name from the Things screen.",
|
||||
category: "SmartThings Labs",
|
||||
singleInstance: true,
|
||||
iconUrl: "https://graph.api.smartthings.com/api/devices/icons/st.secondary.smartapps-tile?displaySize=2x",
|
||||
iconX2Url: "https://graph.api.smartthings.com/api/devices/icons/st.secondary.smartapps-tile?displaySize=2x"
|
||||
)
|
||||
|
||||
preferences {
|
||||
page(name: "MainPage", title: "Search and config your Media Renderers", install:true, uninstall: true){
|
||||
section("") {
|
||||
href(name: "discover",title: "Discovery process",required: false,page: "mediaRendererDiscovery",description: "tap to start searching")
|
||||
}
|
||||
section("Options", hideable: true, hidden: true) {
|
||||
input("refreshMRInterval", "number", title:"Enter refresh players interval (min)",defaultValue:"15", required:false)
|
||||
}
|
||||
}
|
||||
page(name: "mediaRendererDiscovery", title:"Discovery Started!")
|
||||
}
|
||||
|
||||
def mediaRendererDiscovery()
|
||||
{
|
||||
log.trace "mediaRendererDiscovery() state.subscribe ${state.subscribe}"
|
||||
if(canInstallLabs())
|
||||
{
|
||||
|
||||
|
||||
int mediaRendererRefreshCount = !state.mediaRendererRefreshCount ? 0 : state.mediaRendererRefreshCount as int
|
||||
state.mediaRendererRefreshCount = mediaRendererRefreshCount + 1
|
||||
def refreshInterval = 5
|
||||
|
||||
def options = mediaRenderersDiscovered() ?: []
|
||||
|
||||
def numFound = options.size() ?: 0
|
||||
|
||||
if(!state.subscribe) {
|
||||
subscribe(location, null, locationHandler, [filterEvents:false])
|
||||
state.subscribe = true
|
||||
}
|
||||
|
||||
//mediaRenderer discovery request every 5 //25 seconds
|
||||
if((mediaRendererRefreshCount % 8) == 0) {
|
||||
discoverMediaRenderers()
|
||||
}
|
||||
|
||||
//setup.xml request every 3 seconds except on discoveries
|
||||
if(((mediaRendererRefreshCount % 1) == 0) && ((mediaRendererRefreshCount % 8) != 0)) {
|
||||
verifyMediaRendererPlayer()
|
||||
}
|
||||
|
||||
return dynamicPage(name:"mediaRendererDiscovery", title:"Discovery Started!", nextPage:"", refreshInterval:refreshInterval) {
|
||||
section("Please wait while we discover your MediaRenderer. Discovery can take five minutes or more, so sit back and relax! Select your device below once discovered.") {
|
||||
input "selectedMediaRenderer", "enum", required:false, title:"Select Media Renderer (${numFound} found)", multiple:true, options:options
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
def upgradeNeeded = """To use SmartThings Labs, your Hub should be completely up to date.
|
||||
To update your Hub, access Location Settings in the Main Menu (tap the gear next to your location name), select your Hub, and choose "Update Hub"."""
|
||||
|
||||
return dynamicPage(name:"mediaRendererDiscovery", title:"Upgrade needed!", nextPage:"", install:false, uninstall: true) {
|
||||
section("Upgrade") {
|
||||
paragraph "$upgradeNeeded"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private discoverMediaRenderers()
|
||||
{
|
||||
sendHubCommand(new physicalgraph.device.HubAction("lan discovery urn:schemas-upnp-org:device:MediaRenderer:1", physicalgraph.device.Protocol.LAN))
|
||||
}
|
||||
|
||||
|
||||
private verifyMediaRendererPlayer() {
|
||||
def devices = getMediaRendererPlayer().findAll { it?.value?.verified != true }
|
||||
|
||||
devices.each {
|
||||
verifyMediaRenderer((it?.value?.ip + ":" + it?.value?.port), it?.value?.ssdpPath)
|
||||
}
|
||||
}
|
||||
|
||||
private verifyMediaRenderer(String deviceNetworkId, String ssdpPath) {
|
||||
String ip = getHostAddress(deviceNetworkId)
|
||||
if(!ssdpPath){
|
||||
ssdpPath = "/"
|
||||
}
|
||||
log.trace "verifyMediaRenderer($deviceNetworkId, $ssdpPath, $ip)"
|
||||
sendHubCommand(new physicalgraph.device.HubAction("""GET $ssdpPath HTTP/1.1\r\nHOST: $ip\r\n\r\n""", physicalgraph.device.Protocol.LAN, "${deviceNetworkId}"))
|
||||
}
|
||||
|
||||
Map mediaRenderersDiscovered() {
|
||||
def vmediaRenderers = getVerifiedMediaRendererPlayer()
|
||||
def map = [:]
|
||||
vmediaRenderers.each {
|
||||
def value = "${it.value.name}"
|
||||
def key = it.value.ip + ":" + it.value.port
|
||||
map["${key}"] = value
|
||||
}
|
||||
map
|
||||
}
|
||||
|
||||
def getMediaRendererPlayer()
|
||||
{
|
||||
state.mediaRenderers = state.mediaRenderers ?: [:]
|
||||
}
|
||||
|
||||
def getVerifiedMediaRendererPlayer()
|
||||
{
|
||||
getMediaRendererPlayer().findAll{ it?.value?.verified == true }
|
||||
}
|
||||
|
||||
def installed() {
|
||||
log.trace "installed()"
|
||||
//initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.trace "updated()"
|
||||
|
||||
|
||||
if (selectedMediaRenderer) {
|
||||
addMediaRenderer()
|
||||
}
|
||||
|
||||
unsubscribe()
|
||||
state.subscribe = false
|
||||
unschedule()
|
||||
scheduleTimer()
|
||||
scheduleActions()
|
||||
|
||||
refreshAll()
|
||||
syncDevices()
|
||||
}
|
||||
|
||||
def uninstalled() {
|
||||
def devices = getChildDevices()
|
||||
devices.each {
|
||||
deleteChildDevice(it.deviceNetworkId)
|
||||
}
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
// remove location subscription aftwards
|
||||
log.trace "initialize()"
|
||||
//scheduledRefreshHandler()
|
||||
}
|
||||
|
||||
|
||||
def scheduledRefreshHandler(){
|
||||
|
||||
}
|
||||
|
||||
def scheduledTimerHandler() {
|
||||
timerAll()
|
||||
}
|
||||
|
||||
def scheduledActionsHandler() {
|
||||
syncDevices()
|
||||
//runIn(60, scheduledRefreshHandler)
|
||||
}
|
||||
|
||||
private scheduleTimer() {
|
||||
def cron = "0 0/3 * * * ?"
|
||||
schedule(cron, scheduledTimerHandler)
|
||||
}
|
||||
|
||||
private scheduleActions() {
|
||||
def minutes = Math.max(settings.refreshMRInterval.toInteger(),1)
|
||||
def cron = "0 0/${minutes} * * * ?"
|
||||
schedule(cron, scheduledActionsHandler)
|
||||
}
|
||||
|
||||
private syncDevices() {
|
||||
log.debug "syncDevices()"
|
||||
if(!state.subscribe) {
|
||||
subscribe(location, null, locationHandler, [filterEvents:false])
|
||||
log.trace "subscribe($location, null, locationHandler, [filterEvents:false])"
|
||||
state.subscribe = true
|
||||
}
|
||||
|
||||
discoverMediaRenderers()
|
||||
}
|
||||
|
||||
private timerAll(){
|
||||
childDevices*.poll()
|
||||
}
|
||||
|
||||
private refreshAll(){
|
||||
childDevices*.refresh()
|
||||
}
|
||||
|
||||
def addMediaRenderer() {
|
||||
def players = getVerifiedMediaRendererPlayer()
|
||||
def runSubscribe = false
|
||||
selectedMediaRenderer.each { dni ->
|
||||
def d = getChildDevice(dni)
|
||||
if(!d) {
|
||||
def newPlayer = players.find { (it.value.ip + ":" + it.value.port) == dni }
|
||||
if (newPlayer){
|
||||
d = addChildDevice("mujica", "DLNA Player", dni, newPlayer?.value.hub, [label:"${newPlayer?.value.name} Speaker","data":["model":newPlayer?.value.model,"avtcurl":newPlayer?.value.avtcurl,"avteurl":newPlayer?.value.avteurl,"rccurl":newPlayer?.value.rccurl,"rceurl":newPlayer?.value.rceurl,"udn":newPlayer?.value.udn,"dni":dni]])
|
||||
}
|
||||
runSubscribe = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def locationHandler(evt) {
|
||||
def description = evt.description
|
||||
def hub = evt?.hubId
|
||||
def parsedEvent = parseEventMessage(description)
|
||||
def msg = parseLanMessage(description)
|
||||
|
||||
if (msg?.headers?.sid)
|
||||
{
|
||||
childDevices*.each { childDevice ->
|
||||
if(childDevice.getDataValue('subscriptionId') == ((msg?.headers?.sid ?:"") - "uuid:")|| childDevice.getDataValue('subscriptionId1') == ((msg?.headers?.sid ?:"") - "uuid:")){
|
||||
childDevice.parse(description)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
parsedEvent << ["hub":hub]
|
||||
|
||||
if (parsedEvent?.ssdpTerm?.contains("urn:schemas-upnp-org:device:MediaRenderer:1"))
|
||||
{ //SSDP DISCOVERY EVENTS
|
||||
log.debug "MediaRenderer device found" + parsedEvent
|
||||
def mediaRenderers = getMediaRendererPlayer()
|
||||
|
||||
|
||||
if (!(mediaRenderers."${parsedEvent.ssdpUSN.toString()}"))
|
||||
{ //mediaRenderer does not exist
|
||||
mediaRenderers << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent]
|
||||
}
|
||||
else
|
||||
{ // update the values
|
||||
|
||||
def d = mediaRenderers."${parsedEvent.ssdpUSN.toString()}"
|
||||
boolean deviceChangedValues = false
|
||||
if(d.ip != parsedEvent.ip || d.port != parsedEvent.port) {
|
||||
d.ip = parsedEvent.ip
|
||||
d.port = parsedEvent.port
|
||||
deviceChangedValues = true
|
||||
}
|
||||
if (deviceChangedValues) {
|
||||
def children = getChildDevices()
|
||||
children.each {
|
||||
if (parsedEvent.ssdpUSN.toString().contains(it.getDataValue("udn"))) {
|
||||
it.setDeviceNetworkId((parsedEvent.ip + ":" + parsedEvent.port)) //could error if device with same dni already exists
|
||||
it.updateDataValue("dni", (parsedEvent.ip + ":" + parsedEvent.port))
|
||||
it.refresh()
|
||||
log.trace "Updated Device IP"
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (parsedEvent.headers && parsedEvent.body)
|
||||
{ // MEDIARENDER RESPONSES
|
||||
def headerString = new String(parsedEvent?.headers?.decodeBase64())
|
||||
def bodyString = new String(parsedEvent.body.decodeBase64())
|
||||
|
||||
def type = (headerString =~ /Content-Type:.*/) ? (headerString =~ /Content-Type:.*/)[0] : null
|
||||
def body
|
||||
def device
|
||||
if (bodyString?.contains("xml"))
|
||||
{ // description.xml response (application/xml)
|
||||
body = new XmlSlurper().parseText(bodyString)
|
||||
log.trace "MEDIARENDER RESPONSES ${body?.device?.modelName?.text()}"
|
||||
// Avoid add sonos devices
|
||||
device = body?.device
|
||||
body?.device?.deviceList?.device?.each{
|
||||
if (it?.deviceType?.text().contains("urn:schemas-upnp-org:device:MediaRenderer:1")) {
|
||||
device = it
|
||||
}
|
||||
}
|
||||
if ( device?.deviceType?.text().contains("urn:schemas-upnp-org:device:MediaRenderer:1"))
|
||||
{
|
||||
def avtcurl = ""
|
||||
def avteurl = ""
|
||||
def rccurl = ""
|
||||
def rceurl = ""
|
||||
|
||||
|
||||
device?.serviceList?.service?.each{
|
||||
if (it?.serviceType?.text().contains("AVTransport")) {
|
||||
avtcurl = it?.controlURL?.text().startsWith("/")? it?.controlURL.text() : "/" + it?.controlURL.text()
|
||||
avteurl = it?.eventSubURL?.text().startsWith("/")? it?.eventSubURL.text() : "/" + it?.eventSubURL.text()
|
||||
}
|
||||
else if (it?.serviceType?.text().contains("RenderingControl")) {
|
||||
rccurl = it?.controlURL?.text().startsWith("/")? it?.controlURL?.text() : "/" + it?.controlURL?.text()
|
||||
rceurl = it?.eventSubURL?.text().startsWith("/")? it?.eventSubURL?.text() : "/" + it?.eventSubURL?.text()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def mediaRenderers = getMediaRendererPlayer()
|
||||
def player = mediaRenderers.find {it?.key?.contains(device?.UDN?.text())}
|
||||
if (player)
|
||||
{
|
||||
player.value << [name:device?.friendlyName?.text(),model:device?.modelName?.text(), serialNumber:device?.UDN?.text(), verified: true,avtcurl:avtcurl,avteurl:avteurl,rccurl:rccurl,rceurl:rceurl,udn:device?.UDN?.text()]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if(type?.contains("json"))
|
||||
{ //(application/json)
|
||||
body = new groovy.json.JsonSlurper().parseText(bodyString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def parseEventMessage(Map event) {
|
||||
//handles mediaRenderer attribute events
|
||||
return event
|
||||
}
|
||||
|
||||
private def parseEventMessage(String description) {
|
||||
def event = [:]
|
||||
def parts = description.split(',')
|
||||
parts.each { part ->
|
||||
part = part.trim()
|
||||
if (part.startsWith('devicetype:')) {
|
||||
def valueString = part.split(":")[1].trim()
|
||||
event.devicetype = valueString
|
||||
}
|
||||
else if (part.startsWith('mac:')) {
|
||||
def valueString = part.split(":")[1].trim()
|
||||
if (valueString) {
|
||||
event.mac = valueString
|
||||
}
|
||||
}
|
||||
else if (part.startsWith('networkAddress:')) {
|
||||
def valueString = part.split(":")[1].trim()
|
||||
if (valueString) {
|
||||
event.ip = valueString
|
||||
}
|
||||
}
|
||||
else if (part.startsWith('deviceAddress:')) {
|
||||
def valueString = part.split(":")[1].trim()
|
||||
if (valueString) {
|
||||
event.port = valueString
|
||||
}
|
||||
}
|
||||
else if (part.startsWith('ssdpPath:')) {
|
||||
def valueString = part.split(":")[1].trim()
|
||||
if (valueString) {
|
||||
event.ssdpPath = valueString
|
||||
}
|
||||
}
|
||||
else if (part.startsWith('ssdpUSN:')) {
|
||||
part -= "ssdpUSN:"
|
||||
def valueString = part.trim()
|
||||
if (valueString) {
|
||||
event.ssdpUSN = valueString
|
||||
}
|
||||
}
|
||||
else if (part.startsWith('ssdpTerm:')) {
|
||||
part -= "ssdpTerm:"
|
||||
def valueString = part.trim()
|
||||
if (valueString) {
|
||||
event.ssdpTerm = valueString
|
||||
}
|
||||
}
|
||||
else if (part.startsWith('headers')) {
|
||||
part -= "headers:"
|
||||
def valueString = part.trim()
|
||||
if (valueString) {
|
||||
event.headers = valueString
|
||||
}
|
||||
}
|
||||
else if (part.startsWith('body')) {
|
||||
part -= "body:"
|
||||
def valueString = part.trim()
|
||||
if (valueString) {
|
||||
event.body = valueString
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.devicetype == "04" && event.ssdpPath =~ /[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}/ && !event.ssdpUSN && !event.ssdpTerm){
|
||||
def matcher = event.ssdpPath =~ /[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}/
|
||||
def ssdpUSN = matcher[0]
|
||||
event.ssdpUSN = "uuid:$ssdpUSN::urn:schemas-upnp-org:device:MediaRenderer:1"
|
||||
event.ssdpTerm = "urn:schemas-upnp-org:device:MediaRenderer:1"
|
||||
}
|
||||
event
|
||||
}
|
||||
|
||||
|
||||
/////////CHILD DEVICE METHODS
|
||||
def parse(childDevice, description) {
|
||||
def parsedEvent = parseEventMessage(description)
|
||||
|
||||
if (parsedEvent.headers && parsedEvent.body) {
|
||||
def headerString = new String(parsedEvent.headers.decodeBase64())
|
||||
def bodyString = new String(parsedEvent.body.decodeBase64())
|
||||
|
||||
def body = new groovy.json.JsonSlurper().parseText(bodyString)
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
private Integer convertHexToInt(hex) {
|
||||
Integer.parseInt(hex,16)
|
||||
}
|
||||
|
||||
private String convertHexToIP(hex) {
|
||||
[convertHexToInt(hex[0..1]),convertHexToInt(hex[2..3]),convertHexToInt(hex[4..5]),convertHexToInt(hex[6..7])].join(".")
|
||||
}
|
||||
|
||||
private getHostAddress(d) {
|
||||
def parts = d.split(":")
|
||||
def ip = convertHexToIP(parts[0])
|
||||
def port = convertHexToInt(parts[1])
|
||||
return ip + ":" + port
|
||||
}
|
||||
|
||||
private Boolean canInstallLabs()
|
||||
{
|
||||
return hasAllHubsOver("000.011.00603")
|
||||
}
|
||||
|
||||
private Boolean hasAllHubsOver(String desiredFirmware)
|
||||
{
|
||||
return realHubFirmwareVersions.every { fw -> fw >= desiredFirmware }
|
||||
}
|
||||
|
||||
private List getRealHubFirmwareVersions()
|
||||
{
|
||||
return location.hubs*.firmwareVersionString.findAll { it }
|
||||
}
|
||||
Reference in New Issue
Block a user