mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-23 13:14:11 +00:00
Compare commits
2 Commits
MSA-1864-1
...
PROD_2017.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f944df598 | ||
|
|
a06dba0b90 |
@@ -1,2 +0,0 @@
|
|||||||
.st-ignore
|
|
||||||
README.md
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Keen Home Smart Vent
|
|
||||||
|
|
||||||
Cloud Execution
|
|
||||||
|
|
||||||
Works with:
|
|
||||||
|
|
||||||
* [Keen Home Smart Vent](https://www.smartthings.com/works-with-smartthings/keen-home/keen-home-smart-vent)
|
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
* [Capabilities](#capabilities)
|
|
||||||
* [Health](#device-health)
|
|
||||||
* [Troubleshooting](#Troubleshooting)
|
|
||||||
|
|
||||||
## Capabilities
|
|
||||||
|
|
||||||
* **Switch** - can detect state (possible values: on/off)
|
|
||||||
* **Switch Level** - represents current light level, usually 0-100 in percent
|
|
||||||
* **Sensor** - detects sensor events
|
|
||||||
* **Temperature Measurement** - represents capability to measure temperature
|
|
||||||
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
|
|
||||||
* **Battery** - defines device uses a battery
|
|
||||||
* **Refresh** - _refresh()_ command for status updates
|
|
||||||
* **Health Check** - indicates ability to get device health notifications
|
|
||||||
|
|
||||||
## Device Health
|
|
||||||
|
|
||||||
Keen Home Smart Vent with reporting interval of 10 mins.
|
|
||||||
SmartThings platform will ping the device after `checkInterval` seconds of inactivity in last attempt to reach the device before marking it `OFFLINE`
|
|
||||||
|
|
||||||
* __22min__ checkInterval
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the sensor is out of range.
|
|
||||||
Pairing needs to be tried again by placing the sensor closer to the hub.
|
|
||||||
Instructions related to pairing, resetting and removing the different motion sensors from SmartThings can be found in the following links
|
|
||||||
for the different models:
|
|
||||||
* [Keen Home Smart Vent Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/205302050-Keen-Home-Smart-Vent)
|
|
||||||
@@ -11,7 +11,6 @@ metadata {
|
|||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
capability "Temperature Measurement"
|
capability "Temperature Measurement"
|
||||||
capability "Battery"
|
capability "Battery"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
command "getLevel"
|
command "getLevel"
|
||||||
command "getOnOff"
|
command "getOnOff"
|
||||||
@@ -21,8 +20,10 @@ metadata {
|
|||||||
command "setZigBeeIdTile"
|
command "setZigBeeIdTile"
|
||||||
command "clearObstruction"
|
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",
|
||||||
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"
|
profileId: "0104",
|
||||||
|
inClusters: "0000,0001,0003,0004,0005,0006,0008,0020,0402,0403,0B05,FC01,FC02",
|
||||||
|
outClusters: "0019"
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulator metadata
|
// simulator metadata
|
||||||
@@ -465,27 +466,15 @@ def refresh() {
|
|||||||
getBattery()
|
getBattery()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* PING is used by Device-Watch in attempt to reach the Device
|
|
||||||
* */
|
|
||||||
def ping() {
|
|
||||||
return refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
log.debug "CONFIGURE"
|
log.debug "CONFIGURE"
|
||||||
|
|
||||||
// Device-Watch allows 2 check-in misses from device + ping (plus 1 min lag time)
|
|
||||||
// enrolls with default periodic reporting until newer 5 min interval is confirmed
|
|
||||||
sendEvent(name: "checkInterval", value: 2 * 10 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
|
|
||||||
// get ZigBee ID by hidden tile because that's the only way we can do it
|
// get ZigBee ID by hidden tile because that's the only way we can do it
|
||||||
setZigBeeIdTile()
|
setZigBeeIdTile()
|
||||||
|
|
||||||
def configCmds = [
|
def configCmds = [
|
||||||
// bind reporting clusters to hub
|
// bind reporting clusters to hub
|
||||||
//commenting out switch cluster bind as using wrapper onOffConfig of zigbee class
|
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0006 {${device.zigbeeId}} {}", "delay 500",
|
||||||
//"zdo bind 0x${device.deviceNetworkId} 1 1 0x0006 {${device.zigbeeId}} {}", "delay 500",
|
|
||||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0008 {${device.zigbeeId}} {}", "delay 500",
|
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0008 {${device.zigbeeId}} {}", "delay 500",
|
||||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0402 {${device.zigbeeId}} {}", "delay 500",
|
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0402 {${device.zigbeeId}} {}", "delay 500",
|
||||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0403 {${device.zigbeeId}} {}", "delay 500",
|
"zdo bind 0x${device.deviceNetworkId} 1 1 0x0403 {${device.zigbeeId}} {}", "delay 500",
|
||||||
@@ -521,5 +510,5 @@ def configure() {
|
|||||||
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
// "send 0x${device.deviceNetworkId} 1 1", "delay 1500",
|
||||||
]
|
]
|
||||||
|
|
||||||
return configCmds + zigbee.onOffConfig() + refresh()
|
return configCmds + refresh()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ metadata {
|
|||||||
capability "Refresh"
|
capability "Refresh"
|
||||||
capability "Music Player"
|
capability "Music Player"
|
||||||
capability "Health Check"
|
capability "Health Check"
|
||||||
capability "Sensor"
|
|
||||||
capability "Actuator"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define all commands, ie, if you have a custom action not
|
* Define all commands, ie, if you have a custom action not
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
.st-ignore
|
|
||||||
README.md
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# EcoNet Vent
|
|
||||||
|
|
||||||
Cloud Execution
|
|
||||||
|
|
||||||
Works with:
|
|
||||||
|
|
||||||
* [EcoNet Controls Z-Wave Vent](https://www.smartthings.com/works-with-smartthings/econet-controls/econet-controls-z-wave-vent)
|
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
* [Capabilities](#capabilities)
|
|
||||||
* [Health](#device-health)
|
|
||||||
* [Troubleshooting](#troubleshooting)
|
|
||||||
|
|
||||||
## Capabilities
|
|
||||||
|
|
||||||
* **Switch Level** - allows for the control of the level attribute of a light
|
|
||||||
* **Actuator** - represents that a Device has commands
|
|
||||||
* **Switch** - allows for the control of a switch device
|
|
||||||
* **Battery** - defines that the device has a battery
|
|
||||||
* **Refresh** - _refresh()_ command for status updates
|
|
||||||
* **Sensor** - detects sensor events
|
|
||||||
* **Polling** - allows for the polling of devices that support it
|
|
||||||
* **Configuration** - allow configuration of devices that support it
|
|
||||||
* **Health Check** - indicates ability to get device health notifications
|
|
||||||
|
|
||||||
## Device Health
|
|
||||||
|
|
||||||
EcoNet Controls Z-Wave Vent 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:
|
|
||||||
* [EcoNet Controls Z-Wave Vent Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204556420-EcoNet-EV100-Vent)
|
|
||||||
@@ -26,13 +26,11 @@ metadata {
|
|||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
capability "Polling"
|
capability "Polling"
|
||||||
capability "Configuration"
|
capability "Configuration"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
command "open"
|
command "open"
|
||||||
command "close"
|
command "close"
|
||||||
|
|
||||||
fingerprint deviceId: "0x1100", inClusters: "0x26,0x72,0x86,0x77,0x80,0x20"
|
fingerprint deviceId: "0x1100", inClusters: "0x26,0x72,0x86,0x77,0x80,0x20"
|
||||||
fingerprint mfr:"0157", prod:"0100", model:"0100", deviceJoinName: "EcoNet Controls Z-Wave Vent"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
simulator {
|
simulator {
|
||||||
@@ -87,8 +85,6 @@ def parse(String description) {
|
|||||||
|
|
||||||
//send the command to stop polling
|
//send the command to stop polling
|
||||||
def updated() {
|
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("poll stop")
|
response("poll stop")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,13 +169,6 @@ def setLevel(value, duration) {
|
|||||||
setLevel(value)
|
setLevel(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* PING is used by Device-Watch in attempt to reach the Device
|
|
||||||
* */
|
|
||||||
def ping() {
|
|
||||||
refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
delayBetween([
|
delayBetween([
|
||||||
zwave.switchMultilevelV1.switchMultilevelGet().format(),
|
zwave.switchMultilevelV1.switchMultilevelGet().format(),
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
.st-ignore
|
|
||||||
README.md
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# Fibaro Door Window Sensor
|
|
||||||
|
|
||||||
Cloud Execution
|
|
||||||
|
|
||||||
Works with:
|
|
||||||
|
|
||||||
* [Fibaro Door/Window Sensor](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
|
|
||||||
|
|
||||||
* **Contact Sensor** - can detect contact (possible values: open,closed)
|
|
||||||
* **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
|
|
||||||
|
|
||||||
Fibaro Door/Window Sensor 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 Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204075194-Fibaro-Door-Window-Sensor)
|
|
||||||
@@ -39,8 +39,7 @@
|
|||||||
capability "Contact Sensor"
|
capability "Contact Sensor"
|
||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
capability "Battery"
|
capability "Battery"
|
||||||
capability "Configuration"
|
capability "Configuration"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
command "resetParams2StDefaults"
|
command "resetParams2StDefaults"
|
||||||
command "listCurrentParams"
|
command "listCurrentParams"
|
||||||
@@ -267,9 +266,6 @@ def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerS
|
|||||||
*/
|
*/
|
||||||
def configure() {
|
def configure() {
|
||||||
log.debug "Configuring Device..."
|
log.debug "Configuring Device..."
|
||||||
// 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 = []
|
def cmds = []
|
||||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 1, size: 2).format()
|
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 1, size: 2).format()
|
||||||
// send associate to group 3 to get sensor data reported only to hub
|
// send associate to group 3 to get sensor data reported only to hub
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ metadata {
|
|||||||
definition (name: "Logitech Harmony Hub C2C", namespace: "smartthings", author: "SmartThings") {
|
definition (name: "Logitech Harmony Hub C2C", namespace: "smartthings", author: "SmartThings") {
|
||||||
capability "Media Controller"
|
capability "Media Controller"
|
||||||
capability "Refresh"
|
capability "Refresh"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
command "activityoff"
|
command "activityoff"
|
||||||
command "alloff"
|
command "alloff"
|
||||||
@@ -39,16 +38,6 @@ metadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def installed() {
|
|
||||||
log.debug "installed()"
|
|
||||||
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "cloud", scheme:"untracked"]), displayed: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
def updated() {
|
|
||||||
log.debug "updated()"
|
|
||||||
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "cloud", scheme:"untracked"]), displayed: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
def startActivity(String activityId) {
|
def startActivity(String activityId) {
|
||||||
log.debug "Executing 'Start Activity'"
|
log.debug "Executing 'Start Activity'"
|
||||||
log.trace parent.activity("$device.deviceNetworkId-$activityId","start")
|
log.trace parent.activity("$device.deviceNetworkId-$activityId","start")
|
||||||
@@ -69,10 +58,6 @@ def poll() {
|
|||||||
log.trace parent.poll()
|
log.trace parent.poll()
|
||||||
}
|
}
|
||||||
|
|
||||||
def ping() {
|
|
||||||
refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
log.debug "Executing 'Refresh'"
|
log.debug "Executing 'Refresh'"
|
||||||
log.trace parent.poll()
|
log.trace parent.poll()
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
.st-ignore
|
|
||||||
README.md
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Plant Link
|
|
||||||
|
|
||||||
Cloud Execution
|
|
||||||
|
|
||||||
Works with:
|
|
||||||
|
|
||||||
* [OSO Technologies PlantLink Soil Moisture Sensor](https://www.smartthings.com/works-with-smartthings/oso-technologies/oso-technologies-plantlink-soil-moisture-sensor)
|
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
* [Capabilities](#capabilities)
|
|
||||||
* [Health](#device-health)
|
|
||||||
* [Troubleshooting](#troubleshooting)
|
|
||||||
|
|
||||||
## Capabilities
|
|
||||||
|
|
||||||
* **Relative Humidity Measurement** - allows reading the relative humidity from devices that support it
|
|
||||||
* **Sensor** - detects sensor events
|
|
||||||
* **Battery** - defines device uses a battery
|
|
||||||
* **Health Check** - indicates ability to get device health notifications
|
|
||||||
|
|
||||||
## Device Health
|
|
||||||
|
|
||||||
Plant Link sensor is a Z-wave sleepy device and checks in every 15 minutes.
|
|
||||||
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins.
|
|
||||||
|
|
||||||
* __32min__ checkInterval
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the sensor is out of range.
|
|
||||||
Pairing needs to be tried again by placing the sensor closer to the hub.
|
|
||||||
Instructions related to pairing, resetting and removing the different motion sensors from SmartThings can be found in the following links
|
|
||||||
for the different models:
|
|
||||||
* [OSO Technologies PlantLink Soil Moisture Sensor Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206868986-PlantLink-Soil-Moisture-Sensor)
|
|
||||||
@@ -21,10 +21,8 @@ metadata {
|
|||||||
capability "Relative Humidity Measurement"
|
capability "Relative Humidity Measurement"
|
||||||
capability "Battery"
|
capability "Battery"
|
||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
fingerprint profileId: "0104", inClusters: "0000,0003,0405,FC08", outClusters: "0003"
|
fingerprint profileId: "0104", inClusters: "0000,0003,0405,FC08", outClusters: "0003"
|
||||||
fingerprint endpoint: "1", profileId: "0104", inClusters: "0000,0001,0003,0B04", outClusters: "0003", manufacturer: "", model: "", deviceJoinName: "OSO Technologies PlantLink Soil Moisture Sensor"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tiles {
|
tiles {
|
||||||
@@ -50,11 +48,6 @@ metadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def updated() {
|
|
||||||
// Device-Watch allows 2 check-in misses from device
|
|
||||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse incoming device messages to generate events
|
// Parse incoming device messages to generate events
|
||||||
def parse(String description) {
|
def parse(String description) {
|
||||||
log.debug "Parse description $description"
|
log.debug "Parse description $description"
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
.st-ignore
|
|
||||||
README.md
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# Smartsense Moisture
|
|
||||||
|
|
||||||
Cloud Execution
|
|
||||||
|
|
||||||
Works with:
|
|
||||||
|
|
||||||
* [FortrezZ Moisture Sensor](https://www.smartthings.com/works-with-smartthings/fortrezz/fortrezz-moisture-sensor)
|
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
* [Capabilities](#capabilities)
|
|
||||||
* [Health](#device-health)
|
|
||||||
* [Troubleshooting](#troubleshooting)
|
|
||||||
|
|
||||||
## Capabilities
|
|
||||||
|
|
||||||
* **Water Sensor** - can detect presence of water (dry or wet)
|
|
||||||
* **Sensor** - detects sensor events
|
|
||||||
* **Battery** - defines device uses a battery
|
|
||||||
* **Temperature Measurement** - represents capability to measure temperature
|
|
||||||
* **Health Check** - indicates ability to get device health notifications
|
|
||||||
|
|
||||||
## Device Health
|
|
||||||
|
|
||||||
Smartsense Moisture is a Z-wave sleepy device type and checks in 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
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the sensor is out of range.
|
|
||||||
Pairing needs to be tried again by placing the sensor closer to the hub.
|
|
||||||
Instructions related to pairing, resetting and removing the different motion sensors from SmartThings can be found in the following links
|
|
||||||
for the different models:
|
|
||||||
* [FortrezZ Moisture Sensor Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200930740-FortrezZ-Moisture-Sensor)
|
|
||||||
@@ -17,11 +17,9 @@ metadata {
|
|||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
capability "Battery"
|
capability "Battery"
|
||||||
capability "Temperature Measurement"
|
capability "Temperature Measurement"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
fingerprint deviceId: "0x2001", inClusters: "0x30,0x9C,0x9D,0x85,0x80,0x72,0x31,0x84,0x86"
|
fingerprint deviceId: "0x2001", inClusters: "0x30,0x9C,0x9D,0x85,0x80,0x72,0x31,0x84,0x86"
|
||||||
fingerprint deviceId: "0x2101", inClusters: "0x71,0x70,0x85,0x80,0x72,0x31,0x84,0x86"
|
fingerprint deviceId: "0x2101", inClusters: "0x71,0x70,0x85,0x80,0x72,0x31,0x84,0x86"
|
||||||
fingerprint mfr:"0084", prod:"0063", model:"010C", deviceJoinName: "FortrezZ Moisture Sensor"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
simulator {
|
simulator {
|
||||||
@@ -91,11 +89,6 @@ def parse(String description) {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
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])
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
|
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
|
||||||
{
|
{
|
||||||
[descriptionText: "${device.displayName} woke up", isStateChange: false]
|
[descriptionText: "${device.displayName} woke up", isStateChange: false]
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ metadata {
|
|||||||
tiles(scale: 2) {
|
tiles(scale: 2) {
|
||||||
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
|
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
|
||||||
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
|
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
|
||||||
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13"
|
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"##e86d13"
|
||||||
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc"
|
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ metadata {
|
|||||||
capability "Refresh"
|
capability "Refresh"
|
||||||
capability "Temperature Measurement"
|
capability "Temperature Measurement"
|
||||||
capability "Health Check"
|
capability "Health Check"
|
||||||
capability "Sensor"
|
|
||||||
|
|
||||||
command "enrollResponse"
|
command "enrollResponse"
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
.st-ignore
|
|
||||||
README.md
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Leviton Switch (ZigBee)
|
|
||||||
|
|
||||||
Cloud Execution
|
|
||||||
|
|
||||||
Works with:
|
|
||||||
|
|
||||||
* [Leviton Switch (ZigBee)](https://www.smartthings.com/works-with-smartthings/leviton/leviton-switch)
|
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
* [Capabilities](#capabilities)
|
|
||||||
* [Health](#device-health)
|
|
||||||
* [Troubleshooting](#Troubleshooting)
|
|
||||||
|
|
||||||
## Capabilities
|
|
||||||
|
|
||||||
* **Actuator** - represents that a Device has commands
|
|
||||||
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
|
|
||||||
* **Refresh** - _refresh()_ command for status updates
|
|
||||||
* **Switch** - can detect state (possible values: on/off)
|
|
||||||
* **Health Check** - indicates ability to get device health notifications
|
|
||||||
|
|
||||||
## Device Health
|
|
||||||
|
|
||||||
A Zigbee Switch with reporting interval of 10 mins.
|
|
||||||
SmartThings platform will ping the device after `checkInterval` seconds of inactivity in last attempt to reach the device before marking it `OFFLINE`
|
|
||||||
|
|
||||||
* __22min__ 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:
|
|
||||||
* [Leviton Switch Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/209686003-How-to-connect-Leviton-ZigBee-devices)
|
|
||||||
@@ -18,7 +18,6 @@ metadata {
|
|||||||
capability "Configuration"
|
capability "Configuration"
|
||||||
capability "Refresh"
|
capability "Refresh"
|
||||||
capability "Switch"
|
capability "Switch"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006"
|
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006"
|
||||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0006", outClusters: "0003, 0006, 0019, 0406", manufacturer: "Leviton", model: "ZSS-10", deviceJoinName: "Leviton Switch"
|
fingerprint profileId: "0104", inClusters: "0000, 0003, 0006", outClusters: "0003, 0006, 0019, 0406", manufacturer: "Leviton", model: "ZSS-10", deviceJoinName: "Leviton Switch"
|
||||||
@@ -76,20 +75,11 @@ def on() {
|
|||||||
zigbee.on()
|
zigbee.on()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* PING is used by Device-Watch in attempt to reach the Device
|
|
||||||
* */
|
|
||||||
def ping() {
|
|
||||||
return refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
zigbee.onOffRefresh() + zigbee.onOffConfig()
|
zigbee.onOffRefresh() + zigbee.onOffConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
// Device-Watch allows 2 check-in misses from device + ping (plus 2 min lag time)
|
|
||||||
sendEvent(name: "checkInterval", value: 2 * 10 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
log.debug "Configuring Reporting and Bindings."
|
log.debug "Configuring Reporting and Bindings."
|
||||||
zigbee.onOffRefresh() + zigbee.onOffConfig()
|
zigbee.onOffRefresh() + zigbee.onOffConfig()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
/**
|
|
||||||
* Zooz Power Strip Outlet
|
|
||||||
*
|
|
||||||
* Copyright 2017 SmartThings
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License. You may obtain a copy of the License at:
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
|
||||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
metadata {
|
|
||||||
definition (name: "Zooz Power Strip Outlet", namespace: "smartthings", author: "SmartThings") {
|
|
||||||
capability "Switch"
|
|
||||||
capability "Actuator"
|
|
||||||
capability "Sensor"
|
|
||||||
}
|
|
||||||
|
|
||||||
tiles {
|
|
||||||
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
|
|
||||||
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
|
|
||||||
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState:"turningOn"
|
|
||||||
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC", nextState:"turningOff"
|
|
||||||
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff"
|
|
||||||
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void on() {
|
|
||||||
parent.childOn(device.deviceNetworkId)
|
|
||||||
}
|
|
||||||
|
|
||||||
void off() {
|
|
||||||
parent.childOff(device.deviceNetworkId)
|
|
||||||
}
|
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
/**
|
|
||||||
* Zooz ZEN20 Power Strip Outlet
|
|
||||||
*
|
|
||||||
* Implementation of the Zooz ZEN20 power strip that uses the new composite device capabilities to provide individual
|
|
||||||
* control of each outlet from SmartApps as well as the mobile app. Incorporates contributions from:
|
|
||||||
*
|
|
||||||
* Eric Maycock (https://github.com/erocm123/SmartThingsPublic/blob/master/devicetypes/erocm123/zooz-power-strip.src/zooz-power-strip.groovy)
|
|
||||||
* Robert Vandervoort (https://github.com/robertvandervoort/SmartThings/blob/master/zooZ-Strip-ZEN20/device_type-zooZ-strip-ZEN20_v1.0)
|
|
||||||
*
|
|
||||||
* Copyright 2017 SmartThings
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
||||||
* in compliance with the License. You may obtain a copy of the License at:
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
|
||||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing permissions and limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
metadata {
|
|
||||||
definition (name: "Zooz Power Strip", namespace: "smartthings", author: "SmartThings") {
|
|
||||||
capability "Switch"
|
|
||||||
capability "Refresh"
|
|
||||||
capability "Actuator"
|
|
||||||
capability "Sensor"
|
|
||||||
|
|
||||||
fingerprint manufacturer: "015D", prod: "0651", model: "F51C", deviceJoinName: "Zooz ZEN 20 Power Strip"
|
|
||||||
}
|
|
||||||
|
|
||||||
tiles {
|
|
||||||
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
|
|
||||||
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
|
|
||||||
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState:"turningOn"
|
|
||||||
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC", nextState:"turningOff"
|
|
||||||
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff"
|
|
||||||
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
childDeviceTiles("outlets")
|
|
||||||
standardTile("refresh", "device.switch", width: 1, height: 1, inactiveLabel: false, decoration: "flat") {
|
|
||||||
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////
|
|
||||||
// Installation and update //
|
|
||||||
/////////////////////////////
|
|
||||||
def installed() {
|
|
||||||
createChildDevices()
|
|
||||||
}
|
|
||||||
|
|
||||||
def updated() {
|
|
||||||
if (!childDevices) {
|
|
||||||
createChildDevices()
|
|
||||||
}
|
|
||||||
else if (device.label != state.oldLabel) {
|
|
||||||
childDevices.each {
|
|
||||||
def newLabel = "${device.displayName} (CH${channelNumber(it.deviceNetworkId)})"
|
|
||||||
it.setLabel(newLabel)
|
|
||||||
}
|
|
||||||
state.oldLabel = device.label
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////
|
|
||||||
// Event Generation //
|
|
||||||
//////////////////////
|
|
||||||
def parse(String description) {
|
|
||||||
trace "parse('$description')"
|
|
||||||
def result = []
|
|
||||||
if (description.startsWith("Err")) {
|
|
||||||
result = createEvent(descriptionText:description, isStateChange:true)
|
|
||||||
} else if (description != "updated") {
|
|
||||||
def cmd = zwave.parse(description, [0x60: 3, 0x32: 3, 0x25: 1, 0x20: 1])
|
|
||||||
if (cmd) {
|
|
||||||
result += zwaveEvent(cmd, 1)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log.warn "Unparsed description $description"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd, ep) {
|
|
||||||
def encapsulatedCommand = cmd.encapsulatedCommand([0x32: 3, 0x25: 1, 0x20: 1])
|
|
||||||
if (encapsulatedCommand) {
|
|
||||||
zwaveEvent(encapsulatedCommand, cmd.sourceEndPoint as Integer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd, endpoint) {
|
|
||||||
trace "zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport $cmd, $endpoint)"
|
|
||||||
zwaveBinaryEvent(cmd, endpoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd, endpoint) {
|
|
||||||
trace "zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport $cmd, $endpoint)"
|
|
||||||
zwaveBinaryEvent(cmd, endpoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (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
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd, ep) {
|
|
||||||
updateDataValue("MSR", String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId))
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd, ep) {
|
|
||||||
trace "applicationVersion $cmd.applicationVersion"
|
|
||||||
}
|
|
||||||
|
|
||||||
def zwaveEvent(physicalgraph.zwave.Command cmd, ep) {
|
|
||||||
log.warn("${device.displayName}: Unhandled ${cmd}" + (ep ? " from endpoint $ep" : ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////
|
|
||||||
// Installation and update //
|
|
||||||
/////////////////////////////
|
|
||||||
def on() {
|
|
||||||
def cmds = []
|
|
||||||
def cmd = zwave.switchBinaryV1.switchBinarySet(switchValue: 0xFF)
|
|
||||||
cmds << zwave.multiChannelV3.multiChannelCmdEncap(bitAddress: true, destinationEndPoint:0x1F).encapsulate(cmd).format()
|
|
||||||
cmds << "delay 400"
|
|
||||||
cmds.addAll(refresh())
|
|
||||||
return cmds
|
|
||||||
}
|
|
||||||
|
|
||||||
def off() {
|
|
||||||
def cmds = []
|
|
||||||
def cmd = zwave.switchBinaryV1.switchBinarySet(switchValue: 0x00)
|
|
||||||
cmds << zwave.multiChannelV3.multiChannelCmdEncap(bitAddress: true, destinationEndPoint:0x1F).encapsulate(cmd).format()
|
|
||||||
cmds << "delay 400"
|
|
||||||
cmds.addAll(refresh())
|
|
||||||
return cmds
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////
|
|
||||||
// Child Device API //
|
|
||||||
//////////////////////
|
|
||||||
void childOn(String dni) {
|
|
||||||
onOffCmd(0xFF, channelNumber(dni))
|
|
||||||
}
|
|
||||||
|
|
||||||
void childOff(String dni) {
|
|
||||||
onOffCmd(0, channelNumber(dni))
|
|
||||||
}
|
|
||||||
|
|
||||||
def refresh() {
|
|
||||||
def cmds = (1..5).collect { endpoint ->
|
|
||||||
encap(zwave.switchBinaryV1.switchBinaryGet(), endpoint)
|
|
||||||
}
|
|
||||||
delayBetween(cmds, 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////
|
|
||||||
// Local Methods //
|
|
||||||
///////////////////
|
|
||||||
private channelNumber(String dni) {
|
|
||||||
dni.split("-ep")[-1] as Integer
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onOffCmd(value, endpoint = null) {
|
|
||||||
def actions = [
|
|
||||||
new physicalgraph.device.HubAction(encap(zwave.basicV1.basicSet(value: value), endpoint)),
|
|
||||||
new physicalgraph.device.HubAction(encap(zwave.switchBinaryV1.switchBinaryGet(), endpoint)),
|
|
||||||
]
|
|
||||||
sendHubCommand(actions, 500)
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createChildDevices() {
|
|
||||||
state.oldLabel = device.label
|
|
||||||
for (i in 1..5) {
|
|
||||||
addChildDevice("Zooz Power Strip Outlet", "${device.deviceNetworkId}-ep${i}", null,
|
|
||||||
[completedSetup: true, label: "${device.displayName} (CH${i})",
|
|
||||||
isComponent: true, componentName: "ch$i", componentLabel: "Channel $i"])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private encap(cmd, endpoint) {
|
|
||||||
if (endpoint) {
|
|
||||||
zwave.multiChannelV3.multiChannelCmdEncap(destinationEndPoint:endpoint).encapsulate(cmd).format()
|
|
||||||
} else {
|
|
||||||
cmd.format()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private trace(msg) {
|
|
||||||
//log.trace(msg)
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
.st-ignore
|
|
||||||
README.md
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# Z-Wave Door Window Sensor
|
|
||||||
|
|
||||||
Cloud Execution
|
|
||||||
|
|
||||||
Works with:
|
|
||||||
|
|
||||||
* [Aeon Labs Door/Window Sensor (Gen 5)](https://www.smartthings.com/works-with-smartthings/aeon-labs/aeon-labs-doorwindow-sensor-gen-5)
|
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
* [Capabilities](#capabilities)
|
|
||||||
* [Health](#device-health)
|
|
||||||
* [Troubleshooting](#Troubleshooting)
|
|
||||||
|
|
||||||
## Capabilities
|
|
||||||
|
|
||||||
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
|
|
||||||
* **Health Check** - indicates ability to get device health notifications
|
|
||||||
* **Sensor** - detects sensor events
|
|
||||||
* **Battery** - defines that the device has a battery
|
|
||||||
* **Contact Sensor** - allows reading the value of a contact sensor device
|
|
||||||
|
|
||||||
## Device Health
|
|
||||||
|
|
||||||
Z-Wave Door Window Sensor is a Z-wave sleepy device and checks in 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
|
|
||||||
|
|
||||||
## 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 links
|
|
||||||
for the different models:
|
|
||||||
* [Aeon Labs Door/Window Sensor (Gen 5) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/211834163-How-to-connect-Aeon-Labs-door-window-sensors)
|
|
||||||
@@ -22,14 +22,12 @@ metadata {
|
|||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
capability "Battery"
|
capability "Battery"
|
||||||
capability "Configuration"
|
capability "Configuration"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x85,0x86,0x72"
|
fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x85,0x86,0x72"
|
||||||
fingerprint deviceId: "0x07", inClusters: "0x30"
|
fingerprint deviceId: "0x07", inClusters: "0x30"
|
||||||
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x98"
|
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x98"
|
||||||
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
|
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
|
||||||
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x80,0x71,0x85,0x70,0x72,0x86,0x30,0x31,0x84,0x59,0x73,0x5A,0x8F,0x98,0x7A", outClusters:"0x20" // Philio multi+
|
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x80,0x71,0x85,0x70,0x72,0x86,0x30,0x31,0x84,0x59,0x73,0x5A,0x8F,0x98,0x7A", outClusters:"0x20" // Philio multi+
|
||||||
fingerprint mfr:"0086", prod:"0002", model:"001D", deviceJoinName: "Aeon Labs Door/Window Sensor (Gen 5)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulator metadata
|
// simulator metadata
|
||||||
@@ -80,8 +78,6 @@ def parse(String description) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def updated() {
|
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])
|
|
||||||
def cmds = []
|
def cmds = []
|
||||||
if (!state.MSR) {
|
if (!state.MSR) {
|
||||||
cmds = [
|
cmds = [
|
||||||
|
|||||||
@@ -22,12 +22,10 @@ metadata {
|
|||||||
capability "Configuration"
|
capability "Configuration"
|
||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
capability "Light"
|
capability "Light"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
command "reset"
|
command "reset"
|
||||||
|
|
||||||
fingerprint inClusters: "0x25,0x32"
|
fingerprint inClusters: "0x25,0x32"
|
||||||
fingerprint mfr:"0086", prod:"0003", model:"0012", deviceJoinName: "Aeon Labs Micro Smart Switch 2E"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulator metadata
|
// simulator metadata
|
||||||
@@ -75,8 +73,6 @@ metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def updated() {
|
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])
|
|
||||||
try {
|
try {
|
||||||
if (!state.MSR) {
|
if (!state.MSR) {
|
||||||
response(zwave.manufacturerSpecificV2.manufacturerSpecificGet().format())
|
response(zwave.manufacturerSpecificV2.manufacturerSpecificGet().format())
|
||||||
@@ -183,14 +179,6 @@ def poll() {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* PING is used by Device-Watch in attempt to reach the Device
|
|
||||||
* */
|
|
||||||
def ping() {
|
|
||||||
log.debug "ping() called"
|
|
||||||
refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
def refresh() {
|
def refresh() {
|
||||||
delayBetween([
|
delayBetween([
|
||||||
zwave.switchBinaryV1.switchBinaryGet().format(),
|
zwave.switchBinaryV1.switchBinaryGet().format(),
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
.st-ignore
|
|
||||||
README.md
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# Z-wave Motion Sensor
|
|
||||||
|
|
||||||
Cloud Execution
|
|
||||||
|
|
||||||
Works with:
|
|
||||||
|
|
||||||
* [Ecolink PIR Motion Detector with Pet Immunity](https://www.smartthings.com/works-with-smartthings/sensors/ecolink-pir-motion-detector-with-pet-immunity)
|
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
* [Capabilities](#capabilities)
|
|
||||||
* [Health](#device-health)
|
|
||||||
* [Battery](#battery-specification)
|
|
||||||
* [Troubleshooting](#troubleshooting)
|
|
||||||
|
|
||||||
## Capabilities
|
|
||||||
|
|
||||||
* **Motion Sensor** - can detect motion
|
|
||||||
* **Sensor** - detects sensor events
|
|
||||||
* **Battery** - defines device uses a battery
|
|
||||||
* **Health Check** - indicates ability to get device health notifications
|
|
||||||
|
|
||||||
## Device Health
|
|
||||||
|
|
||||||
Ecolink PIR Motion Detector with Pet Immunity 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 CR123A Lithium 3V 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:
|
|
||||||
* [Ecolink PIR Motion Detector with Pet Immunity Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202294400-Ecolink-PIR-Motion-Detector-PIRZWAVE2-ECO-)
|
|
||||||
@@ -21,7 +21,6 @@ metadata {
|
|||||||
capability "Motion Sensor"
|
capability "Motion Sensor"
|
||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
capability "Battery"
|
capability "Battery"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
fingerprint mfr: "011F", prod: "0001", model: "0001", deviceJoinName: "Schlage Motion Sensor" // Schlage motion
|
fingerprint mfr: "011F", prod: "0001", model: "0001", deviceJoinName: "Schlage Motion Sensor" // Schlage motion
|
||||||
fingerprint mfr: "014A", prod: "0001", model: "0001", deviceJoinName: "Ecolink Motion Sensor" // Ecolink motion
|
fingerprint mfr: "014A", prod: "0001", model: "0001", deviceJoinName: "Ecolink Motion Sensor" // Ecolink motion
|
||||||
@@ -51,11 +50,6 @@ metadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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])
|
|
||||||
}
|
|
||||||
|
|
||||||
def parse(String description) {
|
def parse(String description) {
|
||||||
def result = null
|
def result = null
|
||||||
if (description.startsWith("Err")) {
|
if (description.startsWith("Err")) {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ metadata {
|
|||||||
capability "Configuration"
|
capability "Configuration"
|
||||||
capability "Polling"
|
capability "Polling"
|
||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
attribute "thermostatFanState", "string"
|
attribute "thermostatFanState", "string"
|
||||||
|
|
||||||
@@ -31,7 +30,6 @@ metadata {
|
|||||||
|
|
||||||
fingerprint deviceId: "0x08"
|
fingerprint deviceId: "0x08"
|
||||||
fingerprint inClusters: "0x43,0x40,0x44,0x31"
|
fingerprint inClusters: "0x43,0x40,0x44,0x31"
|
||||||
fingerprint mfr:"0039", prod:"0011", model:"0001", deviceJoinName: "Honeywell Z-Wave Thermostat"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulator metadata
|
// simulator metadata
|
||||||
@@ -125,11 +123,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 parse(String description)
|
def parse(String description)
|
||||||
{
|
{
|
||||||
def map = createEvent(zwaveEvent(zwave.parse(description, [0x42:1, 0x43:2, 0x31: 3])))
|
def map = createEvent(zwaveEvent(zwave.parse(description, [0x42:1, 0x43:2, 0x31: 3])))
|
||||||
@@ -400,14 +393,6 @@ def setCoolingSetpoint(Double degrees, Integer delay = 30000) {
|
|||||||
], delay)
|
], delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* PING is used by Device-Watch in attempt to reach the Device
|
|
||||||
* */
|
|
||||||
def ping() {
|
|
||||||
log.debug "ping() called"
|
|
||||||
poll()
|
|
||||||
}
|
|
||||||
|
|
||||||
def configure() {
|
def configure() {
|
||||||
delayBetween([
|
delayBetween([
|
||||||
zwave.thermostatModeV2.thermostatModeSupportedGet().format(),
|
zwave.thermostatModeV2.thermostatModeSupportedGet().format(),
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
.st-ignore
|
|
||||||
README.md
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
# Zen Thermostat
|
|
||||||
|
|
||||||
Cloud Execution
|
|
||||||
|
|
||||||
Works with:
|
|
||||||
|
|
||||||
* [Zen Thermostat](https://www.smartthings.com/works-with-smartthings/zen/zen-thermostat)
|
|
||||||
|
|
||||||
## Table of contents
|
|
||||||
|
|
||||||
* [Capabilities](#capabilities)
|
|
||||||
* [Health](#device-health)
|
|
||||||
|
|
||||||
## Capabilities
|
|
||||||
|
|
||||||
* **Actuator** - represents that a Device has commands
|
|
||||||
* **Thermostat** - allows for the control of a thermostat device
|
|
||||||
* **Temperature Measurement** - get the temperature from a Device that reports current temperature
|
|
||||||
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
|
|
||||||
* **Refresh** - _refresh()_ command for status updates
|
|
||||||
* **Sensor** - it represents that a Device has attributes
|
|
||||||
* **Health Check** - indicates ability to get device health notifications
|
|
||||||
|
|
||||||
## Device Health
|
|
||||||
|
|
||||||
Zen Thermostat with reporting interval of 5 mins.
|
|
||||||
SmartThings platform will ping the device after `checkInterval` seconds of inactivity in last attempt to reach the device before marking it `OFFLINE`
|
|
||||||
|
|
||||||
* __12min__ 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.
|
|
||||||
Other troubleshooting tips are listed as follows:
|
|
||||||
* [Zen Thermostat Troubleshooting:](https://support.smartthings.com/hc/en-us/articles/204356564-Zen-Thermostat)
|
|
||||||
@@ -12,9 +12,8 @@ metadata {
|
|||||||
capability "Configuration"
|
capability "Configuration"
|
||||||
capability "Refresh"
|
capability "Refresh"
|
||||||
capability "Sensor"
|
capability "Sensor"
|
||||||
capability "Health Check"
|
|
||||||
|
|
||||||
fingerprint profileId: "0104", endpointId: "01", inClusters: "0000,0001,0003,0004,0005,0020,0201,0202,0204,0B05", outClusters: "000A, 0019", manufacturer: "Zen Within", model: "Zen-01", deviceJoinName: "Zen Thermostat"
|
fingerprint profileId: "0104", endpointId: "01", inClusters: "0000,0001,0003,0004,0005,0020,0201,0202,0204,0B05", outClusters: "000A, 0019"
|
||||||
|
|
||||||
//attribute "temperatureUnit", "number"
|
//attribute "temperatureUnit", "number"
|
||||||
|
|
||||||
@@ -468,12 +467,8 @@ def fanAuto() {
|
|||||||
"st wattr 0x${device.deviceNetworkId} 1 0x202 0 0x30 {05}"
|
"st wattr 0x${device.deviceNetworkId} 1 0x202 0 0x30 {05}"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* PING is used by Device-Watch in attempt to reach the Device
|
|
||||||
* */
|
|
||||||
def ping() {
|
|
||||||
refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============== SmartThings Default Fucntions: refresh, configure, poll ===============
|
// =============== SmartThings Default Fucntions: refresh, configure, poll ===============
|
||||||
def refresh()
|
def refresh()
|
||||||
@@ -507,7 +502,6 @@ def poll()
|
|||||||
|
|
||||||
def configure()
|
def configure()
|
||||||
{
|
{
|
||||||
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
|
||||||
log.debug "configure() - binding & attribute report"
|
log.debug "configure() - binding & attribute report"
|
||||||
[
|
[
|
||||||
//Set long poll interval to 2 qs
|
//Set long poll interval to 2 qs
|
||||||
|
|||||||
@@ -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 }
|
|
||||||
}
|
|
||||||
@@ -19,15 +19,8 @@ definition(
|
|||||||
singleInstance: true) {
|
singleInstance: true) {
|
||||||
appSetting "clientId"
|
appSetting "clientId"
|
||||||
appSetting "clientSecret"
|
appSetting "clientSecret"
|
||||||
appSetting "serverUrl" // See note below
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE regarding OAuth settings. On NA01 (i.e. graph.api), NA01S, and NA01D the serverUrl app setting can be left
|
|
||||||
// Blank. For other shards is should be set to the callback URL registered with LIFX, which is:
|
|
||||||
//
|
|
||||||
// Production -- https://graph.api.smartthings.com
|
|
||||||
// Staging -- https://graph-na01s-useast1.smartthingsgdev.com
|
|
||||||
// Development -- https://graph-na01d-useast1.smartthingsgdev.com
|
|
||||||
|
|
||||||
preferences {
|
preferences {
|
||||||
page(name: "Credentials", title: "LIFX", content: "authPage", install: true)
|
page(name: "Credentials", title: "LIFX", content: "authPage", install: true)
|
||||||
@@ -42,8 +35,8 @@ mappings {
|
|||||||
path("/test") { action: [ GET: "oauthSuccess" ] }
|
path("/test") { action: [ GET: "oauthSuccess" ] }
|
||||||
}
|
}
|
||||||
|
|
||||||
def getServerUrl() { return appSettings.serverUrl ?: apiServerUrl }
|
def getServerUrl() { return "https://graph.api.smartthings.com" }
|
||||||
def getCallbackUrl() { return "${getServerUrl()}/oauth/callback" }
|
def getCallbackUrl() { return "https://graph.api.smartthings.com/oauth/callback"}
|
||||||
def apiURL(path = '/') { return "https://api.lifx.com/v1${path}" }
|
def apiURL(path = '/') { return "https://api.lifx.com/v1${path}" }
|
||||||
def getSecretKey() { return appSettings.secretKey }
|
def getSecretKey() { return appSettings.secretKey }
|
||||||
def getClientId() { return appSettings.clientId }
|
def getClientId() { return appSettings.clientId }
|
||||||
|
|||||||
@@ -511,10 +511,6 @@ def pollResponse(response, data) {
|
|||||||
if (ResponseValues) {
|
if (ResponseValues) {
|
||||||
def map = [:]
|
def map = [:]
|
||||||
ResponseValues.hubs.each {
|
ResponseValues.hubs.each {
|
||||||
// Device-Watch relies on the Logitech Harmony Cloud to get the Device state.
|
|
||||||
def isAlive = it.value.status
|
|
||||||
def d = getChildDevice("harmony-${it.key}")
|
|
||||||
d?.sendEvent(name: "DeviceWatch-DeviceStatus", value: isAlive!=504? "online":"offline", displayed: false, isStateChange: true)
|
|
||||||
if (it.value.message == "OK") {
|
if (it.value.message == "OK") {
|
||||||
map["${it.key}"] = "${it.value.response.data.currentAvActivity},${it.value.response.data.activityStatus}"
|
map["${it.key}"] = "${it.value.response.data.currentAvActivity},${it.value.response.data.activityStatus}"
|
||||||
def hub = getChildDevice("harmony-${it.key}")
|
def hub = getChildDevice("harmony-${it.key}")
|
||||||
|
|||||||
Reference in New Issue
Block a user