Initial commit

This commit is contained in:
bflorian
2015-08-04 15:49:03 -07:00
commit 6ad3c4fd7a
322 changed files with 67201 additions and 0 deletions

View File

@@ -0,0 +1,293 @@
/**
* 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.
*
*/
metadata {
definition (name: "SmartSense Motion", namespace: "smartthings", author: "SmartThings") {
capability "Signal Strength"
capability "Motion Sensor"
capability "Sensor"
capability "Battery"
fingerprint profileId: "0104", deviceId: "013A", inClusters: "0000", outClusters: "0006"
fingerprint profileId: "FC01", deviceId: "013A"
}
simulator {
status "active": "zone report :: type: 19 value: 0031"
status "inactive": "zone report :: type: 19 value: 0030"
}
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")
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) {
state "battery", label:'${currentValue}% battery', unit:""/*, backgroundColors:[
[value: 5, color: "#BC2323"],
[value: 10, color: "#D04E00"],
[value: 15, color: "#F1D801"],
[value: 16, color: "#FFFFFF"]
]*/
}
/*
valueTile("lqi", "device.lqi", decoration: "flat", inactiveLabel: false) {
state "lqi", label:'${currentValue}% signal', unit:""
}
*/
main "motion"
details(["motion", "battery"/*, "lqi"*/])
}
}
def parse(String description) {
def results
if (isZoneType19(description) || !isSupportedDescription(description)) {
results = parseBasicMessage(description)
}
else if (isMotionStatusMessage(description)){
results = parseMotionStatusMessage(description)
}
results
}
private Map parseBasicMessage(description) {
def name = parseName(description)
def value = parseValue(description)
def linkText = getLinkText(device)
def descriptionText = parseDescriptionText(linkText, value, description)
def handlerName = value
def isStateChange = isStateChange(device, name, value)
def results = [
name: name,
value: value,
linkText: linkText,
descriptionText: descriptionText,
handlerName: handlerName,
isStateChange: isStateChange,
displayed: displayed(description, isStateChange)
]
log.debug "Parse returned $results.descriptionText"
return results
}
private String parseName(String description) {
if (isSupportedDescription(description)) {
return "motion"
}
null
}
private String parseValue(String description) {
if (isZoneType19(description)) {
if (translateStatusZoneType19(description)) {
return "active"
}
else {
return "inactive"
}
}
description
}
private parseDescriptionText(String linkText, String value, String description) {
switch(value) {
case "active": return "$linkText detected motion"
case "inactive": return "$linkText motion has stopped"
default: return value
}
}
private Boolean isMotionStatusMessage(String description) {
// "raw:7D360000001D55FF, dni:7D36, motion:00, battery:00, powerSource:00, rssi:1D, lqi:55, other:FF" - old (incorrect dev-conn parse)
// "raw:7D360000001D55FF, dni:7D36, motion:00, powerSource:0000, battery:00, rssi:1D, lqi:55, other:FF" - old (correct dev-conn parse)
// "raw:7D360000001D55FF, dni:7D36, motion:00, powerSource:00, battery:00, batteryDivisor:00, rssi:1D, lqi:55, other:FF" - new
description ==~ /raw:.*dni:.*motion:.*battery:.*powerSource:.*rssi:.*lqi:.*/ || description ==~ /raw:.*dni:.*motion:.*powerSource:.*battery:.*rssi:.*lqi:.*/
}
private List parseMotionStatusMessage(String description) {
def results = []
def parts = description.split(',')
parts.each { part ->
part = part.trim()
if (part.startsWith('motion:')) {
def motionResult = getMotionResult(part, description)
if (motionResult) {
results << motionResult
}
}
else if (part.startsWith('powerSource:')) {
def powerSourceResult = getPowerSourceResult(part, description)
if (powerSourceResult) {
results << powerSourceResult
}
}
else if (part.startsWith('battery:')) {
def batteryResult = getBatteryResult(part, description)
if (batteryResult) {
results << batteryResult
}
}
else if (part.startsWith('rssi:')) {
def rssiResult = getRssiResult(part, description)
if (rssiResult) {
results << rssiResult
}
}
else if (part.startsWith('lqi:')) {
def lqiResult = getLqiResult(part, description)
if (lqiResult) {
results << lqiResult
}
}
}
results
}
private getMotionResult(part, description) {
def name = "motion"
def valueString = part.split(":")[1].trim()
def valueInt = Integer.parseInt(valueString, 16)
def value = valueInt == 0 ? "inactive" : "active"
def linkText = getLinkText(device)
def descriptionText = parseDescriptionText(linkText, value, description)
def isStateChange = isStateChange(device, name, value)
[
name: name,
value: value,
linkText: linkText,
descriptionText: descriptionText,
handlerName: value,
isStateChange: isStateChange,
displayed: displayed(description, isStateChange)
]
}
private getPowerSourceResult(part, description) {
def name = "powerSource"
def valueString = part.split(":")[1].trim()
def valueInt = Integer.parseInt(valueString, 16)
def value = valueInt == 0 ? "battery" : "powered"
def linkText = getLinkText(device)
def descriptionText
if (value == "battery") {
descriptionText = "$linkText is ${value} powered"
}
else {
descriptionText = "$linkText is plugged in"
}
def isStateChange = isStateChange(device, name, value)
[
name: name,
value: value,
linkText: linkText,
descriptionText: descriptionText,
handlerName: name,
isStateChange: isStateChange,
displayed: false
]
}
private getBatteryResult(part, description) {
def name = "battery"
def valueString = part.split(":")[1].trim()
def valueInt = Integer.parseInt(valueString, 16)
// Temporarily disallow zero as a valid result b/c the current firmware has a bug where zero is only value being sent
// This effectively disables battery reporting for this device, so needs to be removed once FW is updated
if (valueInt == 0) return null
def batteryDivisor = description.split(",").find {it.split(":")[0].trim() == "batteryDivisor"} ? description.split(",").find {it.split(":")[0].trim() == "batteryDivisor"}.split(":")[1].trim() : null
def value = zigbee.parseSmartThingsBatteryValue(part, batteryDivisor)
def unit = "%"
def linkText = getLinkText(device)
def descriptionText = "$linkText battery was ${value}${unit}"
def isStateChange = isStateChange(device, name, value)
[
name: name,
value: value,
unit: unit,
linkText: linkText,
descriptionText: descriptionText,
handlerName: name,
isStateChange: isStateChange,
displayed: false
]
}
private getRssiResult(part, description) {
def name = "rssi"
def parts = part.split(":")
if (parts.size() != 2) return null
def valueString = parts[1].trim()
def valueInt = Integer.parseInt(valueString, 16)
def value = (valueInt - 128).toString()
def linkText = getLinkText(device)
def descriptionText = "$linkText was $value dBm"
def isStateChange = isStateChange(device, name, value)
[
name: name,
value: value,
unit: "dBm",
linkText: linkText,
descriptionText: descriptionText,
handlerName: null,
isStateChange: isStateChange,
displayed: false
]
}
/**
* Use LQI (Link Quality Indicator) as a measure of signal strength. The values
* are 0 to 255 (0x00 to 0xFF) and higher values represent higher signal
* strength. Return as a percentage of 255.
*
* Note: To make the signal strength indicator more accurate, we could combine
* LQI with RSSI.
*/
private getLqiResult(part, description) {
def name = "lqi"
def parts = part.split(":")
if (parts.size() != 2) return null
def valueString = parts[1].trim()
def valueInt = Integer.parseInt(valueString, 16)
def percentageOf = 255
def value = Math.round((valueInt / percentageOf * 100)).toString()
def unit = "%"
def linkText = getLinkText(device)
def descriptionText = "$linkText Signal (LQI) was ${value}${unit}"
def isStateChange = isStateChange(device, name, value)
[
name: name,
value: value,
unit: unit,
linkText: linkText,
descriptionText: descriptionText,
handlerName: null,
isStateChange: isStateChange,
displayed: false
]
}