Compare commits

..

1 Commits

Author SHA1 Message Date
Vinay Rao
b05d956d95 Merge pull request #830 from SmartThingsCommunity/staging
Rolling up changes to production from staging 2016-04-26 Release
2016-04-26 10:59:05 -07:00
14 changed files with 63 additions and 473 deletions

View File

@@ -24,7 +24,6 @@ metadata {
command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3010", deviceJoinName: "NYCE Door Hinge Sensor"
fingerprint inClusters: "0000,0001,0003,0406,0500,0020", manufacturer: "NYCE", model: "3011", deviceJoinName: "NYCE Door/Window Sensor"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3011", deviceJoinName: "NYCE Door/Window Sensor"
fingerprint inClusters: "0000,0001,0003,0406,0500,0020", manufacturer: "NYCE", model: "3014", deviceJoinName: "NYCE Tilt Sensor"

View File

@@ -31,7 +31,6 @@ metadata {
capability "Configuration"
capability "Refresh"
capability "Sensor"
capability "Health Check"
// indicates that device keeps track of heartbeat (in state.heartbeat)
attribute "heartbeat", "string"

View File

@@ -31,7 +31,6 @@ metadata {
capability "Refresh"
capability "Temperature Measurement"
capability "Water Sensor"
capability "Health Check"
command "enrollResponse"

View File

@@ -31,7 +31,6 @@ metadata {
capability "Battery"
capability "Temperature Measurement"
capability "Refresh"
capability "Health Check"
command "enrollResponse"

View File

@@ -35,7 +35,6 @@ metadata {
capability "Acceleration Sensor"
capability "Refresh"
capability "Temperature Measurement"
capability "Health Check"
command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3320"

View File

@@ -23,9 +23,8 @@
capability "Acceleration Sensor"
capability "Refresh"
capability "Temperature Measurement"
capability "Health Check"
command "enrollResponse"
command "enrollResponse"
}
simulator {

View File

@@ -20,7 +20,6 @@ metadata {
capability "Refresh"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Health Check"
fingerprint endpointId: "01", inClusters: "0001,0003,0020,0402,0B05,FC45", outClusters: "0019,0003"
}

View File

@@ -1,294 +0,0 @@
/**
* 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: "Test Arrival Sensor", namespace: "smartthings", author: "Mr.kim") {
capability "Tone"
capability "Actuator"
capability "Signal Strength"
capability "Presence Sensor"
capability "Sensor"
capability "Battery"
fingerprint profileId: "FC01", deviceId: "019A"
fingerprint profileId: "FC01", deviceId: "0131", inClusters: "0000,0003", outClusters: "0003"
fingerprint profileId: "FC01", deviceId: "0131", inClusters: "0000", outClusters: "0006"
}
simulator {
status "present": "presence: 1"
status "not present": "presence: 0"
status "battery": "battery: 27, batteryDivisor: 0A, rssi: 100, lqi: 64"
}
preferences {
section {
image(name: 'educationalcontent', multiple: true, images: [
"http://cdn.device-gse.smartthings.com/Arrival/Arrival1.jpg",
"http://cdn.device-gse.smartthings.com/Arrival/Arrival2.jpg"
])
}
}
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"
}
standardTile("beep", "device.beep", decoration: "flat") {
state "beep", label:'', action:"tone.beep", icon:"st.secondary.beep", 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 "presence"
details(["presence", "beep", "battery"/*, "lqi"*/])
}
}
def beep() {
/*
You can make the speaker turn on for 0.5-second beeps by sending some CLI commands:
Command: send raw, wait 7, send raw, wait 7, send raw
Future: new packet type "st.beep"
raw 0xFC05 {15 0A 11 00 00 15 01}
send 0x2F7F 2 2
where "0xABCD" is the node ID of the Smart Tag, everything else above is a constant. Except
the "15 01" at the end of the first raw command, that sets the speaker's period (reciprocal
of frequency). You can play with this value up or down to experiment with loudness as the
loudness will be strongly dependent upon frequency and the enclosure that it's in. Note that
"15 01" represents the hex number 0x0115 so a lower frequency is "16 01" (longer period) and
a higher frequency is "14 01" (shorter period). Note that since the tag only checks its parent
for messages every 5 seconds (while at rest) or every 3 seconds (while in motion) it will take
up to this long from the time you send the message to the time you hear a sound.
*/
[
"raw 0xFC05 {15 0A 11 00 00 15 01}",
"delay 7000",
"raw 0xFC05 {15 0A 11 00 00 15 01}",
"delay 7000",
"raw 0xFC05 {15 0A 11 00 00 15 01}",
"delay 7000",
"raw 0xFC05 {15 0A 11 00 00 15 01}",
"delay 7000",
"raw 0xFC05 {15 0A 11 00 00 15 01}"
]
}
def parse(String description) {
def results
if (isBatteryMessage(description)) {
results = parseBatteryMessage(description)
}
else {
results = parsePresenceMessage(description)
}
log.debug "Parse returned $results.descriptionText"
results
}
private Map parsePresenceMessage(String description) {
def name = parseName(description)
def value = parseValue(description)
def linkText = getLinkText(device)
def descriptionText = parseDescriptionText(linkText, value, description)
def handlerName = getState(value)
def isStateChange = isStateChange(device, name, value)
def results = [
name: name,
value: value,
unit: null,
linkText: linkText,
descriptionText: descriptionText,
handlerName: handlerName,
isStateChange: isStateChange,
displayed: displayed(description, isStateChange)
]
results
}
private String parseName(String description) {
if (description?.startsWith("presence: ")) {
return "presence"
}
null
}
private String parseValue(String description) {
if (description?.startsWith("presence: "))
{
if (description?.endsWith("1"))
{
return "present"
}
else if (description?.endsWith("0"))
{
return "not present"
}
}
description
}
private parseDescriptionText(String linkText, String value, String description) {
switch(value) {
case "present": return "$linkText has arrived"
case "not present": return "$linkText has left"
default: return value
}
}
private getState(String value) {
def state = value
if (value == "present") {
state = "arrived"
}
else if (value == "not present") {
state = "left"
}
state
}
private Boolean isBatteryMessage(String description) {
// "raw:36EF1C, dni:36EF, battery:1B, rssi:, lqi:"
description ==~ /.*battery:.*rssi:.*lqi:.*/
}
private List parseBatteryMessage(String description) {
def results = []
def parts = description.split(',')
parts.each { part ->
part = part.trim()
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 getBatteryResult(part, description) {
def batteryDivisor = description.split(",").find {it.split(":")[0].trim() == "batteryDivisor"} ? description.split(",").find {it.split(":")[0].trim() == "batteryDivisor"}.split(":")[1].trim() : null
def name = "battery"
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: displayed(description, 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: displayed(description, 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: displayed(description, isStateChange)
displayed: false
]
}

View File

@@ -80,31 +80,19 @@ metadata {
state "default", label:''
}
// multi-line text (explicit newlines)
standardTile("multiLine", "device.multiLine", width: 2, height: 2) {
state "default", label: '${currentValue}'
}
standardTile("multiLineWithIcon", "device.multiLine", width: 2, height: 2) {
state "default", label: '${currentValue}', icon: "st.switches.switch.off"
}
main("actionRings")
main("standard1")
details([
"actionRings", "actionFlat", "noActionFlat",
"flatLabel", "flatIconLabel", "flatIcon",
"flatDefaultState", "flatImplicitDefaultState1", "flatImplicitDefaultState2",
"multiLine", "multiLineWithIcon"
])
}
}
def installed() {
sendEvent(name: "switch", value: "off")
sendEvent(name: "multiLine", value: "Line 1\nLine 2\nLine 3")
}
def parse(String description) {

View File

@@ -69,25 +69,16 @@ metadata {
]
}
valueTile("noValue", "device.nada", width: 4, height: 2) {
valueTile("noValue", "device.nada", width: 2, height: 2) {
state "default", label:'${currentValue}'
}
valueTile("multiLine", "device.multiLine", width: 3, height: 2) {
state "default", label: '${currentValue}'
}
valueTile("multiLineWithIcon", "device.multiLine", width: 3, height: 2) {
state "default", label: '${currentValue}', icon: "st.switches.switch.off"
}
main("text")
details([
"text", "longText", "integer",
"integerFloat", "pi", "floatAsText",
"bgColor", "bgColorRange", "bgColorRangeSingleItem",
"bgColorRangeConflict", "noValue",
"multiLine", "multiLineWithIcon"
"bgColorRangeConflict", "noValue"
])
}
}
@@ -99,7 +90,6 @@ def installed() {
sendEvent(name: "integerFloat", value: 47.0)
sendEvent(name: "pi", value: 3.14159)
sendEvent(name: "floatAsText", value: "3.14159")
sendEvent(name: "multiLine", value: "Line 1\nLine 2\nLine 3")
}
def parse(String description) {

View File

@@ -67,47 +67,14 @@ metadata {
attributeState "VALUE_DOWN", action: "levelDown"
}
}
multiAttributeTile(name:"lengthyTile", type:"generic", width:6, height:4) {
tileAttribute("device.lengthyText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821"
}
tileAttribute("device.lengthyText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821"
}
}
multiAttributeTile(name:"multilineTile", type:"generic", width:6, height:4) {
tileAttribute("device.multilineText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821"
}
tileAttribute("device.multilineText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821"
}
}
multiAttributeTile(name:"lengthyTileWithIcon", type:"generic", width:6, height:4) {
tileAttribute("device.lengthyText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
tileAttribute("device.lengthyText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
}
multiAttributeTile(name:"multilineTileWithIcon", type:"generic", width:6, height:4) {
tileAttribute("device.multilineText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
tileAttribute("device.multilineText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
}
main(["basicTile"])
details(["basicTile", "sliderTile", "valueTile", "lengthyTile", "multilineTile", "lengthyTileWithIcon", "multilineTileWithIcon"])
details(["basicTile", "sliderTile", "valueTile"])
}
}
def installed() {
sendEvent(name: "lengthyText", value: "The value of this tile is long and should wrap to two lines")
sendEvent(name: "multilineText", value: "Line 1 YES\nLine 2 YES\nLine 3 NO")
}
def parse() {

View File

@@ -332,7 +332,8 @@ private addChildBulb(dni, hueType, name, hub, update=false, device = null) {
if (deviceType) {
return addChildDevice("smartthings", deviceType, dni, hub, ["label": name])
} else {
}
else {
log.warn "Device type $hueType not supported"
return null
}
@@ -348,10 +349,8 @@ def addBulbs() {
newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni }
if (newHueBulb != null) {
d = addChildBulb(dni, newHueBulb?.value?.type, newHueBulb?.value?.name, newHueBulb?.value?.hub)
if (d) {
log.debug "created ${d.displayName} with id $dni"
d.refresh()
}
log.debug "created ${d.displayName} with id $dni"
d.refresh()
} else {
log.debug "$dni in not longer paired to the Hue Bridge or ID changed"
}
@@ -359,7 +358,7 @@ def addBulbs() {
//backwards compatable
newHueBulb = bulbs.find { (app.id + "/" + it.id) == dni }
d = addChildBulb(dni, "Extended Color Light", newHueBulb?.value?.name, newHueBulb?.value?.hub)
d?.refresh()
d.refresh()
}
} else {
log.debug "found ${d.displayName} with id $dni already exists, type: '$d.typeName'"
@@ -825,7 +824,7 @@ def setColor(childDevice, huesettings) {
value.bri = Math.min(Math.round(huesettings.level * 255 / 100), 255)
}
value.alert = huesettings.alert ? huesettings.alert : "none"
value.transitiontime = huesettings.transitiontime ? huesettings.transitiontime : 4
value.transition = huesettings.transition ? huesettings.transition : 4
// Make sure to turn off light if requested
if (huesettings.switch == "off")

View File

@@ -1,56 +0,0 @@
/**
* 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.
*
* Turn It On For 5 Minutes
* Turn on a switch when a contact sensor opens and then turn it back off 5 minutes later.
*
* Author: SmartThings
*/
definition(
name: "Turn It On For 1 Minutes",
namespace: "smartthings",
author: "mr.kim",
description: "When a SmartSense Multi is opened, a switch will be turned on, and then turned off after 5 minutes.",
category: "Safety & Security",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/light_contact-outlet.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/light_contact-outlet@2x.png"
)
preferences {
section("When it opens..."){
input "contact1", "capability.contactSensor"
}
section("Turn on a switch for 5 minutes..."){
input "switch1", "capability.switch"
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
subscribe(contact1, "contact.open", contactOpenHandler)
}
def updated(settings) {
log.debug "Updated with settings: ${settings}"
unsubscribe()
subscribe(contact1, "contact.open", contactOpenHandler)
}
def contactOpenHandler(evt) {
switch1.on()
def fiveMinuteDelay = 60 * 1
runIn(fiveMinuteDelay, turnOffSwitch)
}
def turnOffSwitch() {
switch1.off()
}

View File

@@ -236,22 +236,23 @@ def addSwitches() {
d = getChildDevices()?.find {
it.deviceNetworkId == selectedSwitch.value.mac || it.device.getDataValue("mac") == selectedSwitch.value.mac
}
if (!d) {
log.debug "Creating WeMo Switch with dni: ${selectedSwitch.value.mac}"
d = addChildDevice("smartthings", "Wemo Switch", selectedSwitch.value.mac, selectedSwitch?.value.hub, [
"label": selectedSwitch?.value?.name ?: "Wemo Switch",
"data": [
"mac": selectedSwitch.value.mac,
"ip": selectedSwitch.value.ip,
"port": selectedSwitch.value.port
]
])
def ipvalue = convertHexToIP(selectedSwitch.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
}
}
if (!d) {
log.debug "Creating WeMo Switch with dni: ${selectedSwitch.value.mac}"
d = addChildDevice("smartthings", "Wemo Switch", selectedSwitch.value.mac, selectedSwitch?.value.hub, [
"label": selectedSwitch?.value?.name ?: "Wemo Switch",
"data": [
"mac": selectedSwitch.value.mac,
"ip": selectedSwitch.value.ip,
"port": selectedSwitch.value.port
]
])
def ipvalue = convertHexToIP(selectedSwitch.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
}
}
}
@@ -266,22 +267,23 @@ def addMotions() {
d = getChildDevices()?.find {
it.deviceNetworkId == selectedMotion.value.mac || it.device.getDataValue("mac") == selectedMotion.value.mac
}
if (!d) {
log.debug "Creating WeMo Motion with dni: ${selectedMotion.value.mac}"
d = addChildDevice("smartthings", "Wemo Motion", selectedMotion.value.mac, selectedMotion?.value.hub, [
"label": selectedMotion?.value?.name ?: "Wemo Motion",
"data": [
"mac": selectedMotion.value.mac,
"ip": selectedMotion.value.ip,
"port": selectedMotion.value.port
]
])
def ipvalue = convertHexToIP(selectedMotion.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
}
}
if (!d) {
log.debug "Creating WeMo Motion with dni: ${selectedMotion.value.mac}"
d = addChildDevice("smartthings", "Wemo Motion", selectedMotion.value.mac, selectedMotion?.value.hub, [
"label": selectedMotion?.value?.name ?: "Wemo Motion",
"data": [
"mac": selectedMotion.value.mac,
"ip": selectedMotion.value.ip,
"port": selectedMotion.value.port
]
])
def ipvalue = convertHexToIP(selectedMotion.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
}
}
}
@@ -296,22 +298,23 @@ def addLightSwitches() {
d = getChildDevices()?.find {
it.deviceNetworkId == selectedLightSwitch.value.mac || it.device.getDataValue("mac") == selectedLightSwitch.value.mac
}
if (!d) {
log.debug "Creating WeMo Light Switch with dni: ${selectedLightSwitch.value.mac}"
d = addChildDevice("smartthings", "Wemo Light Switch", selectedLightSwitch.value.mac, selectedLightSwitch?.value.hub, [
"label": selectedLightSwitch?.value?.name ?: "Wemo Light Switch",
"data": [
"mac": selectedLightSwitch.value.mac,
"ip": selectedLightSwitch.value.ip,
"port": selectedLightSwitch.value.port
]
])
def ipvalue = convertHexToIP(selectedLightSwitch.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "created ${d.displayName} with id $dni"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
}
}
if (!d) {
log.debug "Creating WeMo Light Switch with dni: ${selectedLightSwitch.value.mac}"
d = addChildDevice("smartthings", "Wemo Light Switch", selectedLightSwitch.value.mac, selectedLightSwitch?.value.hub, [
"label": selectedLightSwitch?.value?.name ?: "Wemo Light Switch",
"data": [
"mac": selectedLightSwitch.value.mac,
"ip": selectedLightSwitch.value.ip,
"port": selectedLightSwitch.value.port
]
])
def ipvalue = convertHexToIP(selectedLightSwitch.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "created ${d.displayName} with id $dni"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
}
}
}