mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-13 13:21:53 +00:00
Compare commits
1 Commits
MSA-1718-1
...
MSA-1697-1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd9743a10f |
@@ -99,7 +99,7 @@ def parse(String description) {
|
||||
|
||||
def poll() {
|
||||
def refreshCmds = [
|
||||
"st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 2000"
|
||||
"st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 500"
|
||||
]
|
||||
|
||||
return refreshCmds + zigbee.onOffRefresh() + zigbee.levelRefresh()
|
||||
@@ -197,7 +197,7 @@ def off() {
|
||||
|
||||
def refresh() {
|
||||
def refreshCmds = [
|
||||
"st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 2000"
|
||||
"st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 500"
|
||||
]
|
||||
|
||||
return refreshCmds + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig()
|
||||
|
||||
@@ -128,9 +128,9 @@ def setLevel(value) {
|
||||
|
||||
def refresh() {
|
||||
[
|
||||
"st rattr 0x${device.deviceNetworkId} ${endpointId} 6 0", "delay 2000",
|
||||
"st rattr 0x${device.deviceNetworkId} ${endpointId} 8 0", "delay 2000",
|
||||
"st rattr 0x${device.deviceNetworkId} ${endpointId} 0x0B04 0x050B", "delay 2000"
|
||||
"st rattr 0x${device.deviceNetworkId} ${endpointId} 6 0", "delay 500",
|
||||
"st rattr 0x${device.deviceNetworkId} ${endpointId} 8 0", "delay 500",
|
||||
"st rattr 0x${device.deviceNetworkId} ${endpointId} 0x0B04 0x050B", "delay 500"
|
||||
]
|
||||
|
||||
}
|
||||
@@ -313,9 +313,9 @@ def isDescriptionPower(descMap) {
|
||||
|
||||
def onOffConfig() {
|
||||
[
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 6 {${device.zigbeeId}} {}", "delay 2000",
|
||||
"zcl global send-me-a-report 6 0 0x10 0 600 {01}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000"
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 6 {${device.zigbeeId}} {}", "delay 200",
|
||||
"zcl global send-me-a-report 6 0 0x10 0 600 {01}",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -323,9 +323,9 @@ def onOffConfig() {
|
||||
//min level change is 01
|
||||
def levelConfig() {
|
||||
[
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 8 {${device.zigbeeId}} {}", "delay 2000",
|
||||
"zcl global send-me-a-report 8 0 0x20 5 3600 {01}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000"
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 8 {${device.zigbeeId}} {}", "delay 200",
|
||||
"zcl global send-me-a-report 8 0 0x20 5 3600 {01}",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -333,10 +333,9 @@ def levelConfig() {
|
||||
//min change in value is 05
|
||||
def powerConfig() {
|
||||
[
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 2000",
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 200",
|
||||
"zcl global send-me-a-report 0x0B04 0x050B 0x29 1 600 {05 00}", //The send-me-a-report is custom to the attribute type for CentraLite
|
||||
"delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000"
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -345,10 +344,7 @@ def setLevelWithRate(level, rate) {
|
||||
rate = "0000"
|
||||
}
|
||||
level = convertToHexString(level * 255 / 100) //Converting the 0-100 range to 0-FF range in hex
|
||||
[
|
||||
"st cmd 0x${device.deviceNetworkId} ${endpointId} 8 4 {$level $rate}",
|
||||
"delay 2000"
|
||||
]
|
||||
"st cmd 0x${device.deviceNetworkId} ${endpointId} 8 4 {$level $rate}"
|
||||
}
|
||||
|
||||
String convertToHexString(value, width=2) {
|
||||
|
||||
@@ -51,7 +51,7 @@ def on() {
|
||||
'zcl on-off on',
|
||||
'delay 200',
|
||||
"send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}",
|
||||
'delay 2000'
|
||||
'delay 500'
|
||||
|
||||
]
|
||||
|
||||
@@ -62,6 +62,6 @@ def off() {
|
||||
'zcl on-off off',
|
||||
'delay 200',
|
||||
"send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}",
|
||||
'delay 2000'
|
||||
'delay 500'
|
||||
]
|
||||
}
|
||||
|
||||
@@ -157,10 +157,9 @@ def configure() {
|
||||
//min change in value is 01
|
||||
def powerConfig() {
|
||||
[
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 2000",
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 200",
|
||||
"zcl global send-me-a-report 0x0B04 0x050B 0x29 1 600 {05 00}", //The send-me-a-report is custom to the attribute type for CentraLite
|
||||
"delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000"
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,9 @@ metadata {
|
||||
command "enrollResponse"
|
||||
|
||||
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-S", deviceJoinName: "Water Leak Sensor"
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315"
|
||||
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,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-S", deviceJoinName: "Water Leak Sensor"
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315"
|
||||
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-Seu", deviceJoinName: "Water Leak Sensor"
|
||||
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "moisturev4", deviceJoinName: "Water Leak Sensor"
|
||||
}
|
||||
|
||||
@@ -286,8 +285,8 @@ def ping() {
|
||||
def refresh() {
|
||||
log.debug "Refreshing Temperature and Battery"
|
||||
def refreshCmds = [
|
||||
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 2000",
|
||||
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 2000"
|
||||
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
|
||||
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
|
||||
]
|
||||
|
||||
return refreshCmds + enrollResponse()
|
||||
@@ -309,10 +308,10 @@ def enrollResponse() {
|
||||
[
|
||||
//Resending the CIE in case the enroll request is sent before CIE is written
|
||||
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
|
||||
//Enroll Response
|
||||
"raw 0x500 {01 23 00 00 00}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 2000"
|
||||
"raw 0x500 {01 23 00 00 00}",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -298,8 +298,8 @@ def ping() {
|
||||
def refresh() {
|
||||
log.debug "refresh called"
|
||||
def refreshCmds = [
|
||||
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 2000",
|
||||
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 2000"
|
||||
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
|
||||
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
|
||||
]
|
||||
|
||||
return refreshCmds + enrollResponse()
|
||||
@@ -321,10 +321,10 @@ def enrollResponse() {
|
||||
[
|
||||
//Resending the CIE in case the enroll request is sent before CIE is written
|
||||
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
|
||||
//Enroll Response
|
||||
"raw 0x500 {01 23 00 00 00}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 2000"
|
||||
"raw 0x500 {01 23 00 00 00}",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -428,10 +428,10 @@ def enrollResponse() {
|
||||
[
|
||||
//Resending the CIE in case the enroll request is sent before CIE is written
|
||||
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
|
||||
//Enroll Response
|
||||
"raw 0x500 {01 23 00 00 00}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 2000"
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -252,8 +252,8 @@ def ping() {
|
||||
def refresh() {
|
||||
log.debug "Refreshing Temperature and Battery"
|
||||
def refreshCmds = [
|
||||
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 2000",
|
||||
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 2000"
|
||||
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
|
||||
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
|
||||
]
|
||||
|
||||
return refreshCmds + enrollResponse()
|
||||
@@ -277,10 +277,10 @@ def enrollResponse() {
|
||||
[
|
||||
//Resending the CIE in case the enroll request is sent before CIE is written
|
||||
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 2000",
|
||||
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
|
||||
//Enroll Response
|
||||
"raw 0x500 {01 23 00 00 00}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 2000"
|
||||
"raw 0x500 {01 23 00 00 00}",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -270,9 +270,9 @@ def configure() {
|
||||
|
||||
log.debug "Configuring Reporting and Bindings."
|
||||
def humidityConfigCmds = [
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0xFC45 {${device.zigbeeId}} {}", "delay 2000",
|
||||
"zcl global send-me-a-report 0xFC45 0 0x29 30 3600 {6400}", "delay 200",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 2000"
|
||||
"zdo bind 0x${device.deviceNetworkId} 1 1 0xFC45 {${device.zigbeeId}} {}", "delay 500",
|
||||
"zcl global send-me-a-report 0xFC45 0 0x29 30 3600 {6400}",
|
||||
"send 0x${device.deviceNetworkId} 1 1", "delay 500"
|
||||
]
|
||||
|
||||
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
|
||||
|
||||
@@ -86,7 +86,7 @@ def parse(String description) {
|
||||
def bodyString = msg.body
|
||||
if (bodyString) {
|
||||
unschedule("setOffline")
|
||||
def body = new XmlSlurper().parseText(bodyString.replaceAll("[^\\x20-\\x7e]", ""))
|
||||
def body = new XmlSlurper().parseText(bodyString)
|
||||
|
||||
if (body?.property?.TimeSyncRequest?.text()) {
|
||||
log.trace "Got TimeSyncRequest"
|
||||
|
||||
@@ -78,7 +78,7 @@ def parse(String description) {
|
||||
def bodyString = msg.body
|
||||
if (bodyString) {
|
||||
unschedule("setOffline")
|
||||
def body = new XmlSlurper().parseText(bodyString.replaceAll("[^\\x20-\\x7e]", ""))
|
||||
def body = new XmlSlurper().parseText(bodyString)
|
||||
if (body?.property?.TimeSyncRequest?.text()) {
|
||||
log.trace "Got TimeSyncRequest"
|
||||
result << timeSyncResponse()
|
||||
|
||||
@@ -84,7 +84,7 @@ def parse(String description) {
|
||||
def bodyString = msg.body
|
||||
if (bodyString) {
|
||||
unschedule("setOffline")
|
||||
def body = new XmlSlurper().parseText(bodyString.replaceAll("[^\\x20-\\x7e]", ""))
|
||||
def body = new XmlSlurper().parseText(bodyString)
|
||||
if (body?.property?.TimeSyncRequest?.text()) {
|
||||
log.trace "Got TimeSyncRequest"
|
||||
result << timeSyncResponse()
|
||||
@@ -208,7 +208,7 @@ def subscribe(ip, port) {
|
||||
def existingIp = getDataValue("ip")
|
||||
def existingPort = getDataValue("port")
|
||||
if (ip && ip != existingIp) {
|
||||
log.debug "Updating ip from $existingIp to $ip"
|
||||
log.debug "Updating ip from $existingIp to $ip"
|
||||
updateDataValue("ip", ip)
|
||||
def ipvalue = convertHexToIP(getDataValue("ip"))
|
||||
sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP changed to ${ipvalue}")
|
||||
@@ -291,4 +291,4 @@ User-Agent: CyberGarage-HTTP/1.0
|
||||
</u:GetBinaryState>
|
||||
</s:Body>
|
||||
</s:Envelope>""", physicalgraph.device.Protocol.LAN)
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,8 @@ metadata {
|
||||
|
||||
fingerprint inClusters: "0000, 0001, 0003, 0020, 0402, 0B05", outClusters: "0003, 0006, 0008, 0019", manufacturer: "OSRAM", model: "LIGHTIFY Dimming Switch", deviceJoinName: "OSRAM LIGHTIFY Dimming Switch"
|
||||
//fingerprint inClusters: "0000, 0001, 0003, 0020, 0500", outClusters: "0003,0019", manufacturer: "CentraLite", model: "3455-L", deviceJoinName: "Iris Care Pendant"
|
||||
fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0402, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model: "3460-L", deviceJoinName: "Iris Smart Button"
|
||||
fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model:"3450-L", deviceJoinName: "Iris KeyFob"
|
||||
//fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0402, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model: "3460-L", deviceJoinName: "Iris Smart Button"
|
||||
//fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model:"3450-L", deviceJoinName: "Iris KeyFob"
|
||||
}
|
||||
|
||||
simulator {}
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
/**
|
||||
* Copyright 2015 SmartThings
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* Z-Wave Door/Window Sensor
|
||||
*
|
||||
* Author: SmartThings
|
||||
* Date: 2013-11-3
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "Z-Wave Door Sensor as Smoke Detector", namespace: "smartthings", author: "SmartThings") {
|
||||
capability "Contact Sensor"
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
capability "Configuration"
|
||||
|
||||
fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x85,0x86,0x72"
|
||||
fingerprint deviceId: "0x07", inClusters: "0x30"
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x98"
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x80,0x71,0x85,0x70,0x72,0x86,0x30,0x31,0x84,0x59,0x73,0x5A,0x8F,0x98,0x7A", outClusters:"0x20" // Philio multi+
|
||||
}
|
||||
|
||||
// simulator metadata
|
||||
simulator {
|
||||
// status messages
|
||||
status "fire": "command: 2001, payload: FF"
|
||||
status "safe": "command: 2001, payload: 00"
|
||||
status "wake up": "command: 8407, payload: "
|
||||
}
|
||||
|
||||
// UI tile definitions
|
||||
tiles {
|
||||
standardTile("contact", "device.contact", width: 2, height: 2) {
|
||||
state "fire",label: '${name}',icon: "st.alarm.smoke.smoke",backgroundColor: "#ffa81e"
|
||||
state "safe",label: '${name}',icon: "st.alarm.smoke.clear",backgroundColor: "#79b821"
|
||||
}
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
}
|
||||
|
||||
main "contact"
|
||||
details(["contact", "battery"])
|
||||
}
|
||||
}
|
||||
|
||||
def parse(String description) {
|
||||
def result = null
|
||||
if (description.startsWith("Err 106")) {
|
||||
if (state.sec) {
|
||||
log.debug description
|
||||
} else {
|
||||
result = createEvent(
|
||||
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.",
|
||||
eventType: "ALERT",
|
||||
name: "secureInclusion",
|
||||
value: "failed",
|
||||
isStateChange: true,
|
||||
)
|
||||
}
|
||||
} else if (description != "updated") {
|
||||
def cmd = zwave.parse(description, [0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
|
||||
if (cmd) {
|
||||
result = zwaveEvent(cmd)
|
||||
}
|
||||
}
|
||||
log.debug "parsed '$description' to $result"
|
||||
return result
|
||||
}
|
||||
|
||||
def updated() {
|
||||
def cmds = []
|
||||
if (!state.MSR) {
|
||||
cmds = [
|
||||
command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()),
|
||||
"delay 1200",
|
||||
zwave.wakeUpV1.wakeUpNoMoreInformation().format()
|
||||
]
|
||||
} else if (!state.lastbat) {
|
||||
cmds = []
|
||||
} else {
|
||||
cmds = [zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
|
||||
}
|
||||
response(cmds)
|
||||
}
|
||||
|
||||
def configure() {
|
||||
commands([
|
||||
zwave.manufacturerSpecificV2.manufacturerSpecificGet(),
|
||||
zwave.batteryV1.batteryGet()
|
||||
], 6000)
|
||||
}
|
||||
|
||||
def sensorValueEvent(value) {
|
||||
if (value) {
|
||||
createEvent(name: "contact", value: "fire", descriptionText: "$device.displayName fire detected")
|
||||
} else {
|
||||
createEvent(name: "contact", value: "safe", descriptionText: "$device.displayName is safe")
|
||||
}
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
|
||||
{
|
||||
sensorValueEvent(cmd.value)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
|
||||
{
|
||||
sensorValueEvent(cmd.value)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
|
||||
{
|
||||
sensorValueEvent(cmd.value)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cmd)
|
||||
{
|
||||
sensorValueEvent(cmd.sensorValue)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)
|
||||
{
|
||||
sensorValueEvent(cmd.sensorState)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd)
|
||||
{
|
||||
def result = []
|
||||
if (cmd.notificationType == 0x06 && cmd.event == 0x16) {
|
||||
result << sensorValueEvent(1)
|
||||
} else if (cmd.notificationType == 0x06 && cmd.event == 0x17) {
|
||||
result << sensorValueEvent(0)
|
||||
} else if (cmd.notificationType == 0x07) {
|
||||
if (cmd.v1AlarmType == 0x07) { // special case for nonstandard messages from Monoprice door/window sensors
|
||||
result << sensorValueEvent(cmd.v1AlarmLevel)
|
||||
} else if (cmd.event == 0x01 || cmd.event == 0x02) {
|
||||
result << sensorValueEvent(1)
|
||||
} else if (cmd.event == 0x03) {
|
||||
result << createEvent(descriptionText: "$device.displayName covering was removed", isStateChange: true)
|
||||
if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()))
|
||||
} else if (cmd.event == 0x05 || cmd.event == 0x06) {
|
||||
result << createEvent(descriptionText: "$device.displayName detected glass breakage", isStateChange: true)
|
||||
} else if (cmd.event == 0x07) {
|
||||
if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()))
|
||||
result << createEvent(name: "motion", value: "active", descriptionText:"$device.displayName detected motion")
|
||||
}
|
||||
} else if (cmd.notificationType) {
|
||||
def text = "Notification $cmd.notificationType: event ${([cmd.event] + cmd.eventParameter).join(", ")}"
|
||||
result << createEvent(name: "notification$cmd.notificationType", value: "$cmd.event", descriptionText: text, displayed: false)
|
||||
} else {
|
||||
def value = cmd.v1AlarmLevel == 255 ? "active" : cmd.v1AlarmLevel ?: "inactive"
|
||||
result << createEvent(name: "alarm $cmd.v1AlarmType", value: value, displayed: false)
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
|
||||
{
|
||||
def event = createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)
|
||||
def cmds = []
|
||||
if (!state.MSR) {
|
||||
cmds << command(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
|
||||
cmds << "delay 1200"
|
||||
}
|
||||
if (!state.lastbat || now() - state.lastbat > 53*60*60*1000) {
|
||||
cmds << command(zwave.batteryV1.batteryGet())
|
||||
} else {
|
||||
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
|
||||
}
|
||||
[event, response(cmds)]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
|
||||
def map = [ name: "battery", unit: "%" ]
|
||||
if (cmd.batteryLevel == 0xFF) {
|
||||
map.value = 1
|
||||
map.descriptionText = "${device.displayName} has a low battery"
|
||||
map.isStateChange = true
|
||||
} else {
|
||||
map.value = cmd.batteryLevel
|
||||
}
|
||||
state.lastbat = now()
|
||||
[createEvent(map), response(zwave.wakeUpV1.wakeUpNoMoreInformation())]
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
|
||||
def result = []
|
||||
|
||||
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
|
||||
log.debug "msr: $msr"
|
||||
updateDataValue("MSR", msr)
|
||||
|
||||
retypeBasedOnMSR()
|
||||
|
||||
result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
|
||||
|
||||
if (msr == "011A-0601-0901") { // Enerwave motion doesn't always get the associationSet that the hub sends on join
|
||||
result << response(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId))
|
||||
} else if (!device.currentState("battery")) {
|
||||
if (msr == "0086-0102-0059") {
|
||||
result << response(zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.batteryV1.batteryGet()).format())
|
||||
} else {
|
||||
result << response(command(zwave.batteryV1.batteryGet()))
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
|
||||
def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
|
||||
// log.debug "encapsulated: $encapsulatedCommand"
|
||||
if (encapsulatedCommand) {
|
||||
state.sec = 1
|
||||
zwaveEvent(encapsulatedCommand)
|
||||
}
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.Command cmd) {
|
||||
createEvent(descriptionText: "$device.displayName: $cmd", displayed: false)
|
||||
}
|
||||
|
||||
private command(physicalgraph.zwave.Command cmd) {
|
||||
if (state.sec == 1) {
|
||||
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
|
||||
} else {
|
||||
cmd.format()
|
||||
}
|
||||
}
|
||||
|
||||
private commands(commands, delay=200) {
|
||||
delayBetween(commands.collect{ command(it) }, delay)
|
||||
}
|
||||
|
||||
def retypeBasedOnMSR() {
|
||||
switch (state.MSR) {
|
||||
case "0086-0002-002D":
|
||||
log.debug "Changing device type to Z-Wave Water Sensor"
|
||||
setDeviceType("Z-Wave Water Sensor")
|
||||
break
|
||||
case "011F-0001-0001": // Schlage motion
|
||||
case "014A-0001-0001": // Ecolink motion
|
||||
case "014A-0004-0001": // Ecolink motion +
|
||||
case "0060-0001-0002": // Everspring SP814
|
||||
case "0060-0001-0003": // Everspring HSP02
|
||||
case "011A-0601-0901": // Enerwave ZWN-BPC
|
||||
log.debug "Changing device type to Z-Wave Motion Sensor"
|
||||
setDeviceType("Z-Wave Motion Sensor")
|
||||
break
|
||||
case "013C-0002-000D": // Philio multi +
|
||||
log.debug "Changing device type to 3-in-1 Multisensor Plus (SG)"
|
||||
setDeviceType("3-in-1 Multisensor Plus (SG)")
|
||||
break
|
||||
case "0109-2001-0106": // Vision door/window
|
||||
log.debug "Changing device type to Z-Wave Plus Door/Window Sensor"
|
||||
setDeviceType("Z-Wave Plus Door/Window Sensor")
|
||||
break
|
||||
case "0109-2002-0205": // Vision Motion
|
||||
log.debug "Changing device type to Z-Wave Plus Motion/Temp Sensor"
|
||||
setDeviceType("Z-Wave Plus Motion/Temp Sensor")
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,6 @@ metadata {
|
||||
fingerprint mfr: "0060", prod: "0001", model: "0002", deviceJoinName: "Everspring Motion Sensor" // Everspring SP814
|
||||
fingerprint mfr: "0060", prod: "0001", model: "0003", deviceJoinName: "Everspring Motion Sensor" // Everspring HSP02
|
||||
fingerprint mfr: "011A", prod: "0601", model: "0901", deviceJoinName: "Enerwave Motion Sensor" // Enerwave ZWN-BPC
|
||||
fingerprint mfr: "0063", prod: "4953", model: "3133", deviceJoinName: "GE Smart Motion Sensor"
|
||||
}
|
||||
|
||||
simulator {
|
||||
|
||||
@@ -1,548 +1,253 @@
|
||||
/**
|
||||
* 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",
|
||||
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 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.switch", 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("/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 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 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 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
|
||||
}
|
||||
|
||||
//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) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
def watt = getMeterStatus(device.id)
|
||||
return [Device_state: device.currentSwitch] + 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 (command){
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.on();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def turnOffOutlet() {
|
||||
def device = outlets.find { it.id == params.id }
|
||||
if (command){
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
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')]
|
||||
}
|
||||
}
|
||||
|
||||
def turnOnSwitch() {
|
||||
def device = switches.find { it.id == params.id }
|
||||
if (command){
|
||||
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 (command){
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
|
||||
device.on();
|
||||
|
||||
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)
|
||||
return [Device_state: device.currentValue('temperature')] + 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
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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",
|
||||
namespace: "gideon.api",
|
||||
author: "Braindrain Solutions",
|
||||
description: "Gideon AI Smart app allows you to connect and control all of your SmartThings devices through the Gideon AI 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 AI API", displayLink: "gideon.ai"])
|
||||
|
||||
|
||||
preferences {
|
||||
section("Control these switches...") {
|
||||
input "switches", "capability.switch", multiple:true
|
||||
}
|
||||
section("Control these motion sensors...") {
|
||||
input "motions", "capability.motionSensor", multiple:true
|
||||
}
|
||||
section("Control these presence sensors...") {
|
||||
input "presence_sensors", "capability.presenceSensor", multiple:true
|
||||
}
|
||||
section("Control these outlets...") {
|
||||
input "outlets", "capability.switch", multiple:true
|
||||
}
|
||||
section("Control these locks...") {
|
||||
input "locks", "capability.lock", multiple:true
|
||||
}
|
||||
section("Control these locks...") {
|
||||
input "temperature_sensors", "capability.temperatureMeasurement"
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {
|
||||
log.debug "Installed with settings: ${settings}"
|
||||
|
||||
initialize()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "Updated with settings: ${settings}"
|
||||
|
||||
unsubscribe()
|
||||
initialize()
|
||||
}
|
||||
|
||||
def initialize() {
|
||||
// TODO: subscribe to attributes, devices, locations, etc.
|
||||
subscribe(outlet, "energy", outletHandler)
|
||||
subscribe(outlet, "switch", outletHandler)
|
||||
}
|
||||
|
||||
// TODO: implement event handlers
|
||||
def outletHandler(evt) {
|
||||
log.debug "$outlet.currentEnergy"
|
||||
//TODO call G API
|
||||
}
|
||||
|
||||
|
||||
private device(it, type) {
|
||||
it ? [id: it.id, label: it.label, type: type] : null
|
||||
}
|
||||
|
||||
//API Mapping
|
||||
mappings {
|
||||
path("/getalldevices") {
|
||||
action: [
|
||||
GET: "getAllDevices"
|
||||
]
|
||||
}
|
||||
path("/doorlocks/:id/:command") {
|
||||
action: [
|
||||
GET: "updateDoorLock"
|
||||
]
|
||||
}
|
||||
path("/doorlocks/:id") {
|
||||
action: [
|
||||
GET: "getDoorLockStatus"
|
||||
]
|
||||
}
|
||||
path("/tempsensors/:id") {
|
||||
action: [
|
||||
GET: "getTempSensorsStatus"
|
||||
]
|
||||
}
|
||||
path("/presences/:id") {
|
||||
action: [
|
||||
GET: "getPresenceStatus"
|
||||
]
|
||||
}
|
||||
path("/motions/:id") {
|
||||
action: [
|
||||
GET: "getMotionStatus"
|
||||
]
|
||||
}
|
||||
path("/outlets/:id") {
|
||||
action: [
|
||||
GET: "getOutletStatus"
|
||||
]
|
||||
}
|
||||
path("/outlets/:id/:command") {
|
||||
action: [
|
||||
GET: "updateOutlet"
|
||||
]
|
||||
}
|
||||
path("/switches/:command") {
|
||||
action: [
|
||||
PUT: "updateSwitch"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
//API Methods
|
||||
def getAllDevices() {
|
||||
def locks_list = locks.collect{device(it,"Lock")}
|
||||
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 temp_list = temperature_sensors.collect{device(it,"Temperature")}
|
||||
return [Locks: locks_list, Presences: presences_list, Motions: motions_list, Outlets: outlets_list, Switches: switches_list, Temperatures: temp_list]
|
||||
}
|
||||
|
||||
//LOCKS
|
||||
def getDoorLockStatus() {
|
||||
def device = locks.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
return [Device_state: device.currentValue('lock')]
|
||||
}
|
||||
}
|
||||
|
||||
def updateDoorLock() {
|
||||
def command = params.command
|
||||
def device = locks.find { it.id == params.id }
|
||||
if (command){
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
if(command == "toggle")
|
||||
{
|
||||
if(device.currentValue('lock') == "locked")
|
||||
device.unlock();
|
||||
else
|
||||
device.lock();
|
||||
|
||||
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 {
|
||||
return [Device_state: device.currentValue('presence')]
|
||||
}
|
||||
}
|
||||
|
||||
//MOTION
|
||||
def getMotionStatus() {
|
||||
|
||||
def device = motions.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
return [Device_state: device.currentValue('motion')]
|
||||
}
|
||||
}
|
||||
|
||||
//OUTLET
|
||||
def getOutletStatus() {
|
||||
|
||||
def device = outlets.find { it.id == params.id }
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
return [Device_state: device.currentSwitch, Current_watt: device.currentValue("energy")]
|
||||
}
|
||||
}
|
||||
|
||||
def updateOutlet() {
|
||||
|
||||
def command = params.command
|
||||
def device = outlets.find { it.id == params.id }
|
||||
if (command){
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
if(command == "toggle")
|
||||
{
|
||||
if(device.currentSwitch == "on")
|
||||
device.off();
|
||||
else
|
||||
device.on();
|
||||
|
||||
return [Device_id: params.id, result_action: "200"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//SWITCH
|
||||
def updateSwitch() {
|
||||
def command = params.command
|
||||
def device = switches.find { it.id == params.id }
|
||||
if (command){
|
||||
if (!device) {
|
||||
httpError(404, "Device not found")
|
||||
} else {
|
||||
if(command == "toggle")
|
||||
{
|
||||
if(device.currentSwitch == "on")
|
||||
device.off();
|
||||
else
|
||||
device.on();
|
||||
|
||||
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 {
|
||||
return [Device_state: device.currentValue('temperature')]
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
/**
|
||||
* Color Coordinator
|
||||
* Version 1.1.1 - 11/9/16
|
||||
* Version 1.1.0 - 11/9/16
|
||||
* By Michael Struck
|
||||
*
|
||||
* 1.0.0 - Initial release
|
||||
* 1.1.0 - Fixed issue where master can be part of slaves. This causes a loop that impacts SmartThings.
|
||||
* 1.1.1 - Fix NPE being thrown for slave/master inputs being empty.
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
@@ -34,17 +33,17 @@ preferences {
|
||||
|
||||
def mainPage() {
|
||||
dynamicPage(name: "mainPage", title: "", install: true, uninstall: false) {
|
||||
def masterInList = slaves?.id?.find{it==master?.id}
|
||||
def masterInList = slaves.id.find{it==master.id}
|
||||
if (masterInList) {
|
||||
section ("**WARNING**"){
|
||||
paragraph "You have included the Master Light in the Slave Group. This will cause a loop in execution. Please remove this device from the Slave Group.", image: "https://raw.githubusercontent.com/MichaelStruck/SmartThingsPublic/master/img/caution.png"
|
||||
}
|
||||
}
|
||||
section("Master Light") {
|
||||
input "master", "capability.colorControl", title: "Colored Light", required: true
|
||||
input "master", "capability.colorControl", title: "Colored Light"
|
||||
}
|
||||
section("Lights that follow the master settings") {
|
||||
input "slaves", "capability.colorControl", title: "Colored Lights", multiple: true, required: true, submitOnChange: true
|
||||
input "slaves", "capability.colorControl", title: "Colored Lights", multiple: true, required: false, submitOnChange: true
|
||||
}
|
||||
section([mobileOnly:true], "Options") {
|
||||
input "randomYes", "bool",title: "When Master Turned On, Randomize Color", defaultValue: false
|
||||
@@ -82,44 +81,40 @@ def init() {
|
||||
}
|
||||
//-----------------------------------
|
||||
def onOffHandler(evt){
|
||||
if (slaves && master) {
|
||||
if (!slaves?.id.find{it==master?.id}){
|
||||
if (master?.currentValue("switch") == "on"){
|
||||
if (randomYes) getRandomColorMaster()
|
||||
else slaves?.on()
|
||||
}
|
||||
else {
|
||||
slaves?.off()
|
||||
}
|
||||
}
|
||||
if (!slaves.id.find{it==master.id}){
|
||||
if (master.currentValue("switch") == "on"){
|
||||
if (randomYes) getRandomColorMaster()
|
||||
else slaves?.on()
|
||||
}
|
||||
else {
|
||||
slaves?.off()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def colorHandler(evt) {
|
||||
if (slaves && master) {
|
||||
if (!slaves?.id?.find{it==master?.id} && master?.currentValue("switch") == "on"){
|
||||
log.debug "Changing Slave units H,S,L"
|
||||
def dimLevel = master?.currentValue("level")
|
||||
def hueLevel = master?.currentValue("hue")
|
||||
def saturationLevel = master.currentValue("saturation")
|
||||
def newValue = [hue: hueLevel, saturation: saturationLevel, level: dimLevel as Integer]
|
||||
slaves?.setColor(newValue)
|
||||
try {
|
||||
log.debug "Changing Slave color temp"
|
||||
def tempLevel = master?.currentValue("colorTemperature")
|
||||
slaves?.setColorTemperature(tempLevel)
|
||||
}
|
||||
catch (e){
|
||||
log.debug "Color temp for master --"
|
||||
}
|
||||
}
|
||||
if (!slaves.id.find{it==master.id} && master.currentValue("switch") == "on"){
|
||||
log.debug "Changing Slave units H,S,L"
|
||||
def dimLevel = master.currentValue("level")
|
||||
def hueLevel = master.currentValue("hue")
|
||||
def saturationLevel = master.currentValue("saturation")
|
||||
def newValue = [hue: hueLevel, saturation: saturationLevel, level: dimLevel as Integer]
|
||||
slaves?.setColor(newValue)
|
||||
try {
|
||||
log.debug "Changing Slave color temp"
|
||||
def tempLevel = master.currentValue("colorTemperature")
|
||||
slaves?.setColorTemperature(tempLevel)
|
||||
}
|
||||
catch (e){
|
||||
log.debug "Color temp for master --"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def getRandomColorMaster(){
|
||||
def hueLevel = Math.floor(Math.random() *1000)
|
||||
def saturationLevel = Math.floor(Math.random() * 100)
|
||||
def dimLevel = master?.currentValue("level")
|
||||
def dimLevel = master.currentValue("level")
|
||||
def newValue = [hue: hueLevel, saturation: saturationLevel, level: dimLevel as Integer]
|
||||
log.debug hueLevel
|
||||
log.debug saturationLevel
|
||||
@@ -128,14 +123,12 @@ def getRandomColorMaster(){
|
||||
}
|
||||
|
||||
def tempHandler(evt){
|
||||
if (slaves && master) {
|
||||
if (!slaves?.id?.find{it==master?.id} && master?.currentValue("switch") == "on"){
|
||||
if (evt.value != "--") {
|
||||
log.debug "Changing Slave color temp based on Master change"
|
||||
def tempLevel = master.currentValue("colorTemperature")
|
||||
slaves?.setColorTemperature(tempLevel)
|
||||
}
|
||||
}
|
||||
if (!slaves.id.find{it==master.id} && master.currentValue("switch") == "on"){
|
||||
if (evt.value != "--") {
|
||||
log.debug "Changing Slave color temp based on Master change"
|
||||
def tempLevel = master.currentValue("colorTemperature")
|
||||
slaves?.setColorTemperature(tempLevel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +139,7 @@ private def textAppName() {
|
||||
}
|
||||
|
||||
private def textVersion() {
|
||||
def text = "Version 1.1.1 (12/13/2016)"
|
||||
def text = "Version 1.1.0 (11/09/2016)"
|
||||
}
|
||||
|
||||
private def textCopyright() {
|
||||
@@ -173,4 +166,4 @@ private def textHelp() {
|
||||
"This application will allow you to control the settings of multiple colored lights with one control. " +
|
||||
"Simply choose a master control light, and then choose the lights that will follow the settings of the master, "+
|
||||
"including on/off conditions, hue, saturation, level and color temperature. Also includes a random color feature."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user