mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-09 05:11:52 +00:00
Compare commits
67 Commits
PROD_2017.
...
MSA-1854-3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbf8d80504 | ||
|
|
a03e8f20c5 | ||
|
|
e0d307f6b5 | ||
|
|
0ec8cba885 | ||
|
|
bcfece27c4 | ||
|
|
26f9690190 | ||
|
|
eca8fda0f2 | ||
|
|
ce07c065c8 | ||
|
|
640f9413c3 | ||
|
|
1c52f80eae | ||
|
|
de4d52a28b | ||
|
|
6892965cf1 | ||
|
|
17ec6270d6 | ||
|
|
d233a65ef5 | ||
|
|
b36a985d92 | ||
|
|
8a3c9edf0a | ||
|
|
a560c5b040 | ||
|
|
3ee374028f | ||
|
|
7ac7bd3034 | ||
|
|
f734c5490b | ||
|
|
b93a05d450 | ||
|
|
f5186a41c7 | ||
|
|
c505f95e7a | ||
|
|
173c34150a | ||
|
|
f6b850500e | ||
|
|
4dac7b5379 | ||
|
|
a79d56e467 | ||
|
|
e2d8af48a8 | ||
|
|
0f00c3c7c0 | ||
|
|
0a4d56be04 | ||
|
|
1326881142 | ||
|
|
d30494172f | ||
|
|
2678480244 | ||
|
|
b5e8a46143 | ||
|
|
6237dbd179 | ||
|
|
65f5597ccc | ||
|
|
fced2d7c61 | ||
|
|
74552420ba | ||
|
|
be0c16c76d | ||
|
|
89f1302c99 | ||
|
|
16cb20685c | ||
|
|
30d8e6d835 | ||
|
|
6d0f9d101d | ||
|
|
4ba55e7f0a | ||
|
|
8a41fb6090 | ||
|
|
79c254cfac | ||
|
|
72248b0004 | ||
|
|
d8b35b23ea | ||
|
|
9a53e12427 | ||
|
|
7a7a08ea6e | ||
|
|
950a33dc74 | ||
|
|
2ae163b10b | ||
|
|
e3168793bd | ||
|
|
0baa986c61 | ||
|
|
8484f18a0e | ||
|
|
3c4d86bb31 | ||
|
|
1f69ab6634 | ||
|
|
b0ac006781 | ||
|
|
ef1ebc8347 | ||
|
|
aa1f2f21e8 | ||
|
|
cb6377886d | ||
|
|
a544e2f019 | ||
|
|
a777c298ca | ||
|
|
65ae2c0ddf | ||
|
|
a583a25ef3 | ||
|
|
a15ca97988 | ||
|
|
648dee90b6 |
@@ -22,28 +22,29 @@ metadata {
|
||||
capability "Temperature Measurement"
|
||||
capability "Water Sensor"
|
||||
capability "Health Check"
|
||||
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x22, 0x85, 0x59, 0x20, 0x80, 0x70, 0x56, 0x5A, 0x7A, 0x72, 0x8E, 0x71, 0x73, 0x98, 0x9C, 0x31, 0x86", outClusters: ""
|
||||
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x22, 0x85, 0x59, 0x20, 0x80, 0x70, 0x56, 0x5A, 0x7A, 0x72, 0x8E, 0x71, 0x73, 0x98, 0x9C, 0x31, 0x86", outClusters: ""
|
||||
fingerprint mfr:"010F", prod:"0B01", model:"2002"
|
||||
fingerprint mfr:"010F", prod:"0B01", model:"1002"
|
||||
}
|
||||
|
||||
simulator {
|
||||
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
}
|
||||
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
|
||||
state "temperature", label:'${currentValue}°',
|
||||
backgroundColors:[
|
||||
[value: 31, color: "#153591"],
|
||||
@@ -55,22 +56,22 @@ metadata {
|
||||
[value: 96, color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
}
|
||||
|
||||
main "FGFS"
|
||||
details(["FGFS","battery", "temperature"])
|
||||
}
|
||||
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
}
|
||||
|
||||
main "FGFS"
|
||||
details(["FGFS","battery", "temperature"])
|
||||
}
|
||||
}
|
||||
|
||||
// parse events into attributes
|
||||
def parse(String description) {
|
||||
log.debug "Parsing '${description}'"
|
||||
def result = []
|
||||
|
||||
if (description.startsWith("Err 106")) {
|
||||
|
||||
if (description.startsWith("Err 106")) {
|
||||
if (state.sec) {
|
||||
result = createEvent(descriptionText:description, displayed:false)
|
||||
} else {
|
||||
@@ -85,13 +86,13 @@ def parse(String description) {
|
||||
} else if (description == "updated") {
|
||||
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])
|
||||
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)
|
||||
}
|
||||
}
|
||||
if (cmd) {
|
||||
log.debug "Parsed '${cmd}'"
|
||||
zwaveEvent(cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//security
|
||||
@@ -108,7 +109,7 @@ def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulat
|
||||
//crc16
|
||||
def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd)
|
||||
{
|
||||
def versions = [0x31: 5, 0x72: 2, 0x80: 1]
|
||||
def versions = [0x31: 5, 0x72: 2, 0x80: 1]
|
||||
def version = versions[cmd.commandClass as Integer]
|
||||
def ccObj = version ? zwave.commandClass(cmd.commandClass, version) : zwave.commandClass(cmd.commandClass)
|
||||
def encapsulatedCommand = ccObj?.command(cmd.command)?.parse(cmd.data)
|
||||
@@ -122,105 +123,124 @@ def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap 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())
|
||||
cmds << "delay 500"
|
||||
cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0))
|
||||
cmds << "delay 1200"
|
||||
cmds << encap(zwave.wakeUpV1.wakeUpNoMoreInformation())
|
||||
[event, response(cmds)]
|
||||
def cmds = []
|
||||
// cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0))
|
||||
// cmds << "delay 500"
|
||||
cmds << encap(zwave.batteryV1.batteryGet())
|
||||
[event, response(cmds)]
|
||||
}
|
||||
|
||||
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}"
|
||||
log.debug "manufacturerName: ${cmd.manufacturerName}"
|
||||
log.debug "productId: ${cmd.productId}"
|
||||
log.debug "productTypeId: ${cmd.productTypeId}"
|
||||
}
|
||||
|
||||
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
|
||||
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}"
|
||||
}
|
||||
|
||||
cmd.deviceIdData.each{ data ->
|
||||
serialNumber += "${String.format("%02X", data)}"
|
||||
}
|
||||
|
||||
updateDataValue("serialNumber", serialNumber)
|
||||
log.debug "${device.displayName} - serial number: ${serialNumber}"
|
||||
}
|
||||
|
||||
def response_cmds = []
|
||||
if (!device.currentState("temperature")) {
|
||||
response_cmds << encap(zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0))
|
||||
}
|
||||
if (!getDataValue("version") && !zwaveInfo.ver) {
|
||||
log.debug "Requesting Version Report"
|
||||
response_cmds << "delay 500"
|
||||
response_cmds << encap(zwave.versionV1.versionGet())
|
||||
}
|
||||
response_cmds << "delay 1000"
|
||||
response_cmds << encap(zwave.wakeUpV2.wakeUpNoMoreInformation())
|
||||
[[:], response(response_cmds)]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
|
||||
updateDataValue("version", "${cmd.applicationVersion}.${cmd.applicationSubVersion}")
|
||||
log.debug "applicationVersion: ${cmd.applicationVersion}"
|
||||
log.debug "applicationSubVersion: ${cmd.applicationSubVersion}"
|
||||
log.debug "zWaveLibraryType: ${cmd.zWaveLibraryType}"
|
||||
log.debug "zWaveProtocolVersion: ${cmd.zWaveProtocolVersion}"
|
||||
log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}"
|
||||
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
|
||||
updateDataValue("version", "${cmd.applicationVersion}.${cmd.applicationSubVersion}")
|
||||
log.debug "applicationVersion: ${cmd.applicationVersion}"
|
||||
log.debug "applicationSubVersion: ${cmd.applicationSubVersion}"
|
||||
log.debug "zWaveLibraryType: ${cmd.zWaveLibraryType}"
|
||||
log.debug "zWaveProtocolVersion: ${cmd.zWaveProtocolVersion}"
|
||||
log.debug "zWaveProtocolSubVersion: ${cmd.zWaveProtocolSubVersion}"
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
|
||||
def result = []
|
||||
def map = [:]
|
||||
map.name = "battery"
|
||||
map.value = cmd.batteryLevel == 255 ? 1 : cmd.batteryLevel.toString()
|
||||
map.unit = "%"
|
||||
map.displayed = true
|
||||
createEvent(map)
|
||||
|
||||
result << createEvent(map)
|
||||
|
||||
if (!getDataValue("serialNumber")) {
|
||||
result << response(encap(zwave.manufacturerSpecificV2.deviceSpecificGet()))
|
||||
} else {
|
||||
result << response(encap(zwave.wakeUpV2.wakeUpNoMoreInformation()))
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
|
||||
def map = [:]
|
||||
if (cmd.notificationType == 5) {
|
||||
switch (cmd.event) {
|
||||
case 2:
|
||||
map.name = "water"
|
||||
map.value = "wet"
|
||||
map.descriptionText = "${device.displayName} is ${map.value}"
|
||||
break
|
||||
|
||||
case 0:
|
||||
map.name = "water"
|
||||
map.value = "dry"
|
||||
map.descriptionText = "${device.displayName} is ${map.value}"
|
||||
break
|
||||
}
|
||||
} else if (cmd.notificationType == 7) {
|
||||
switch (cmd.event) {
|
||||
case 0:
|
||||
map.name = "tamper"
|
||||
map.value = "inactive"
|
||||
map.descriptionText = "${device.displayName}: tamper alarm has been deactivated"
|
||||
if (cmd.notificationType == 5) {
|
||||
switch (cmd.event) {
|
||||
case 2:
|
||||
map.name = "water"
|
||||
map.value = "wet"
|
||||
map.descriptionText = "${device.displayName} is ${map.value}"
|
||||
break
|
||||
|
||||
case 3:
|
||||
map.name = "tamper"
|
||||
map.value = "active"
|
||||
map.descriptionText = "${device.displayName}: tamper alarm activated"
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
createEvent(map)
|
||||
|
||||
case 0:
|
||||
map.name = "water"
|
||||
map.value = "dry"
|
||||
map.descriptionText = "${device.displayName} is ${map.value}"
|
||||
break
|
||||
}
|
||||
} else if (cmd.notificationType == 7) {
|
||||
switch (cmd.event) {
|
||||
case 0:
|
||||
map.name = "tamper"
|
||||
map.value = "inactive"
|
||||
map.descriptionText = "${device.displayName}: tamper alarm has been deactivated"
|
||||
break
|
||||
|
||||
case 3:
|
||||
map.name = "tamper"
|
||||
map.value = "active"
|
||||
map.descriptionText = "${device.displayName}: tamper alarm activated"
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd) {
|
||||
def map = [:]
|
||||
if (cmd.sensorType == 1) {
|
||||
// temperature
|
||||
def cmdScale = cmd.scale == 1 ? "F" : "C"
|
||||
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
|
||||
map.unit = getTemperatureScale()
|
||||
map.name = "temperature"
|
||||
map.displayed = true
|
||||
// temperature
|
||||
def cmdScale = cmd.scale == 1 ? "F" : "C"
|
||||
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
|
||||
map.unit = getTemperatureScale()
|
||||
map.name = "temperature"
|
||||
map.displayed = true
|
||||
}
|
||||
|
||||
createEvent(map)
|
||||
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLocallyNotification cmd) {
|
||||
@@ -229,21 +249,18 @@ def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLoca
|
||||
|
||||
def configure() {
|
||||
log.debug "Executing 'configure'"
|
||||
// Device-Watch simply pings if no device events received for 8 hrs & 2 minutes
|
||||
// Device wakes up every 4 hours, this interval of 8h 2m 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)//FGFS' default wake up interval
|
||||
cmds += zwave.manufacturerSpecificV2.manufacturerSpecificGet()
|
||||
cmds += zwave.manufacturerSpecificV2.deviceSpecificGet()
|
||||
cmds += zwave.versionV1.versionGet()
|
||||
cmds += zwave.batteryV1.batteryGet()
|
||||
cmds += zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 1, scale: 0)
|
||||
cmds += zwave.associationV2.associationSet(groupingIdentifier:1, nodeId: [zwaveHubNodeId])
|
||||
cmds += zwave.wakeUpV2.wakeUpNoMoreInformation()
|
||||
// default initial state
|
||||
sendEvent(name: "water", value: "dry")
|
||||
|
||||
encapSequence(cmds, 500)
|
||||
def cmds = []
|
||||
|
||||
cmds << zwave.associationV2.associationSet(groupingIdentifier:1, nodeId: [zwaveHubNodeId])
|
||||
cmds << zwave.batteryV1.batteryGet() // other queries sent as response to BatteryReport
|
||||
|
||||
encapSequence(cmds, 200)
|
||||
}
|
||||
|
||||
private secure(physicalgraph.zwave.Command cmd) {
|
||||
@@ -252,7 +269,7 @@ private secure(physicalgraph.zwave.Command cmd) {
|
||||
|
||||
private crc16(physicalgraph.zwave.Command cmd) {
|
||||
//zwave.crc16EncapV1.crc16Encap().encapsulate(cmd).format()
|
||||
"5601${cmd.format()}0000"
|
||||
"5601${cmd.format()}0000"
|
||||
}
|
||||
|
||||
private encapSequence(commands, delay=200) {
|
||||
@@ -260,13 +277,10 @@ private encapSequence(commands, delay=200) {
|
||||
}
|
||||
|
||||
private encap(physicalgraph.zwave.Command cmd) {
|
||||
def secureClasses = [0x20, 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 }) {
|
||||
secure(cmd)
|
||||
} else {
|
||||
crc16(cmd)
|
||||
}
|
||||
}
|
||||
if (zwaveInfo.zw && !zwaveInfo.zw.contains("s")) {
|
||||
// Secure inclusion failed
|
||||
crc16(cmd)
|
||||
} else {
|
||||
secure(cmd)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,10 +40,10 @@ metadata {
|
||||
// UI tile definitions
|
||||
tiles {
|
||||
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
||||
state "on", action: "switch.off", icon: "st.vents.vent-open-text", backgroundColor: "#53a7c0"
|
||||
state "on", action: "switch.off", icon: "st.vents.vent-open-text", backgroundColor: "#00a0dc"
|
||||
state "off", action: "switch.on", icon: "st.vents.vent-closed", backgroundColor: "#ffffff"
|
||||
state "obstructed", action: "clearObstruction", icon: "st.vents.vent-closed", backgroundColor: "#ff0000"
|
||||
state "clearing", action: "", icon: "st.vents.vent-closed", backgroundColor: "#ffff33"
|
||||
state "obstructed", action: "clearObstruction", icon: "st.vents.vent-closed", backgroundColor: "#e86d13"
|
||||
state "clearing", action: "", icon: "st.vents.vent-closed", backgroundColor: "#ffffff"
|
||||
}
|
||||
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false) {
|
||||
state "level", action:"switch level.setLevel"
|
||||
|
||||
@@ -22,7 +22,7 @@ metadata
|
||||
{
|
||||
standardTile("mainTile", "device.status", width: 1, height: 1, icon: "st.Entertainment.entertainment11")
|
||||
{
|
||||
state "default", label: "Simple Sync", icon: "st.Home.home2", backgroundColor: "#55A7FF"
|
||||
state "default", label: "Simple Sync", icon: "st.Home.home2", backgroundColor: "#00a0dc"
|
||||
}
|
||||
|
||||
def detailTiles = ["mainTile"]
|
||||
|
||||
@@ -82,8 +82,8 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){
|
||||
tileAttribute ("device.motion", key: "PRIMARY_CONTROL") {
|
||||
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
|
||||
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
|
||||
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC"
|
||||
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
|
||||
}
|
||||
}
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.st-ignore
|
||||
README.md
|
||||
43
devicetypes/smartthings/aeon-multisensor-gen5.src/README.md
Normal file
43
devicetypes/smartthings/aeon-multisensor-gen5.src/README.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Aeon Multisensor Gen5
|
||||
|
||||
Cloud Execution
|
||||
|
||||
Works with:
|
||||
|
||||
* [Aeon Labs MultiSensor (Gen 5)](https://www.smartthings.com/works-with-smartthings/sensors/aeon-labs-multisensor-gen-5)
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Capabilities](#capabilities)
|
||||
* [Health](#device-health)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Capabilities
|
||||
|
||||
* **Motion Sensor** - can detect motion
|
||||
* **Temperature Measurement** - defines device measures current temperature
|
||||
* **Relative Humidity Measurement** - allow reading the relative humidity from devices that support it
|
||||
* **Illuminance Measurement** - gives the illuminance reading from devices that support it
|
||||
* **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
|
||||
|
||||
Aeon Labs MultiSensor (Gen 5) 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:
|
||||
* [Aeon Labs MultiSensor (Gen 5) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206157226-Aeon-Labs-MultiSensor-Gen-5-)
|
||||
@@ -20,10 +20,12 @@ metadata {
|
||||
capability "Configuration"
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
capability "Health Check"
|
||||
|
||||
command "configureAfterSecure"
|
||||
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x98,0x7A", outClusters:"0x5A"
|
||||
fingerprint mfr:"0086", prod:"0102", model:"004A", deviceJoinName: "Aeon Labs MultiSensor (Gen 5)"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -64,8 +66,8 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){
|
||||
tileAttribute ("device.motion", key: "PRIMARY_CONTROL") {
|
||||
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
|
||||
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
|
||||
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00a0dc"
|
||||
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
|
||||
}
|
||||
}
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
|
||||
@@ -98,6 +100,11 @@ 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 result = null
|
||||
@@ -244,6 +251,13 @@ def configureAfterSecure() {
|
||||
secureSequence(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
secure(zwave.batteryV1.batteryGet())
|
||||
}
|
||||
|
||||
def configure() {
|
||||
// log.debug "configure()"
|
||||
//["delay 30000"] + secure(zwave.securityV1.securityCommandsSupportedGet())
|
||||
|
||||
@@ -59,8 +59,8 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){
|
||||
tileAttribute ("device.motion", key: "PRIMARY_CONTROL") {
|
||||
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
|
||||
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
|
||||
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00a0dc"
|
||||
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
|
||||
}
|
||||
}
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
|
||||
|
||||
@@ -53,7 +53,7 @@ metadata {
|
||||
// tile definitions
|
||||
tiles {
|
||||
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
||||
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
|
||||
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
|
||||
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
|
||||
}
|
||||
valueTile("power", "device.power", decoration: "flat") {
|
||||
|
||||
2
devicetypes/smartthings/aeon-siren.src/.st-ignore
Normal file
2
devicetypes/smartthings/aeon-siren.src/.st-ignore
Normal file
@@ -0,0 +1,2 @@
|
||||
.st-ignore
|
||||
README.md
|
||||
37
devicetypes/smartthings/aeon-siren.src/README.md
Normal file
37
devicetypes/smartthings/aeon-siren.src/README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Aeon Siren
|
||||
|
||||
Cloud Execution
|
||||
|
||||
Works with:
|
||||
|
||||
* [Aeon Labs Siren (Gen 5)](https://www.smartthings.com/works-with-smartthings/aeon-labs/aeon-labs-siren-gen-5)
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Capabilities](#capabilities)
|
||||
* [Health](#device-health)
|
||||
|
||||
## Capabilities
|
||||
|
||||
* **Actuator** - represents that a Device has commands
|
||||
* **Alarm** - allows for interacting with devices that serve as alarms
|
||||
* **Switch** - can detect state (possible values: on/off)
|
||||
* **Health Check** - indicates ability to get device health notifications
|
||||
|
||||
## Device Health
|
||||
|
||||
Aeon Labs Siren (Gen 5) 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:
|
||||
* [Aeon Labs Siren (Gen 5) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204555240-Aeon-Labs-Siren-Gen-5-)
|
||||
@@ -20,10 +20,11 @@ metadata {
|
||||
capability "Actuator"
|
||||
capability "Alarm"
|
||||
capability "Switch"
|
||||
capability "Health Check"
|
||||
|
||||
command "test"
|
||||
|
||||
fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98"
|
||||
fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98", deviceJoinName: "Aeon Labs Siren (Gen 5)"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -58,6 +59,9 @@ 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])
|
||||
|
||||
if(!state.sound) state.sound = 1
|
||||
if(!state.volume) state.volume = 3
|
||||
|
||||
@@ -148,3 +152,10 @@ def test() {
|
||||
private secure(physicalgraph.zwave.Command cmd) {
|
||||
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
secure(zwave.basicV1.basicGet())
|
||||
}
|
||||
@@ -42,8 +42,8 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) {
|
||||
state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#53a7c0"
|
||||
state "not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ebeef2"
|
||||
state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#00a0dc"
|
||||
state "not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ffffff"
|
||||
}
|
||||
standardTile("beep", "device.beep", decoration: "flat") {
|
||||
state "beep", label:'', action:"tone.beep", icon:"st.secondary.beep", backgroundColor:"#ffffff"
|
||||
|
||||
@@ -67,10 +67,10 @@ metadata {
|
||||
}
|
||||
|
||||
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
|
||||
state "on", label: '${name}', action: "forceOff", icon: "st.Electronics.electronics16", backgroundColor: "#79b821", nextState:"turningOff"
|
||||
state "on", label: '${name}', action: "forceOff", icon: "st.Electronics.electronics16", backgroundColor: "#00a0dc", nextState:"turningOff"
|
||||
state "turningOff", label:'TURNING OFF', icon:"st.Electronics.electronics16", backgroundColor:"#ffffff"
|
||||
state "off", label: '${name}', action: "forceOn", icon: "st.Electronics.electronics16", backgroundColor: "#ffffff", nextState:"turningOn"
|
||||
state "turningOn", label:'TURNING ON', icon:"st.Electronics.electronics16", backgroundColor:"#79b821"
|
||||
state "turningOn", label:'TURNING ON', icon:"st.Electronics.electronics16", backgroundColor:"#00a0dc"
|
||||
}
|
||||
valueTile("1", "device.station1", decoration: "flat", canChangeIcon: false) {
|
||||
state "station1", label:'${currentValue}', action:"preset1"
|
||||
|
||||
@@ -81,13 +81,13 @@ metadata {
|
||||
state "fanCirculate", label:'${name}', action:"switchFanMode"
|
||||
}
|
||||
controlTile("heatSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
|
||||
state "setHeatingSetpoint", action:"quickSetHeat", backgroundColor:"#d04e00"
|
||||
state "setHeatingSetpoint", action:"quickSetHeat", backgroundColor:"#e86d13"
|
||||
}
|
||||
valueTile("heatingSetpoint", "device.heatingSetpoint", inactiveLabel: false, decoration: "flat") {
|
||||
state "heat", label:'${currentValue}° heat', backgroundColor:"#ffffff"
|
||||
}
|
||||
controlTile("coolSliderControl", "device.coolingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
|
||||
state "setCoolingSetpoint", action:"quickSetCool", backgroundColor: "#1e9cbb"
|
||||
state "setCoolingSetpoint", action:"quickSetCool", backgroundColor: "#00a0dc"
|
||||
}
|
||||
valueTile("coolingSetpoint", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") {
|
||||
state "cool", label:'${currentValue}° cool', backgroundColor:"#ffffff"
|
||||
|
||||
@@ -53,7 +53,7 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
||||
state "on", action:"switch.off", icon:"st.vents.vent-open-text", backgroundColor:"#53a7c0"
|
||||
state "on", action:"switch.off", icon:"st.vents.vent-open-text", backgroundColor:"#00a0dc"
|
||||
state "off", action:"switch.on", icon:"st.vents.vent-closed", backgroundColor:"#ffffff"
|
||||
}
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
|
||||
|
||||
@@ -56,9 +56,9 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
||||
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
|
||||
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff"
|
||||
state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
|
||||
state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
|
||||
state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff"
|
||||
state "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
|
||||
}
|
||||
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Device Type Definition File
|
||||
*
|
||||
* Device Type: Fibaro Flood Sensor
|
||||
* File Name: fibaro-flood-sensor.groovy
|
||||
* Initial Release: 2014-12-10
|
||||
* @author: Todd Wackford
|
||||
* Email: todd@wackford.net
|
||||
* @version: 1.0
|
||||
* Device Type: Fibaro Flood Sensor
|
||||
* File Name: fibaro-flood-sensor.groovy
|
||||
* Initial Release: 2014-12-10
|
||||
* @author: Todd Wackford
|
||||
* Email: todd@wackford.net
|
||||
* @version: 1.0
|
||||
*
|
||||
* Copyright 2014 SmartThings
|
||||
*
|
||||
@@ -26,8 +26,8 @@
|
||||
* not displayed to the user. We do this so we can receive events and display on device
|
||||
* activity. If the user wants to display the tamper tile, adjust the tile display lines
|
||||
* with the following:
|
||||
* main(["water", "temperature", "tamper"])
|
||||
* details(["water", "temperature", "battery", "tamper"])
|
||||
* main(["water", "temperature", "tamper"])
|
||||
* details(["water", "temperature", "battery", "tamper"])
|
||||
*
|
||||
* @param none
|
||||
*
|
||||
@@ -40,13 +40,17 @@ metadata {
|
||||
capability "Configuration"
|
||||
capability "Battery"
|
||||
capability "Health Check"
|
||||
|
||||
command "resetParams2StDefaults"
|
||||
command "listCurrentParams"
|
||||
command "updateZwaveParam"
|
||||
command "test"
|
||||
|
||||
capability "Sensor"
|
||||
|
||||
command "resetParams2StDefaults"
|
||||
command "listCurrentParams"
|
||||
command "updateZwaveParam"
|
||||
command "test"
|
||||
|
||||
fingerprint deviceId: "0xA102", inClusters: "0x30,0x9C,0x60,0x85,0x8E,0x72,0x70,0x86,0x80,0x84"
|
||||
fingerprint mfr:"010F", prod:"0000", model:"2002"
|
||||
fingerprint mfr:"010F", prod:"0000", model:"1002"
|
||||
fingerprint mfr:"010F", prod:"0B00", model:"1001"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -73,7 +77,7 @@ metadata {
|
||||
tiles {
|
||||
standardTile("water", "device.water", width: 2, height: 2) {
|
||||
state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
|
||||
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
|
||||
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#00a0dc"
|
||||
}
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false) {
|
||||
state "temperature", label:'${currentValue}°',
|
||||
@@ -87,9 +91,9 @@ metadata {
|
||||
[value: 96, color: "#bc2323"]
|
||||
]
|
||||
}
|
||||
standardTile("tamper", "device.tamper") {
|
||||
state("secure", label:"secure", icon:"st.locks.lock.locked", backgroundColor:"#ffffff")
|
||||
state("tampered", label:"tampered", icon:"st.locks.lock.unlocked", backgroundColor:"#53a7c0")
|
||||
standardTile("tamper", "device.tamper") {
|
||||
state("secure", label:"secure", icon:"st.locks.lock.locked", backgroundColor:"#ffffff")
|
||||
state("tampered", label:"tampered", icon:"st.locks.lock.unlocked", backgroundColor:"#00a0dc")
|
||||
}
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
@@ -107,26 +111,17 @@ metadata {
|
||||
def parse(String description)
|
||||
{
|
||||
def result = []
|
||||
|
||||
if (description == "updated") {
|
||||
if (!state.MSR) {
|
||||
result << response(zwave.wakeUpV1.wakeUpIntervalSet(seconds: 60*60, nodeid:zwaveHubNodeId))
|
||||
result << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
|
||||
}
|
||||
} else {
|
||||
def cmd = zwave.parse(description, [0x31: 2, 0x30: 1, 0x70: 2, 0x71: 1, 0x84: 1, 0x80: 1, 0x9C: 1, 0x72: 2, 0x56: 2, 0x60: 3])
|
||||
|
||||
if (cmd) {
|
||||
result += zwaveEvent(cmd) //createEvent(zwaveEvent(cmd))
|
||||
}
|
||||
}
|
||||
|
||||
result << response(zwave.batteryV1.batteryGet().format())
|
||||
|
||||
if ( result[0] != null ) {
|
||||
|
||||
def cmd = zwave.parse(description, [0x31: 2, 0x30: 1, 0x70: 2, 0x71: 1, 0x84: 1, 0x80: 1, 0x9C: 1, 0x72: 2, 0x56: 2, 0x60: 3])
|
||||
|
||||
if (cmd) {
|
||||
result += zwaveEvent(cmd) //createEvent(zwaveEvent(cmd))
|
||||
}
|
||||
|
||||
if ( result[0] != null ) {
|
||||
log.debug "Parse returned ${result}"
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,10 +138,9 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) {
|
||||
def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]
|
||||
if (!isConfigured()) {
|
||||
// we're still in the process of configuring a newly joined device
|
||||
result += lateConfigure(true)
|
||||
result << lateConfigure(true)
|
||||
} else {
|
||||
result += response(zwave.wakeUpV1.wakeUpNoMoreInformation())
|
||||
log.debug "We're done with WakeUp!"
|
||||
result << response(zwave.wakeUpV1.wakeUpNoMoreInformation())
|
||||
}
|
||||
result
|
||||
}
|
||||
@@ -154,7 +148,7 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) {
|
||||
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv2.SensorMultilevelReport cmd)
|
||||
{
|
||||
def map = [:]
|
||||
|
||||
|
||||
switch (cmd.sensorType) {
|
||||
case 1:
|
||||
// temperature
|
||||
@@ -185,7 +179,7 @@ def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cm
|
||||
def map = [:]
|
||||
map.value = cmd.sensorValue ? "active" : "inactive"
|
||||
map.name = "acceleration"
|
||||
|
||||
|
||||
if (map.value == "active") {
|
||||
map.descriptionText = "$device.displayName detected vibration"
|
||||
}
|
||||
@@ -200,49 +194,49 @@ def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
|
||||
log.debug "BasicSet with CMD = ${cmd}"
|
||||
|
||||
if (!isConfigured()) {
|
||||
def result = []
|
||||
def map = [:]
|
||||
|
||||
map.name = "water"
|
||||
log.debug "BasicSet with CMD = ${cmd}"
|
||||
|
||||
if (!isConfigured()) {
|
||||
def result = []
|
||||
def map = [:]
|
||||
|
||||
map.name = "water"
|
||||
map.value = cmd.value ? "wet" : "dry"
|
||||
map.descriptionText = "${device.displayName} is ${map.value}"
|
||||
|
||||
// If we are getting a BasicSet, and isConfigured == false, then we are likely NOT properly configured.
|
||||
result += lateConfigure(true)
|
||||
|
||||
result << createEvent(map)
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
// If we are getting a BasicSet, and isConfigured == false, then we are likely NOT properly configured.
|
||||
result += lateConfigure(true)
|
||||
|
||||
result << createEvent(map)
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)
|
||||
{
|
||||
def map = [:]
|
||||
|
||||
|
||||
if (cmd.sensorType == 0x05) {
|
||||
map.name = "water"
|
||||
map.value = cmd.sensorState ? "wet" : "dry"
|
||||
map.descriptionText = "${device.displayName} is ${map.value}"
|
||||
|
||||
log.debug "CMD = SensorAlarmReport: ${cmd}"
|
||||
setConfigured()
|
||||
} else if ( cmd.sensorType == 0) {
|
||||
map.name = "tamper"
|
||||
map.isStateChange = true
|
||||
map.value = cmd.sensorState ? "tampered" : "secure"
|
||||
map.descriptionText = "${device.displayName} has been tampered with"
|
||||
runIn(30, "resetTamper") //device does not send alarm cancelation
|
||||
|
||||
} else if ( cmd.sensorType == 1) {
|
||||
map.name = "tamper"
|
||||
map.value = cmd.sensorState ? "tampered" : "secure"
|
||||
map.descriptionText = "${device.displayName} has been tampered with"
|
||||
runIn(30, "resetTamper") //device does not send alarm cancelation
|
||||
|
||||
|
||||
log.debug "CMD = SensorAlarmReport: ${cmd}"
|
||||
setConfigured()
|
||||
} else if ( cmd.sensorType == 0) {
|
||||
map.name = "tamper"
|
||||
map.isStateChange = true
|
||||
map.value = cmd.sensorState ? "tampered" : "secure"
|
||||
map.descriptionText = "${device.displayName} has been tampered with"
|
||||
runIn(30, "resetTamper") //device does not send alarm cancelation
|
||||
|
||||
} else if ( cmd.sensorType == 1) {
|
||||
map.name = "tamper"
|
||||
map.value = cmd.sensorState ? "tampered" : "secure"
|
||||
map.descriptionText = "${device.displayName} has been tampered with"
|
||||
runIn(30, "resetTamper") //device does not send alarm cancelation
|
||||
|
||||
} else {
|
||||
map.descriptionText = "${device.displayName}: ${cmd}"
|
||||
}
|
||||
@@ -251,10 +245,10 @@ def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)
|
||||
|
||||
def resetTamper() {
|
||||
def map = [:]
|
||||
map.name = "tamper"
|
||||
map.value = "secure"
|
||||
map.descriptionText = "$device.displayName is secure"
|
||||
sendEvent(map)
|
||||
map.name = "tamper"
|
||||
map.value = "secure"
|
||||
map.descriptionText = "$device.displayName is secure"
|
||||
sendEvent(map)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.Command cmd) {
|
||||
@@ -268,10 +262,10 @@ def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerS
|
||||
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
|
||||
log.debug "msr: $msr"
|
||||
device.updateDataValue(["MSR", msr])
|
||||
|
||||
if ( msr == "010F-0B00-2001" ) { //this is the msr and device type for the fibaro flood sensor
|
||||
result += lateConfigure(true)
|
||||
}
|
||||
|
||||
if ( msr == "010F-0B00-2001" ) { //this is the msr and device type for the fibaro flood sensor
|
||||
result += lateConfigure(true)
|
||||
}
|
||||
|
||||
result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
|
||||
result
|
||||
@@ -283,17 +277,17 @@ def setConfigured() {
|
||||
|
||||
def isConfigured() {
|
||||
Boolean configured = device.getDataValue(["configured"]) as Boolean
|
||||
|
||||
return configured
|
||||
|
||||
return configured
|
||||
}
|
||||
|
||||
def lateConfigure(setConf = False) {
|
||||
def res = response(configure())
|
||||
|
||||
if (setConf)
|
||||
setConfigured()
|
||||
|
||||
return res
|
||||
|
||||
if (setConf)
|
||||
setConfigured()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -305,29 +299,34 @@ def lateConfigure(setConf = False) {
|
||||
*/
|
||||
def configure() {
|
||||
log.debug "Configuring Device..."
|
||||
// Device-Watch simply pings if no device events received for 8 hrs & 2 minutes
|
||||
// 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 = []
|
||||
|
||||
// send associate to group 2 to get alarm data
|
||||
cmds << zwave.associationV2.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format()
|
||||
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format()
|
||||
|
||||
// send associate to group 3 to get sensor data reported only to hub
|
||||
cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()
|
||||
// default initial state
|
||||
sendEvent(name: "water", value: "dry")
|
||||
|
||||
// temp hysteresis set to .5 degrees celcius
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()
|
||||
def cmds = []
|
||||
|
||||
// send associate to group 2 to get alarm data
|
||||
cmds << zwave.associationV2.associationSet(groupingIdentifier:2, nodeId:[zwaveHubNodeId]).format()
|
||||
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format()
|
||||
|
||||
// send associate to group 3 to get sensor data reported only to hub
|
||||
cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId:[zwaveHubNodeId]).format()
|
||||
|
||||
// reporting frequency of temps and battery set to one hour
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,60*60], parameterNumber: 10, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()
|
||||
|
||||
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
|
||||
|
||||
// cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()
|
||||
|
||||
// temp hysteresis set to .5 degrees celcius
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format()
|
||||
// cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()
|
||||
|
||||
cmds << zwave.batteryV1.batteryGet().format()
|
||||
|
||||
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
|
||||
|
||||
delayBetween(cmds, 100)
|
||||
}
|
||||
|
||||
@@ -353,18 +352,18 @@ def test() {
|
||||
* @return none
|
||||
*/
|
||||
def updateZwaveParam(params) {
|
||||
if ( params ) {
|
||||
def pNumber = params.paramNumber
|
||||
def pSize = params.size
|
||||
def pValue = [params.value]
|
||||
log.debug "Make sure device is awake and in recieve mode (triple-click?)"
|
||||
log.debug "Updating ${device.displayName} parameter number '${pNumber}' with value '${pValue}' with size of '${pSize}'"
|
||||
if ( params ) {
|
||||
def pNumber = params.paramNumber
|
||||
def pSize = params.size
|
||||
def pValue = [params.value]
|
||||
log.debug "Make sure device is awake and in recieve mode (triple-click?)"
|
||||
log.debug "Updating ${device.displayName} parameter number '${pNumber}' with value '${pValue}' with size of '${pSize}'"
|
||||
|
||||
def cmds = []
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: pValue, parameterNumber: pNumber, size: pSize).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: pNumber).format()
|
||||
delayBetween(cmds, 1000)
|
||||
}
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: pValue, parameterNumber: pNumber, size: pSize).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: pNumber).format()
|
||||
delayBetween(cmds, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -381,26 +380,26 @@ def updateZwaveParam(params) {
|
||||
def resetParams2StDefaults() {
|
||||
log.debug "Resetting ${device.displayName} parameters to SmartThings compatible defaults"
|
||||
def cmds = []
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 1, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [3], parameterNumber: 2, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 7, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 9, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,60*60], parameterNumber: 10, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [5,220], parameterNumber: 50, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [13,172], parameterNumber: 51, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0,0,225], parameterNumber: 61, size: 4).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,255,0,0], parameterNumber: 62, size: 4).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 63, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 73, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 74, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 75, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 76, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 77, size: 1).format()
|
||||
|
||||
delayBetween(cmds, 1200)
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 1, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [3], parameterNumber: 2, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 5, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [255], parameterNumber: 7, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 9, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,60*60], parameterNumber: 10, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,50], parameterNumber: 12, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 13, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [5,220], parameterNumber: 50, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [13,172], parameterNumber: 51, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0,0,225], parameterNumber: 61, size: 4).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,255,0,0], parameterNumber: 62, size: 4).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 63, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 73, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 74, size: 1).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 75, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0,0], parameterNumber: 76, size: 2).format()
|
||||
cmds << zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 77, size: 1).format()
|
||||
|
||||
delayBetween(cmds, 1200)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -417,25 +416,25 @@ def resetParams2StDefaults() {
|
||||
def listCurrentParams() {
|
||||
log.debug "Listing of current parameter settings of ${device.displayName}"
|
||||
def cmds = []
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 1).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 2).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 5).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 7).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 9).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 13).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 50).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 51).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 61).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 62).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 63).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 73).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 74).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 75).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 76).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 77).format()
|
||||
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 1).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 2).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 5).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 7).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 9).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 10).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 12).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 13).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 50).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 51).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 61).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 62).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 63).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 73).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 74).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 75).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 76).format()
|
||||
cmds << zwave.configurationV1.configurationGet(parameterNumber: 77).format()
|
||||
|
||||
delayBetween(cmds, 1200)
|
||||
}
|
||||
|
||||
|
||||
@@ -82,8 +82,8 @@
|
||||
|
||||
tiles {
|
||||
standardTile("motion", "device.motion", width: 2, height: 2) {
|
||||
state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
|
||||
state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
|
||||
state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00a0dc"
|
||||
state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
|
||||
}
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false) {
|
||||
state "temperature", label:'${currentValue}°',
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.st-ignore
|
||||
README.md
|
||||
39
devicetypes/smartthings/fortrezz-water-valve.src/README.md
Normal file
39
devicetypes/smartthings/fortrezz-water-valve.src/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# FortrezZ Water Valve
|
||||
|
||||
Cloud Execution
|
||||
|
||||
Works with:
|
||||
|
||||
* [FortrezZ Water Valve](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
|
||||
* **Health Check** - indicates ability to get device health notifications
|
||||
* **Valve** - allows for the control of a valve device
|
||||
* **Refresh** - _refresh()_ command for status updates
|
||||
* **Sensor** - detects sensor events
|
||||
|
||||
## Device Health
|
||||
|
||||
FortrezZ Water Valve 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 Water Valve Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202088434-FortrezZ-Water-Valve-Shutoff)
|
||||
@@ -14,11 +14,13 @@
|
||||
metadata {
|
||||
definition (name: "Fortrezz Water Valve", namespace: "smartthings", author: "SmartThings") {
|
||||
capability "Actuator"
|
||||
capability "Health Check"
|
||||
capability "Valve"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
|
||||
fingerprint deviceId: "0x1000", inClusters: "0x25,0x72,0x86,0x71,0x22,0x70"
|
||||
fingerprint mfr:"0084", prod:"0213", model:"0215", deviceJoinName: "FortrezZ Water Valve"
|
||||
}
|
||||
|
||||
// simulator metadata
|
||||
@@ -48,6 +50,11 @@ 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) {
|
||||
log.trace description
|
||||
def result = null
|
||||
@@ -76,6 +83,13 @@ def close() {
|
||||
zwave.switchBinaryV1.switchBinarySet(switchValue: 0xFF).format()
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
refresh()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
zwave.switchBinaryV1.switchBinaryGet().format()
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("motion", "device.motion", width: 2, height: 2) {
|
||||
state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
|
||||
state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
|
||||
state "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC"
|
||||
state "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
|
||||
}
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false) {
|
||||
state "temperature", label:'${currentValue}°',
|
||||
|
||||
@@ -21,6 +21,7 @@ metadata {
|
||||
capability "Configuration"
|
||||
capability "Battery"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
|
||||
command "enrollResponse"
|
||||
|
||||
@@ -31,8 +32,8 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("motion", "device.motion", width: 2, height: 2) {
|
||||
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
|
||||
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
|
||||
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC")
|
||||
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc")
|
||||
}
|
||||
|
||||
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) {
|
||||
|
||||
@@ -24,6 +24,7 @@ metadata {
|
||||
capability "Contact Sensor"
|
||||
capability "Refresh"
|
||||
capability "Health Check"
|
||||
capability "Sensor"
|
||||
|
||||
command "enrollResponse"
|
||||
|
||||
@@ -41,8 +42,8 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("contact", "device.contact", width: 2, height: 2) {
|
||||
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
|
||||
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
|
||||
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13")
|
||||
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc")
|
||||
}
|
||||
|
||||
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) {
|
||||
|
||||
@@ -33,6 +33,7 @@ metadata {
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315"
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-Seu", deviceJoinName: "Water Leak Sensor"
|
||||
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-L", deviceJoinName: "Iris Smart Water Sensor"
|
||||
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-G", deviceJoinName: "Centralite Water Sensor"
|
||||
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "moisturev4", deviceJoinName: "Water Leak Sensor"
|
||||
}
|
||||
|
||||
@@ -58,7 +59,7 @@ metadata {
|
||||
multiAttributeTile(name: "water", type: "generic", width: 6, height: 4) {
|
||||
tileAttribute("device.water", key: "PRIMARY_CONTROL") {
|
||||
attributeState "dry", label: "Dry", icon: "st.alarm.water.dry", backgroundColor: "#ffffff"
|
||||
attributeState "wet", label: "Wet", icon: "st.alarm.water.wet", backgroundColor: "#53a7c0"
|
||||
attributeState "wet", label: "Wet", icon: "st.alarm.water.wet", backgroundColor: "#00A0DC"
|
||||
}
|
||||
}
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
|
||||
@@ -106,6 +107,12 @@ def parse(String description) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (map.name == "temperature") {
|
||||
if (tempOffset) {
|
||||
map.value = (int) map.value + (int) tempOffset
|
||||
}
|
||||
map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F'
|
||||
map.translatable = true
|
||||
}
|
||||
|
||||
log.debug "Parse returned $map"
|
||||
|
||||
@@ -34,6 +34,7 @@ metadata {
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3325"
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3326"
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3326-L", deviceJoinName: "Iris Motion Sensor"
|
||||
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3328-G", deviceJoinName: "Centralite Micro Motion Sensor"
|
||||
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "motionv4", deviceJoinName: "Motion Sensor"
|
||||
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "motionv5", deviceJoinName: "Motion Sensor"
|
||||
}
|
||||
@@ -112,6 +113,12 @@ def parse(String description) {
|
||||
map = getMotionResult(value)
|
||||
}
|
||||
}
|
||||
} else if (map.name == "temperature") {
|
||||
if (tempOffset) {
|
||||
map.value = (int) map.value + (int) tempOffset
|
||||
}
|
||||
map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F'
|
||||
map.translatable = true
|
||||
}
|
||||
|
||||
log.debug "Parse returned $map"
|
||||
|
||||
@@ -30,8 +30,8 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){
|
||||
tileAttribute ("device.motion", key: "PRIMARY_CONTROL") {
|
||||
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
|
||||
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
|
||||
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC"
|
||||
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
|
||||
}
|
||||
}
|
||||
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
|
||||
|
||||
@@ -33,6 +33,7 @@ metadata {
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3320"
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3321"
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3321-S", deviceJoinName: "Multipurpose Sensor"
|
||||
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3323-G", deviceJoinName: "Centralite Micro Door Sensor"
|
||||
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500,FC02", outClusters: "0019", manufacturer: "SmartThings", model: "multiv4", deviceJoinName: "Multipurpose Sensor"
|
||||
|
||||
attribute "status", "string"
|
||||
|
||||
@@ -52,14 +52,14 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
|
||||
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
|
||||
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e"
|
||||
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821"
|
||||
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"##e86d13"
|
||||
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc"
|
||||
}
|
||||
}
|
||||
|
||||
standardTile("acceleration", "device.acceleration", width: 2, height: 2) {
|
||||
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0")
|
||||
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
|
||||
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00a0dc")
|
||||
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#cccccc")
|
||||
}
|
||||
valueTile("temperature", "device.temperature", width: 2, height: 2) {
|
||||
state("temperature", label:'${currentValue}°',
|
||||
|
||||
@@ -45,8 +45,8 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name: "contact", type: "generic", width: 6, height: 4) {
|
||||
tileAttribute("device.contact", key: "PRIMARY_CONTROL") {
|
||||
attributeState "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
|
||||
attributeState "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
|
||||
attributeState "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13"
|
||||
attributeState "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00A0DC"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,12 @@ def parse(String description) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (map.name == "temperature") {
|
||||
if (tempOffset) {
|
||||
map.value = (int) map.value + (int) tempOffset
|
||||
}
|
||||
map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F'
|
||||
map.translatable = true
|
||||
}
|
||||
|
||||
log.debug "Parse returned $map"
|
||||
|
||||
@@ -88,6 +88,12 @@ def parse(String description) {
|
||||
log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}"
|
||||
}
|
||||
}
|
||||
} else if (map.name == "temperature") {
|
||||
if (tempOffset) {
|
||||
map.value = (int) map.value + (int) tempOffset
|
||||
}
|
||||
map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F'
|
||||
map.translatable = true
|
||||
}
|
||||
|
||||
log.debug "Parse returned $map"
|
||||
|
||||
@@ -41,8 +41,8 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("contact", "device.contact", width: 2, height: 2) {
|
||||
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
|
||||
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
|
||||
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13")
|
||||
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00A0DC")
|
||||
}
|
||||
|
||||
valueTile("temperature", "device.temperature", inactiveLabel: false) {
|
||||
|
||||
@@ -44,7 +44,7 @@ metadata {
|
||||
tiles {
|
||||
standardTile("button", "device.button", width: 2, height: 2) {
|
||||
state "default", label: "", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff"
|
||||
state "button 1 pushed", label: "pushed #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821"
|
||||
state "button 1 pushed", label: "pushed #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC"
|
||||
}
|
||||
|
||||
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) {
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Copyright 2016 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.
|
||||
*
|
||||
*/
|
||||
import groovy.transform.Field
|
||||
|
||||
@Field Boolean hasConfiguredHealthCheck = false
|
||||
|
||||
metadata {
|
||||
definition (name: "ZLL White Color Temperature Bulb 5000K", namespace: "smartthings", author: "SmartThings") {
|
||||
|
||||
capability "Actuator"
|
||||
capability "Color Temperature"
|
||||
capability "Configuration"
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Switch"
|
||||
capability "Switch Level"
|
||||
capability "Health Check"
|
||||
|
||||
attribute "colorName", "string"
|
||||
command "setGenericName"
|
||||
|
||||
fingerprint profileId: "C05E", deviceId: "0220", inClusters: "0000, 0004, 0003, 0006, 0008, 0005, 0300", outClusters: "0019", manufacturer: "Eaton", model: "Halo_LT01", deviceJoinName: "Halo RL56 Wireless"
|
||||
}
|
||||
|
||||
// UI tile definitions
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
|
||||
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
|
||||
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff"
|
||||
attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
|
||||
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff"
|
||||
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
|
||||
}
|
||||
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
|
||||
attributeState "level", action:"switch level.setLevel"
|
||||
}
|
||||
tileAttribute ("colorName", key: "SECONDARY_CONTROL") {
|
||||
attributeState "colorName", label:'${currentValue}'
|
||||
}
|
||||
}
|
||||
|
||||
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
|
||||
}
|
||||
|
||||
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..5000)") {
|
||||
state "colorTemperature", action:"color temperature.setColorTemperature"
|
||||
}
|
||||
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||
state "colorTemperature", label: '${currentValue} K'
|
||||
}
|
||||
|
||||
main(["switch"])
|
||||
details(["switch", "colorTempSliderControl", "colorTemp", "refresh"])
|
||||
}
|
||||
}
|
||||
|
||||
// Parse incoming device messages to generate events
|
||||
def parse(String description) {
|
||||
log.debug "description is $description"
|
||||
def event = zigbee.getEvent(description)
|
||||
if (event) {
|
||||
if (event.name == "colorTemperature") {
|
||||
event.unit = "K"
|
||||
}
|
||||
sendEvent(event)
|
||||
}
|
||||
else {
|
||||
log.warn "DID NOT PARSE MESSAGE for description : $description"
|
||||
log.debug zigbee.parseDescriptionAsMap(description)
|
||||
}
|
||||
}
|
||||
|
||||
def off() {
|
||||
zigbee.off() + ["delay 1500"] + zigbee.onOffRefresh()
|
||||
}
|
||||
|
||||
def on() {
|
||||
zigbee.on() + ["delay 1500"] + zigbee.onOffRefresh()
|
||||
}
|
||||
|
||||
def setLevel(value) {
|
||||
zigbee.setLevel(value) + zigbee.onOffRefresh() + zigbee.levelRefresh()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
def cmds = zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
|
||||
|
||||
// Do NOT config if the device is the Eaton Halo_LT01, it responds with "switch:off" to onOffConfig, and maybe other weird things with the others
|
||||
if (!((device.getDataValue("manufacturer") == "Eaton") && (device.getDataValue("model") == "Halo_LT01"))) {
|
||||
cmds = cmds + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig()
|
||||
}
|
||||
|
||||
cmds
|
||||
}
|
||||
|
||||
def poll() {
|
||||
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
return zigbee.levelRefresh()
|
||||
}
|
||||
|
||||
def healthPoll() {
|
||||
log.debug "healthPoll()"
|
||||
def cmds = zigbee.onOffRefresh() + zigbee.levelRefresh()
|
||||
cmds.each{ sendHubCommand(new physicalgraph.device.HubAction(it))}
|
||||
}
|
||||
|
||||
def configureHealthCheck() {
|
||||
Integer hcIntervalMinutes = 12
|
||||
if (!hasConfiguredHealthCheck) {
|
||||
log.debug "Configuring Health Check, Reporting"
|
||||
unschedule("healthPoll")
|
||||
runEvery5Minutes("healthPoll")
|
||||
// Device-Watch allows 2 check-in misses from device
|
||||
sendEvent(name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
|
||||
hasConfiguredHealthCheck = true
|
||||
}
|
||||
}
|
||||
|
||||
def configure() {
|
||||
log.debug "configure()"
|
||||
configureHealthCheck()
|
||||
// Implementation note: for the Eaton Halo_LT01, it responds with "switch:off" to onOffConfig, so be sure this is before the call to onOffRefresh
|
||||
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "updated()"
|
||||
configureHealthCheck()
|
||||
}
|
||||
|
||||
def setColorTemperature(value) {
|
||||
setGenericName(value)
|
||||
zigbee.setColorTemperature(value) + ["delay 1500"] + zigbee.colorTemperatureRefresh()
|
||||
}
|
||||
|
||||
//Naming based on the wiki article here: http://en.wikipedia.org/wiki/Color_temperature
|
||||
def setGenericName(value){
|
||||
if (value != null) {
|
||||
def genericName = ""
|
||||
if (value < 3300) {
|
||||
genericName = "Soft White"
|
||||
} else if (value < 4150) {
|
||||
genericName = "Moonlight"
|
||||
} else if (value <= 5000) {
|
||||
genericName = "Cool White"
|
||||
} else {
|
||||
genericName = "Daylight"
|
||||
}
|
||||
sendEvent(name: "colorName", value: genericName, displayed: false)
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
||||
state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#79b821"
|
||||
state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#00A0DC"
|
||||
state "off", label: '${name}', action: "switch.on", icon: "st.unknown.zwave.device", backgroundColor: "#ffffff"
|
||||
}
|
||||
standardTile("switchOn", "device.switch", inactiveLabel: false, decoration: "flat") {
|
||||
|
||||
@@ -33,7 +33,7 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
||||
state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#79b821"
|
||||
state "on", label: '${name}', action: "switch.off", icon: "st.unknown.zwave.device", backgroundColor: "#00A0DC"
|
||||
state "off", label: '${name}', action: "switch.on", icon: "st.unknown.zwave.device", backgroundColor: "#ffffff"
|
||||
}
|
||||
standardTile("switchOn", "device.switch", inactiveLabel: false, decoration: "flat") {
|
||||
|
||||
@@ -41,8 +41,8 @@ metadata {
|
||||
// UI tile definitions
|
||||
tiles {
|
||||
standardTile("contact", "device.contact", width: 2, height: 2) {
|
||||
state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
|
||||
state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
|
||||
state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13"
|
||||
state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00A0DC"
|
||||
}
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.st-ignore
|
||||
README.md
|
||||
@@ -0,0 +1,41 @@
|
||||
# Z-wave Garage Door Opener
|
||||
|
||||
Cloud Execution
|
||||
|
||||
Works with:
|
||||
|
||||
* [Linear GoControl Garage Door Opener](https://www.smartthings.com/works-with-smartthings/other/linear-gocontrol-garage-door-opener)
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Capabilities](#capabilities)
|
||||
* [Health](#device-health)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Capabilities
|
||||
|
||||
* **Actuator** - represents that a Device has commands
|
||||
* **Door Control** - allow for the control of a door
|
||||
* **Garage Door Control** - allow for the control of a garage door
|
||||
* **Health Check** - indicates ability to get device health notifications
|
||||
* **Contact Sensor** - can detect contact (with possible values - open/closed)
|
||||
* **Refresh** - _refresh()_ command for status updates
|
||||
* **Sensor** - detects sensor events
|
||||
|
||||
## Device Health
|
||||
|
||||
Linear GoControl Garage Door Opener 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:
|
||||
* [Linear GoControl Garage Door Opener Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204831116-GoControl-Linear-Garage-Door-Opener-GD00Z-4-)
|
||||
@@ -18,12 +18,14 @@ metadata {
|
||||
capability "Actuator"
|
||||
capability "Door Control"
|
||||
capability "Garage Door Control"
|
||||
capability "Health Check"
|
||||
capability "Contact Sensor"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
|
||||
fingerprint deviceId: "0x4007", inClusters: "0x98"
|
||||
fingerprint deviceId: "0x4006", inClusters: "0x98"
|
||||
fingerprint mfr:"014F", prod:"4744", model:"3030", deviceJoinName: "Linear GoControl Garage Door Opener"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -39,11 +41,11 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("toggle", "device.door", width: 2, height: 2) {
|
||||
state("unknown", label:'${name}', action:"refresh.refresh", icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e")
|
||||
state("closed", label:'${name}', action:"door control.open", icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821", nextState:"opening")
|
||||
state("open", label:'${name}', action:"door control.close", icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e", nextState:"closing")
|
||||
state("opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#ffe71e")
|
||||
state("closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#ffe71e")
|
||||
state("unknown", label:'${name}', action:"refresh.refresh", icon:"st.doors.garage.garage-open", backgroundColor:"#ffffff")
|
||||
state("closed", label:'${name}', action:"door control.open", icon:"st.doors.garage.garage-closed", backgroundColor:"#00a0dc", nextState:"opening")
|
||||
state("open", label:'${name}', action:"door control.close", icon:"st.doors.garage.garage-open", backgroundColor:"#e86d13", nextState:"closing")
|
||||
state("opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#e86d13")
|
||||
state("closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#00a0dc")
|
||||
|
||||
}
|
||||
standardTile("open", "device.door", inactiveLabel: false, decoration: "flat") {
|
||||
@@ -63,6 +65,11 @@ metadata {
|
||||
|
||||
import physicalgraph.zwave.commands.barrieroperatorv1.*
|
||||
|
||||
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 result = null
|
||||
if (description.startsWith("Err")) {
|
||||
@@ -287,6 +294,13 @@ def close() {
|
||||
secure(zwave.barrierOperatorV1.barrierOperatorSet(requestedBarrierState: BarrierOperatorSet.REQUESTED_BARRIER_STATE_CLOSE))
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
refresh()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
secure(zwave.barrierOperatorV1.barrierOperatorGet())
|
||||
}
|
||||
|
||||
2
devicetypes/smartthings/zwave-lock.src/.st-ignore
Normal file
2
devicetypes/smartthings/zwave-lock.src/.st-ignore
Normal file
@@ -0,0 +1,2 @@
|
||||
.st-ignore
|
||||
README.md
|
||||
45
devicetypes/smartthings/zwave-lock.src/README.md
Normal file
45
devicetypes/smartthings/zwave-lock.src/README.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Z-Wave Switch
|
||||
|
||||
Cloud Execution
|
||||
|
||||
Works with:
|
||||
|
||||
* [Yale Key Free Touchscreen Deadbolt (YRD240)](https://www.smartthings.com/works-with-smartthings/yale/yale-key-free-touchscreen-deadbolt-yrd240)
|
||||
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Capabilities](#capabilities)
|
||||
* [Health](#device-health)
|
||||
* [Troubleshooting](#Troubleshooting)
|
||||
|
||||
## Capabilities
|
||||
|
||||
* **Actuator** - represents that a Device has commands
|
||||
* **Battery** - defines device uses a battery
|
||||
* **Lock** - allows for the control of a lock device
|
||||
* **Lock Codes** - allows for the lock code control of a lock device
|
||||
* **Polling** - represents that poll() can be implemented for the device
|
||||
* **Refresh** - _refresh()_ command for status updates
|
||||
* **Sensor** - detects sensor events
|
||||
* **Health Check** - indicates ability to get device health notifications
|
||||
|
||||
## Device Health
|
||||
|
||||
Z-Wave Locks are 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:
|
||||
* [General Z-Wave/ZigBee Yale Lock Troubleshooting](https://support.smartthings.com/hc/en-us/articles/205138400-How-to-connect-Yale-locks)
|
||||
|
||||
|
||||
@@ -20,11 +20,13 @@ metadata {
|
||||
capability "Sensor"
|
||||
capability "Lock Codes"
|
||||
capability "Battery"
|
||||
capability "Health Check"
|
||||
|
||||
command "unlockwtimeout"
|
||||
|
||||
fingerprint deviceId: "0x4003", inClusters: "0x98"
|
||||
fingerprint deviceId: "0x4004", inClusters: "0x98"
|
||||
fingerprint mfr:"0129", prod:"0002", model:"0000", deviceJoinName: "Yale Key Free Touchscreen Deadbolt"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -38,10 +40,10 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"toggle", type: "generic", width: 6, height: 4){
|
||||
tileAttribute ("device.lock", key: "PRIMARY_CONTROL") {
|
||||
attributeState "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821", nextState:"unlocking"
|
||||
attributeState "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00A0DC", nextState:"unlocking"
|
||||
attributeState "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff", nextState:"locking"
|
||||
attributeState "unknown", label:"unknown", action:"lock.lock", icon:"st.locks.lock.unknown", backgroundColor:"#ffffff", nextState:"locking"
|
||||
attributeState "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#79b821"
|
||||
attributeState "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#00A0DC"
|
||||
attributeState "unlocking", label:'unlocking', icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff"
|
||||
}
|
||||
}
|
||||
@@ -67,6 +69,8 @@ import physicalgraph.zwave.commands.doorlockv1.*
|
||||
import physicalgraph.zwave.commands.usercodev1.*
|
||||
|
||||
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 {
|
||||
if (!state.init) {
|
||||
state.init = true
|
||||
@@ -504,6 +508,13 @@ def unlockwtimeout() {
|
||||
lockAndCheck(DoorLockOperationSet.DOOR_LOCK_MODE_DOOR_UNSECURED_WITH_TIMEOUT)
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
refresh()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
def cmds = [secure(zwave.doorLockV1.doorLockOperationGet())]
|
||||
if (state.assoc == zwaveHubNodeId) {
|
||||
|
||||
@@ -51,7 +51,7 @@ metadata {
|
||||
// tile definitions
|
||||
tiles {
|
||||
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
|
||||
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
|
||||
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
|
||||
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
|
||||
}
|
||||
valueTile("power", "device.power") {
|
||||
|
||||
@@ -38,8 +38,8 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("motion", "device.motion", width: 2, height: 2) {
|
||||
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
|
||||
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
|
||||
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC")
|
||||
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc")
|
||||
}
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
|
||||
state("battery", label:'${currentValue}% battery', unit:"")
|
||||
|
||||
@@ -37,8 +37,8 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
|
||||
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
|
||||
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e"
|
||||
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821"
|
||||
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13"
|
||||
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc"
|
||||
}
|
||||
}
|
||||
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
|
||||
|
||||
@@ -32,8 +32,8 @@ metadata {
|
||||
|
||||
tiles {
|
||||
standardTile("sensor", "device.sensor", width: 2, height: 2) {
|
||||
state("inactive", label:'inactive', icon:"st.unknown.zwave.sensor", backgroundColor:"#ffffff")
|
||||
state("active", label:'active', icon:"st.unknown.zwave.sensor", backgroundColor:"#53a7c0")
|
||||
state("inactive", label:'inactive', icon:"st.unknown.zwave.sensor", backgroundColor:"#cccccc")
|
||||
state("active", label:'active', icon:"st.unknown.zwave.sensor", backgroundColor:"#00A0DC")
|
||||
}
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
|
||||
2
devicetypes/smartthings/zwave-siren.src/.st-ignore
Normal file
2
devicetypes/smartthings/zwave-siren.src/.st-ignore
Normal file
@@ -0,0 +1,2 @@
|
||||
.st-ignore
|
||||
README.md
|
||||
42
devicetypes/smartthings/zwave-siren.src/README.md
Normal file
42
devicetypes/smartthings/zwave-siren.src/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 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,6 +20,7 @@ metadata {
|
||||
capability "Actuator"
|
||||
capability "Alarm"
|
||||
capability "Battery"
|
||||
capability "Health Check"
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
@@ -27,6 +28,7 @@ metadata {
|
||||
|
||||
|
||||
fingerprint inClusters: "0x20,0x25,0x86,0x80,0x85,0x72,0x71"
|
||||
fingerprint mfr:"0084", prod:"0313", model:"010B", deviceJoinName: "FortrezZ Siren Strobe Alarm"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -58,6 +60,11 @@ 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) {
|
||||
@@ -119,6 +126,13 @@ 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()
|
||||
|
||||
2
devicetypes/smartthings/zwave-smoke-alarm.src/.st-ignore
Normal file
2
devicetypes/smartthings/zwave-smoke-alarm.src/.st-ignore
Normal file
@@ -0,0 +1,2 @@
|
||||
.st-ignore
|
||||
README.md
|
||||
40
devicetypes/smartthings/zwave-smoke-alarm.src/README.md
Normal file
40
devicetypes/smartthings/zwave-smoke-alarm.src/README.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Z-wave Smoke Alarm
|
||||
|
||||
Cloud Execution
|
||||
|
||||
Works with:
|
||||
|
||||
* [First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO)](https://www.smartthings.com/works-with-smartthings/sensors/first-alert-smoke-detector-and-carbon-monoxide-alarm-zcombo)
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Capabilities](#capabilities)
|
||||
* [Health](#device-health)
|
||||
* [Battery](#battery-specification)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Capabilities
|
||||
|
||||
* **Smoke Detector** - measure smoke and optionally carbon monoxide levels
|
||||
* **Carbon Monoxide Detector** - measure carbon monoxide levels
|
||||
* **Sensor** - detects sensor events
|
||||
* **Battery** - defines device uses a battery
|
||||
* **Health Check** - indicates ability to get device health notifications
|
||||
|
||||
## Device Health
|
||||
|
||||
First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO) is a Z-wave sleepy 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
|
||||
|
||||
Two 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:
|
||||
* [First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/201581984-First-Alert-Smoke-Detector-and-Carbon-Monoxide-Alarm-ZCOMBO-)
|
||||
@@ -17,10 +17,12 @@ metadata {
|
||||
capability "Carbon Monoxide Detector"
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
capability "Health Check"
|
||||
|
||||
attribute "alarmState", "string"
|
||||
|
||||
fingerprint deviceId: "0xA100", inClusters: "0x20,0x80,0x70,0x85,0x71,0x72,0x86"
|
||||
fingerprint mfr:"0138", prod:"0001", model:"0002", deviceJoinName: "First Alert Smoke Detector and Carbon Monoxide Alarm (ZCOMBO)"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -51,6 +53,11 @@ metadata {
|
||||
}
|
||||
}
|
||||
|
||||
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])
|
||||
}
|
||||
|
||||
def parse(String description) {
|
||||
def results = []
|
||||
if (description.startsWith("Err")) {
|
||||
@@ -65,7 +72,6 @@ def parse(String description) {
|
||||
return results
|
||||
}
|
||||
|
||||
|
||||
def createSmokeOrCOEvents(name, results) {
|
||||
def text = null
|
||||
switch (name) {
|
||||
|
||||
@@ -47,7 +47,7 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
|
||||
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
|
||||
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
|
||||
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
|
||||
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ metadata {
|
||||
tiles(scale: 2) {
|
||||
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
|
||||
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
|
||||
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
|
||||
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
|
||||
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ metadata {
|
||||
capability "Configuration"
|
||||
capability "Polling"
|
||||
capability "Sensor"
|
||||
capability "Health Check"
|
||||
|
||||
attribute "thermostatFanState", "string"
|
||||
|
||||
@@ -30,6 +31,7 @@ metadata {
|
||||
|
||||
fingerprint deviceId: "0x08"
|
||||
fingerprint inClusters: "0x43,0x40,0x44,0x31"
|
||||
fingerprint mfr:"0039", prod:"0011", model:"0001", deviceJoinName: "Honeywell Z-Wave Thermostat"
|
||||
}
|
||||
|
||||
// simulator metadata
|
||||
@@ -123,6 +125,11 @@ 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 map = createEvent(zwaveEvent(zwave.parse(description, [0x42:1, 0x43:2, 0x31: 3])))
|
||||
@@ -393,6 +400,14 @@ def setCoolingSetpoint(Double degrees, Integer delay = 30000) {
|
||||
], delay)
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
def ping() {
|
||||
log.debug "ping() called"
|
||||
poll()
|
||||
}
|
||||
|
||||
def configure() {
|
||||
delayBetween([
|
||||
zwave.thermostatModeV2.thermostatModeSupportedGet().format(),
|
||||
|
||||
@@ -33,7 +33,7 @@ metadata {
|
||||
tiles {
|
||||
standardTile("water", "device.water", width: 2, height: 2) {
|
||||
state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
|
||||
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
|
||||
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#00A0DC"
|
||||
}
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
|
||||
@@ -0,0 +1,794 @@
|
||||
/**
|
||||
* Gideon
|
||||
*
|
||||
* Copyright 2016 Nicola Russo
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing permissions and limitations under the License.
|
||||
*
|
||||
*/
|
||||
definition(
|
||||
name: "Gideon Smart Home",
|
||||
namespace: "gideon.api",
|
||||
author: "Braindrain Solutions ltd",
|
||||
description: "Gideon Smart Home SmartApp allows you to connect and control all of your SmartThings devices through the Gideon app, making your SmartThings devices even smarter.",
|
||||
category: "Family",
|
||||
iconUrl: "http://s33.postimg.org/t77u7y7v3/logo.png",
|
||||
iconX2Url: "http://s33.postimg.org/t77u7y7v3/logo.png",
|
||||
iconX3Url: "http://s33.postimg.org/t77u7y7v3/logo.png",
|
||||
oauth: [displayName: "Gideon Smart Home API app", displayLink: "gideon.ai"])
|
||||
|
||||
preferences {
|
||||
section("Control these contact sensors...") {
|
||||
input "contact", "capability.contactSensor", multiple:true, required:false
|
||||
}
|
||||
section("Control these switch levels...") {
|
||||
input "switchlevels", "capability.switchLevel", multiple:true, required:false
|
||||
}
|
||||
/* section("Control these thermostats...") {
|
||||
input "thermostats", "capability.thermostat", multiple:true, required:false
|
||||
}*/
|
||||
section("Control the color for these devices...") {
|
||||
input "colors", "capability.colorControl", multiple:true, required:false
|
||||
}
|
||||
section("Control the color temperature for these devices...") {
|
||||
input "kelvin", "capability.colorTemperature", multiple:true, required:false
|
||||
}
|
||||
section("Control these switches...") {
|
||||
input "switches", "capability.switch", multiple:true, required:false
|
||||
}
|
||||
section("Control these smoke alarms...") {
|
||||
input "smoke_alarms", "capability.smokeDetector", multiple:true, required:false
|
||||
}
|
||||
section("Control these window shades...") {
|
||||
input "shades", "capability.windowShade", multiple:true, required:false
|
||||
}
|
||||
section("Control these garage doors...") {
|
||||
input "garage", "capability.garageDoorControl", multiple:true, required:false
|
||||
}
|
||||
section("Control these water sensors...") {
|
||||
input "water_sensors", "capability.waterSensor", multiple:true, required:false
|
||||
}
|
||||
section("Control these motion sensors...") {
|
||||
input "motions", "capability.motionSensor", multiple:true, required:false
|
||||
}
|
||||
section("Control these presence sensors...") {
|
||||
input "presence_sensors", "capability.presenceSensor", multiple:true, required:false
|
||||
}
|
||||
section("Control these outlets...") {
|
||||
input "outlets", "capability.outlet", multiple:true, required:false
|
||||
}
|
||||
section("Control these power meters...") {
|
||||
input "meters", "capability.powerMeter", multiple:true, required:false
|
||||
}
|
||||
section("Control these locks...") {
|
||||
input "locks", "capability.lock", multiple:true, required:false
|
||||
}
|
||||
section("Control these temperature sensors...") {
|
||||
input "temperature_sensors", "capability.temperatureMeasurement", multiple:true, required:false
|
||||
}
|
||||
section("Control these batteries...") {
|
||||
input "batteries", "capability.battery", multiple:true, required:false
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {
|
||||
log.debug "Installed with settings: ${settings}"
|
||||
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "Updated with settings: ${settings}"
|
||||
|
||||
unsubscribe()
|
||||
initialize()
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
}
|
||||
|
||||
private device(it, type) {
|
||||
it ? [id: it.id, label: it.label, type: type] : null
|
||||
}
|
||||
|
||||
//API Mapping
|
||||
mappings {
|
||||
path("/getalldevices") {
|
||||
action: [
|
||||
GET: "getAllDevices"
|
||||
]
|
||||
}
|
||||
/*
|
||||
path("/thermostat/setcool/:id/:temp") {
|
||||
action: [
|
||||
GET: "setCoolTemp"
|
||||
]
|
||||
}
|
||||
path("/thermostat/setheat/:id/:temp") {
|
||||
action: [
|
||||
GET: "setHeatTemp"
|
||||
]
|
||||
}
|
||||
path("/thermostat/setfanmode/:id/:mode") {
|
||||
action: [
|
||||
GET: "setFanMode"
|
||||
]
|
||||
}
|
||||
path("/thermostat/setmode/:id/:mode") {
|
||||
action: [
|
||||
GET: "setThermostatMode"
|
||||
]
|
||||
}
|
||||
path("/thermostat/:id") {
|
||||
action: [
|
||||
GET: "getThermostatStatus"
|
||||
]
|
||||
}
|
||||
*/
|
||||
path("/light/dim/:id/:dim") {
|
||||
action: [
|
||||
GET: "setLevelStatus"
|
||||
]
|
||||
}
|
||||
path("/light/kelvin/:id/:kelvin") {
|
||||
action: [
|
||||
GET: "setKelvin"
|
||||
]
|
||||
}
|
||||
path("/colorlight/:id/:hue/:sat") {
|
||||
action: [
|
||||
GET: "setColor"
|
||||
]
|
||||
}
|
||||
path("/light/status/:id") {
|
||||
action: [
|
||||
GET: "getLightStatus"
|
||||
]
|
||||
}
|
||||
path("/light/on/:id") {
|
||||
action: [
|
||||
GET: "turnOnLight"
|
||||
]
|
||||
}
|
||||
path("/light/off/:id") {
|
||||
action: [
|
||||
GET: "turnOffLight"
|
||||
]
|
||||
}
|
||||
path("/doorlocks/lock/:id") {
|
||||
action: [
|
||||
GET: "lockDoorLock"
|
||||
]
|
||||
}
|
||||
path("/doorlocks/unlock/:id") {
|
||||
action: [
|
||||
GET: "unlockDoorLock"
|
||||
]
|
||||
}
|
||||
path("/doorlocks/:id") {
|
||||
action: [
|
||||
GET: "getDoorLockStatus"
|
||||
]
|
||||
}
|
||||
path("/contacts/:id") {
|
||||
action: [
|
||||
GET: "getContactStatus"
|
||||
]
|
||||
}
|
||||
path("/smoke/:id") {
|
||||
action: [
|
||||
GET: "getSmokeStatus"
|
||||
]
|
||||
}
|
||||
path("/shades/open/:id") {
|
||||
action: [
|
||||
GET: "openShade"
|
||||
]
|
||||
}
|
||||
path("/shades/preset/:id") {
|
||||
action: [
|
||||
GET: "presetShade"
|
||||
]
|
||||
}
|
||||
path("/shades/close/:id") {
|
||||
action: [
|
||||
GET: "closeShade"
|
||||
]
|
||||
}
|
||||
path("/shades/:id") {
|
||||
action: [
|
||||
GET: "getShadeStatus"
|
||||
]
|
||||
}
|
||||
path("/garage/open/:id") {
|
||||
action: [
|
||||
GET: "openGarage"
|
||||
]
|
||||
}
|
||||
path("/garage/close/:id") {
|
||||
action: [
|
||||
GET: "closeGarage"
|
||||
]
|
||||
}
|
||||
path("/garage/:id") {
|
||||
action: [
|
||||
GET: "getGarageStatus"
|
||||
]
|
||||
}
|
||||
path("/watersensors/:id") {
|
||||
action: [
|
||||
GET: "getWaterSensorStatus"
|
||||
]
|
||||
}
|
||||
path("/tempsensors/:id") {
|
||||
action: [
|
||||
GET: "getTempSensorsStatus"
|
||||
]
|
||||
}
|
||||
path("/meters/:id") {
|
||||
action: [
|
||||
GET: "getMeterStatus"
|
||||
]
|
||||
}
|
||||
path("/batteries/:id") {
|
||||
action: [
|
||||
GET: "getBatteryStatus"
|
||||
]
|
||||
}
|
||||
path("/presences/:id") {
|
||||
action: [
|
||||
GET: "getPresenceStatus"
|
||||
]
|
||||
}
|
||||
path("/motions/:id") {
|
||||
action: [
|
||||
GET: "getMotionStatus"
|
||||
]
|
||||
}
|
||||
path("/outlets/:id") {
|
||||
action: [
|
||||
GET: "getOutletStatus"
|
||||
]
|
||||
}
|
||||
path("/outlets/turnon/:id") {
|
||||
action: [
|
||||
GET: "turnOnOutlet"
|
||||
]
|
||||
}
|
||||
path("/outlets/turnoff/:id") {
|
||||
action: [
|
||||
GET: "turnOffOutlet"
|
||||
]
|
||||
}
|
||||
path("/switches/turnon/:id") {
|
||||
action: [
|
||||
GET: "turnOnSwitch"
|
||||
]
|
||||
}
|
||||
path("/switches/turnoff/:id") {
|
||||
action: [
|
||||
GET: "turnOffSwitch"
|
||||
]
|
||||
}
|
||||
path("/switches/:id") {
|
||||
action: [
|
||||
GET: "getSwitchStatus"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
//API Methods
|
||||
def getAllDevices() {
|
||||
def locks_list = locks.collect{device(it,"Lock")}
|
||||
/*def thermo_list = thermostats.collect{device(it,"Thermostat")}*/
|
||||
def colors_list = colors.collect{device(it,"Color")}
|
||||
def kelvin_list = kelvin.collect{device(it,"Kelvin")}
|
||||
def contact_list = contact.collect{device(it,"Contact Sensor")}
|
||||
def smokes_list = smoke_alarms.collect{device(it,"Smoke Alarm")}
|
||||
def shades_list = shades.collect{device(it,"Window Shade")}
|
||||
def garage_list = garage.collect{device(it,"Garage Door")}
|
||||
def water_sensors_list = water_sensors.collect{device(it,"Water Sensor")}
|
||||
def presences_list = presence_sensors.collect{device(it,"Presence")}
|
||||
def motions_list = motions.collect{device(it,"Motion")}
|
||||
def outlets_list = outlets.collect{device(it,"Outlet")}
|
||||
def switches_list = switches.collect{device(it,"Switch")}
|
||||
def switchlevels_list = switchlevels.collect{device(it,"Switch Level")}
|
||||
def temp_list = temperature_sensors.collect{device(it,"Temperature")}
|
||||
def meters_list = meters.collect{device(it,"Power Meters")}
|
||||
def battery_list = batteries.collect{device(it,"Batteries")}
|
||||
return outlets_list + kelvin_list + colors_list + switchlevels_list + smokes_list + contact_list + water_sensors_list + shades_list + garage_list + locks_list + presences_list + motions_list + switches_list + temp_list + meters_list + battery_list
|
||||
}
|
||||
|
||||
//thermostat
|
||||
/*
|
||||
def setCoolTemp() {
|
||||
def device = thermostats.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
if(device.hasCommand("setCoolingSetpoint")) {
|
||||
device.setCoolingSetpoint(params.temp.toInteger());
|
||||
return [result_action: "200"]
|
||||
}
|
||||
else {
|
||||
httpError(510, "Not supported!")
|
||||
}
|
||||
}
|
||||
}
|
||||
def setHeatTemp() {
|
||||
def device = thermostats.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
if(device.hasCommand("setHeatingSetpoint")) {
|
||||
device.setHeatingSetpoint(params.temp.toInteger());
|
||||
return [result_action: "200"]
|
||||
}
|
||||
else {
|
||||
httpError(510, "Not supported!")
|
||||
}
|
||||
}
|
||||
}
|
||||
def setFanMode() {
|
||||
def device = thermostats.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
if(device.hasCommand("setThermostatFanMode")) {
|
||||
device.setThermostatFanMode(params.mode);
|
||||
return [result_action: "200"]
|
||||
}
|
||||
else {
|
||||
httpError(510, "Not supported!")
|
||||
}
|
||||
}
|
||||
}
|
||||
def setThermostatMode() {
|
||||
def device = thermostats.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
if(device.hasCommand("setThermostatMode")) {
|
||||
device.setThermostatMode(params.mode);
|
||||
return [result_action: "200"]
|
||||
}
|
||||
else {
|
||||
httpError(510, "Not supported!")
|
||||
}
|
||||
}
|
||||
}
|
||||
def getThermostatStatus() {
|
||||
def device = thermostats.find{ it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
return [ThermostatOperatingState: device.currentValue('thermostatOperatingState'), ThermostatSetpoint: device.currentValue('thermostatSetpoint'),
|
||||
ThermostatFanMode: device.currentValue('thermostatFanMode'), ThermostatMode: device.currentValue('thermostatMode')]
|
||||
}
|
||||
}
|
||||
*/
|
||||
//light
|
||||
def turnOnLight() {
|
||||
def device = switches.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
device.on();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
|
||||
def turnOffLight() {
|
||||
def device = switches.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
device.off();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
|
||||
def getLightStatus() {
|
||||
def device = switches.find{ it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
return [Status: device.currentValue('switch'), Dim: getLevelStatus(params.id), Color: getColorStatus(params.id), Kelvin: getKelvinStatus(params.id)]
|
||||
}
|
||||
}
|
||||
|
||||
//color control
|
||||
def setColor() {
|
||||
def device = colors.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
def map = [hue:params.hue.toInteger(), saturation:params.sat.toInteger()]
|
||||
|
||||
device.setColor(map);
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
|
||||
def getColorStatus(id) {
|
||||
def device = colors.find { it.id == id }
|
||||
if (!device) {
|
||||
return [Color: "none"]
|
||||
} else {
|
||||
return [hue: device.currentValue('hue'), saturation: device.currentValue('saturation')]
|
||||
}
|
||||
}
|
||||
|
||||
//kelvin control
|
||||
def setKelvin() {
|
||||
def device = kelvin.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.setColorTemperature(params.kelvin.toInteger());
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
|
||||
def getKelvinStatus(id) {
|
||||
def device = kelvin.find { it.id == id }
|
||||
if (!device) {
|
||||
return [kelvin: "none"]
|
||||
} else {
|
||||
return [kelvin: device.currentValue('colorTemperature')]
|
||||
}
|
||||
}
|
||||
|
||||
//switch level
|
||||
def getLevelStatus() {
|
||||
def device = switchlevels.find { it.id == params.id }
|
||||
if (!device) {
|
||||
[Level: "No dimmer"]
|
||||
} else {
|
||||
return [Level: device.currentValue('level')]
|
||||
}
|
||||
}
|
||||
|
||||
def getLevelStatus(id) {
|
||||
def device = switchlevels.find { it.id == id }
|
||||
if (!device) {
|
||||
[Level: "No dimmer"]
|
||||
} else {
|
||||
return [Level: device.currentValue('level')]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def setLevelStatus() {
|
||||
def device = switchlevels.find { it.id == params.id }
|
||||
def level = params.dim
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
device.setLevel(level.toInteger())
|
||||
return [result_action: "200", Level: device.currentValue('level')]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//contact sensors
|
||||
def getContactStatus() {
|
||||
def device = contact.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
def args = getTempSensorsStatus(device.id)
|
||||
return [Device_state: device.currentValue('contact')] + args
|
||||
}
|
||||
}
|
||||
|
||||
//smoke detectors
|
||||
def getSmokeStatus() {
|
||||
def device = smoke_alarms.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
def bat = getBatteryStatus(device.id)
|
||||
return [Device_state: device.currentValue('smoke')] + bat
|
||||
}
|
||||
}
|
||||
|
||||
//garage
|
||||
def getGarageStatus() {
|
||||
def device = garage.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
return [Device_state: device.currentValue('door')]
|
||||
}
|
||||
}
|
||||
|
||||
def openGarage() {
|
||||
def device = garage.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.open();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
|
||||
def closeGarage() {
|
||||
def device = garage.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.close();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
//shades
|
||||
def getShadeStatus() {
|
||||
def device = shades.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
return [Device_state: device.currentValue('windowShade')]
|
||||
}
|
||||
}
|
||||
|
||||
def openShade() {
|
||||
def device = shades.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.open();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
|
||||
def presetShade() {
|
||||
def device = shades.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.presetPosition();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
|
||||
def closeShade() {
|
||||
def device = shades.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.close();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
|
||||
//water sensor
|
||||
def getWaterSensorStatus() {
|
||||
def device = water_sensors.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
def bat = getBatteryStatus(device.id)
|
||||
return [Device_state: device.currentValue('water')] + bat
|
||||
}
|
||||
}
|
||||
//batteries
|
||||
def getBatteryStatus() {
|
||||
def device = batteries.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
return [Device_state: device.latestValue("battery")]
|
||||
}
|
||||
}
|
||||
|
||||
def getBatteryStatus(id) {
|
||||
def device = batteries.find { it.id == id }
|
||||
if (!device) {
|
||||
return []
|
||||
} else {
|
||||
return [battery_state: device.latestValue("battery")]
|
||||
}
|
||||
}
|
||||
|
||||
//LOCKS
|
||||
def getDoorLockStatus() {
|
||||
def device = locks.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
def bat = getBatteryStatus(device.id)
|
||||
return [Device_state: device.currentValue('lock')] + bat
|
||||
}
|
||||
}
|
||||
|
||||
def lockDoorLock() {
|
||||
def device = locks.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.lock();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
|
||||
def unlockDoorLock() {
|
||||
def device = locks.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.unlock();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
//PRESENCE
|
||||
def getPresenceStatus() {
|
||||
|
||||
def device = presence_sensors.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
def bat = getBatteryStatus(device.id)
|
||||
return [Device_state: device.currentValue('presence')] + bat
|
||||
}
|
||||
}
|
||||
|
||||
//MOTION
|
||||
def getMotionStatus() {
|
||||
|
||||
def device = motions.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
def args = getTempSensorsStatus(device.id)
|
||||
return [Device_state: device.currentValue('motion')] + args
|
||||
}
|
||||
}
|
||||
|
||||
//OUTLET
|
||||
def getOutletStatus() {
|
||||
|
||||
def device = outlets.find { it.id == params.id }
|
||||
if (!device) {
|
||||
device = switches.find { it.id == params.id }
|
||||
if(!device) {
|
||||
httpError(404, "Device not found")
|
||||
}
|
||||
}
|
||||
def watt = getMeterStatus(device.id)
|
||||
|
||||
return [Device_state: device.currentValue('switch')] + watt
|
||||
}
|
||||
|
||||
def getMeterStatus() {
|
||||
|
||||
def device = meters.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
return [Device_id: device.id, Device_type: device.type, Current_watt: device.currentValue("power")]
|
||||
}
|
||||
}
|
||||
|
||||
def getMeterStatus(id) {
|
||||
|
||||
def device = meters.find { it.id == id }
|
||||
if (!device) {
|
||||
return []
|
||||
} else {
|
||||
return [Current_watt: device.currentValue("power")]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def turnOnOutlet() {
|
||||
def device = outlets.find { it.id == params.id }
|
||||
if (!device) {
|
||||
device = switches.find { it.id == params.id }
|
||||
if(!device) {
|
||||
httpError(404, "Device not found")
|
||||
}
|
||||
}
|
||||
|
||||
device.on();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
|
||||
def turnOffOutlet() {
|
||||
def device = outlets.find { it.id == params.id }
|
||||
if (!device) {
|
||||
device = switches.find { it.id == params.id }
|
||||
if(!device) {
|
||||
httpError(404, "Device not found")
|
||||
}
|
||||
}
|
||||
|
||||
device.off();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
|
||||
//SWITCH
|
||||
def getSwitchStatus() {
|
||||
def device = switches.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
return [Device_state: device.currentValue('switch'), Dim: getLevelStatus(params.id)]
|
||||
}
|
||||
}
|
||||
|
||||
def turnOnSwitch() {
|
||||
def device = switches.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.on();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
|
||||
def turnOffSwitch() {
|
||||
def device = switches.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.off();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//TEMPERATURE
|
||||
def getTempSensorsStatus() {
|
||||
def device = temperature_sensors.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
def bat = getBatteryStatus(device.id)
|
||||
def scale = [Scale: location.temperatureScale]
|
||||
return [Device_state: device.currentValue('temperature')] + scale + bat
|
||||
}
|
||||
}
|
||||
|
||||
def getTempSensorsStatus(id) {
|
||||
def device = temperature_sensors.find { it.id == id }
|
||||
if (!device) {
|
||||
return []
|
||||
} else {
|
||||
def bat = getBatteryStatus(device.id)
|
||||
return [temperature: device.currentValue('temperature')] + bat
|
||||
}
|
||||
}
|
||||
211
smartapps/global-ipl-ijini/ijini.src/ijini.groovy
Normal file
211
smartapps/global-ipl-ijini/ijini.src/ijini.groovy
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* IJINI
|
||||
*
|
||||
* Copyright 2017 IPL_DevAccount
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing permissions and limitations under the License.
|
||||
*
|
||||
*/
|
||||
definition(
|
||||
name: "IJINI",
|
||||
namespace: "global.ipl.IJINI",
|
||||
author: "IPL_DevAccount",
|
||||
description: "IJINI SUPPORTING APP",
|
||||
category: "SmartThings Labs",
|
||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
|
||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
|
||||
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
|
||||
|
||||
|
||||
preferences {
|
||||
section("Allow Endpoint to Control These Things...") {
|
||||
input "switches", "capability.switch", title: "Which Switches?", multiple: true
|
||||
//input "locks", "capability.lock", title: "Which Locks?", multiple: true
|
||||
input "themotion", "capability.motionSensor", title: "Which Motions?", multiple: true
|
||||
}
|
||||
}
|
||||
|
||||
mappings {
|
||||
|
||||
path("/switches") {
|
||||
action: [
|
||||
GET: "listSwitches"
|
||||
]
|
||||
}
|
||||
path("/switches/:id") {
|
||||
action: [
|
||||
GET: "showSwitch"
|
||||
]
|
||||
}
|
||||
path("/switches/:id/:command") {
|
||||
action: [
|
||||
GET: "updateSwitch"
|
||||
]
|
||||
}
|
||||
|
||||
path("/locks") {
|
||||
action: [
|
||||
GET: "listLocks"
|
||||
]
|
||||
}
|
||||
path("/locks/:id") {
|
||||
action: [
|
||||
GET: "showLock"
|
||||
]
|
||||
}
|
||||
path("/locks/:id/:command") {
|
||||
action: [
|
||||
GET: "updateLock"
|
||||
]
|
||||
}
|
||||
|
||||
path("/SwitchState/:id") {
|
||||
action: [
|
||||
GET: "SwitchState"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
def SwitchState()
|
||||
{
|
||||
GetSwitchState(switches,"switch");
|
||||
}
|
||||
|
||||
def GetSwitchState(devices, type)
|
||||
{
|
||||
|
||||
def device = devices.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found ${devices}")
|
||||
}
|
||||
else
|
||||
{
|
||||
def attributeName = (type == "motionSensor") ? "motion" : type
|
||||
def s = device.currentState(attributeName)
|
||||
[value: s?.value]
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated()
|
||||
{
|
||||
unsubscribe()
|
||||
}
|
||||
|
||||
def initialize()
|
||||
{
|
||||
subscribe(themotion, "motion.active", motionDetectedHandler)
|
||||
subscribe(themotion, "motion.inactive", motionStoppedHandler)
|
||||
}
|
||||
|
||||
def motionDetectedHandler(evt) {
|
||||
log.debug "motionDetectedHandler called: ${evt}"
|
||||
httpGet(String uri, Closure closure)
|
||||
}
|
||||
|
||||
def motionStoppedHandler(evt) {
|
||||
log.debug "motionStoppedHandler called: ${evt}"
|
||||
}
|
||||
|
||||
//switches
|
||||
def listSwitches() {
|
||||
switches.collect{device(it,"switch")}
|
||||
}
|
||||
def showSwitch() {
|
||||
show(switches, "switch")
|
||||
}
|
||||
void updateSwitch() {
|
||||
update(switches)
|
||||
}
|
||||
|
||||
//locks
|
||||
def listLocks() {
|
||||
locks.collect{device(it,"lock")}
|
||||
}
|
||||
def showLock() {
|
||||
show(locks, "lock")
|
||||
}
|
||||
void updateLock() {
|
||||
update(locks)
|
||||
}
|
||||
|
||||
//Motions
|
||||
def listMotion() {
|
||||
log.debug "listMotions is activated...."
|
||||
motion.collect{device(it,"motion")}
|
||||
}
|
||||
|
||||
def showMotion() {
|
||||
show(motion, "motionSensor")
|
||||
}
|
||||
|
||||
void updateMotion() {
|
||||
update(motion)
|
||||
}
|
||||
|
||||
|
||||
def deviceHandler(evt) {
|
||||
log.debug "deviceHandler"
|
||||
}
|
||||
|
||||
private void update(devices)
|
||||
{
|
||||
log.debug "update, request: params: ${params}, devices: $devices.id"
|
||||
|
||||
//def command = request.JSON?.command
|
||||
def command = params.command
|
||||
//let's create a toggle option here
|
||||
if (command)
|
||||
{
|
||||
def device = devices.find { it.id == params.id }//it, params 상에서 같은것을 찾아내서 저장...하는듯하다.
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
if(command == "toggle")
|
||||
{
|
||||
if(device.currentValue('switch') == "on")
|
||||
{
|
||||
device.off();
|
||||
}
|
||||
else
|
||||
{
|
||||
device.on();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
device."$command"()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private show(devices, type) {
|
||||
log.debug "device = ${devices},type = ${type} "
|
||||
def device = devices.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
}
|
||||
else {
|
||||
def attributeName = (type == "motionSensor") ? "motion" : type
|
||||
def s = device.currentState(attributeName)
|
||||
|
||||
[id: device.id, label: device.displayName, value: s?.value, unitTime: s?.date?.time, type: type]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private device(it, type) {
|
||||
log.debug "device ctrl.. ${it}, ${type}"
|
||||
it ? [id: it.id, label: it.label, type: type] : null
|
||||
}
|
||||
@@ -30,7 +30,7 @@ preferences {
|
||||
input "havdalahOffset", "number", title: "Minutes After Sundown", required:true
|
||||
}
|
||||
section("Your ZipCode") {
|
||||
input "zipcode", "number", title: "ZipCode", required:true
|
||||
input "zipcode", "text", title: "ZipCode", required:true
|
||||
}
|
||||
section( "Notifications" ) {
|
||||
input "sendPushMessage", "enum", title: "Send a push notification?", metadata:[values:["Yes","No"]], required:false
|
||||
@@ -205,4 +205,4 @@ if ( sendPushMessage != "No" ) {
|
||||
log.debug( "sending text message" )
|
||||
sendSms( phone, msg )
|
||||
}
|
||||
}//END def sendMessage(msg)
|
||||
}//END def sendMessage(msg)
|
||||
|
||||
@@ -472,8 +472,6 @@ def addBridge() {
|
||||
log.error "Failed to create Hue Bridge device"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.debug "found ${d.displayName} with id $selectedHue already exists"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -715,6 +713,9 @@ def doDeviceSync(){
|
||||
log.warn "state.updating failed to clear"
|
||||
}
|
||||
|
||||
if (selectedHue) {
|
||||
addBridge()
|
||||
}
|
||||
convertBulbListToMap()
|
||||
poll()
|
||||
ssdpSubscribe()
|
||||
@@ -1358,7 +1359,7 @@ private void createSwitchEvent(childDevice, setSwitch, setLevel = null) {
|
||||
private colorPointsForModel(model = null) {
|
||||
def result = null
|
||||
switch (model) {
|
||||
// Gamut A
|
||||
// Gamut A
|
||||
case "LLC001": /* Monet, Renoir, Mondriaan (gen II) */
|
||||
case "LLC005": /* Bloom (gen II) */
|
||||
case "LLC006": /* Iris (gen III) */
|
||||
@@ -1370,12 +1371,12 @@ private colorPointsForModel(model = null) {
|
||||
case "LLC010": /* Hue Living Colors Iris + */
|
||||
result = [r:[x: 0.704f, y: 0.296f], g:[x: 0.2151f, y: 0.7106f], b:[x: 0.138f, y: 0.08f]];
|
||||
break
|
||||
// Gamut C
|
||||
// Gamut C
|
||||
case "LLC020": /* Hue Go */
|
||||
case "LST002": /* Hue LightStrips Plus */
|
||||
result = [r:[x: 0.692f, y: 0.308f], g:[x: 0.17f, y: 0.7f], b:[x: 0.153f, y: 0.048f]];
|
||||
break
|
||||
// Gamut B
|
||||
// Gamut B
|
||||
case "LCT001": /* Hue A19 */
|
||||
case "LCT002": /* Hue BR30 */
|
||||
case "LCT003": /* Hue GU10 */
|
||||
@@ -1803,4 +1804,3 @@ def hsvToHex(hue, sat, value = 100){
|
||||
|
||||
return "#$r1$g1$b1"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user