Compare commits

...

47 Commits

Author SHA1 Message Date
Sai
3e738ba82e Modifying 'Billion Single Phase Smart Meter Device Type' 2015-10-14 22:53:17 -05:00
Sai
395989785a Modifying 'Billion Single Phase Smart Meter Device Type' 2015-09-03 06:06:50 -05:00
Sai
024a33e425 MSA-63: Device type for Billion Single Phase Smart Meter that has the following attributes - Energy, Power, Voltage, Current, Frequency, Power Factor and Apparent Power. 2015-09-03 05:06:56 -05:00
Matthew Nohr
b1680e2f18 Merge pull request #85 from mrnohr/main-tile-fix-rollback
Rollback changes for active tile fix
2015-09-02 20:24:03 -05:00
Matt Nohr
5e1ce98314 Rollback changes for active tile fix 2015-09-02 20:01:29 -05:00
tslagle13
3903e2fad9 Update thermostat-mode-director.groovy 2015-09-02 17:25:29 -05:00
Matthew Nohr
e1077fcce4 Merge pull request #94 from mrnohr/education-images
Adding education images
2015-09-02 13:04:12 -05:00
Matt Nohr
84f873a536 Adding education images 2015-09-02 13:03:01 -05:00
Kristofer Schaller
b2e5538bc5 Merge pull request #91 from kris-schaller/master
Updating notify me when description
2015-09-02 00:49:31 -07:00
Kris Schaller
e907deeed2 Updating notify me when description 2015-09-02 00:48:48 -07:00
Kristofer Schaller
9d34d22bba Merge pull request #90 from kris-schaller/master
Changing description for smartapps
2015-09-01 14:36:17 -07:00
Kris Schaller
dcd1380f4b Changing description for smartapps 2015-09-01 14:35:14 -07:00
Vinay Rao
a49542c614 Merge pull request #89 from workingmonk/centralite_thermostat
[PROB-516] as Integer causes the temp to be off by 1
2015-09-01 13:59:35 -07:00
Vinay Rao
33d9efad23 as Integer causes the temp to be off by 1 2015-09-01 13:42:07 -07:00
Tyler Lange
7ff18e5145 Merge pull request #34 from 625alex/patch-1
added "Sensor" capability - missing from device type.
2015-09-01 12:34:47 -07:00
Tyler Lange
09aeb7b9b9 Merge pull request #40 from 625alex/patch-2
added "Sensor" capability to SmartWeather Station Tile. This is a virtual device that can provide temperature information to SmartApps and should have likely contained "sensor" to begin with.
2015-09-01 12:00:39 -07:00
Vinay Rao
caeda8f100 Merge pull request #87 from workingmonk/garagedoor_wording
Small fix to the wording
2015-08-31 21:08:27 -07:00
Vinay Rao
d65400ac0e Small fix to the wording 2015-08-31 21:07:10 -07:00
Vinay Rao
fe1fa5d62c Merge pull request #86 from workingmonk/garageDoor
[DVCSMP-811] Garage door preference based DTH with icon support
2015-08-31 20:55:03 -07:00
Vinay Rao
7161990f39 Updating the label for the garage icons 2015-08-31 20:06:40 -07:00
Vinay Rao
139c44a85e Garage door preference based DTH with icon support 2015-08-31 07:08:43 -07:00
Vinay Rao
e07c78e9c6 Merge pull request #83 from workingmonk/enrollment_changes_nonST
Fixing the enrollment issue for the remaining IAS devices.
2015-08-29 21:55:01 -07:00
Vinay Rao
72d4696508 Merge pull request #84 from larsfinander/smartOutletHeartAdd
Smart outlet heartbeat fix
2015-08-29 20:38:02 -07:00
larsfinander
45da8e9fee Smart outlet heartbeat fix
-Readded heartbeat calls that were accidentally removed.
2015-08-29 20:26:44 -07:00
Vinay Rao
e3facfcb32 Fixing the enrollment issue for the remaining IAS devices. Also cleared the long standing typo "Confuguring" 2015-08-29 20:14:26 -07:00
Vinay Rao
b611794854 Merge pull request #79 from mrnohr/main-tile-fix
Fix for main tile issue
2015-08-27 11:13:01 -07:00
Vinay Rao
0353a059f0 Merge pull request #37 from workingmonk/smartpower_new_dt
Updating smartpower outlet device type to use zigbee library
2015-08-26 20:44:48 -07:00
Vinay Rao
25ce6096b7 using the library converter and returning empty map 2015-08-26 20:34:19 -07:00
Vinay Rao
debf5468bd Merge pull request #43 from SmartThingsCommunity/patch_from_private
Update smartsense-moisture.groovy
2015-08-26 20:32:00 -07:00
Matt Nohr
0afd090d1e Temporary fix so users can select main tiles 2015-08-26 21:09:07 -05:00
Bill Fern
7571309def Merge pull request #45 from whfern/feature/CREX-2640
CREX-2640: Adding labels to moisture sensor attribute states.
2015-08-26 08:54:38 -05:00
Vinay Rao
b10308fe5c Handling the power issues via configuring 2015-08-25 20:57:27 -07:00
Vinay Rao
b6352e8548 Merge pull request #46 from mrnohr/icon-updates
Add back canChangeIcon to device types
2015-08-25 19:58:42 -07:00
Matt Nohr
9b67f4f894 Add back canChangeIcon to device types 2015-08-25 21:04:34 -05:00
Bill Fern
572e1027c0 CREX-2640: Adding labels to moisture sensor attribute states.
We need to have labels present so that the states can be properly
labeled in the new versions of client applications. This causes a slight
experience degradation in older versions of the app, but the impact is
understood.
2015-08-25 15:54:00 -05:00
Vinay Rao
91719ba5ca Updating the power config based on the discussion with CentraLite and the sniffer data 2015-08-25 13:10:18 -07:00
Vinay Rao
b5e3b91336 Update smartsense-moisture.groovy 2015-08-25 11:35:00 -07:00
625alex
22b4722f9c added "Sensor" capability 2015-08-24 11:51:47 -06:00
Matthew Nohr
df9a3b1343 Merge pull request #35 from workingmonk/moisture_sensor_tile
Moisture sensor UI temperature issue
2015-08-24 08:29:38 -05:00
Matthew Nohr
4ef6b0f4d7 Merge pull request #38 from mrnohr/matt/hue-tile-update
Update tiles for Hue Bulb
2015-08-24 06:15:35 -05:00
Matt Nohr
5ceb48647e Update tiles 2015-08-23 20:35:29 -05:00
Vinay Rao
e453c337e2 Updating smartpower outlet device type to use zigbee library 2015-08-23 18:22:44 -07:00
Vinay Rao
8f0cce8665 Small fix fixing tile issue on new ui 2015-08-21 16:20:45 -07:00
Vinay Rao
d2fc763a0e Merge pull request #33 from workingmonk/enrollment_changes
Updating device types for v2 zigbee eui changes and enrollment changes
2015-08-21 16:12:31 -07:00
Vinay Rao
35cfd1bc27 Adding enroll changes to the open-close sensors 2015-08-21 09:56:34 -07:00
625alex
9c8cf9d686 added "Sensor" capability 2015-08-20 21:09:04 -06:00
Vinay Rao
2df48cf6b3 Updating device types for v2 zigbee eui changes and enrollment changes for centralite devices 2015-08-20 16:59:37 -07:00
26 changed files with 758 additions and 347 deletions

View File

@@ -0,0 +1,246 @@
/**
* Copyright 2015 Intraix
*
* 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.
*
* Billion Smart Meter
*
* Author: Intraix
* Date: 2015-09-03
*/
metadata {
definition(name: "Billion Smart Meter", namespace: "intraix", author: "Intraix") {
capability "Actuator"
capability "Sensor"
capability "Configuration"
capability "Refresh"
capability "Switch"
capability "Energy Meter"
capability "Power Meter"
// Custom attiributes for capabilities not supported by ST
attribute "voltage", "number"
attribute "current", "number"
attribute "frequency", "number"
attribute "powerFactor", "number"
attribute "apparentPower", "number"
fingerprint profileId: "0104", inClusters: "0000,0003,0006,0702", outClusters: ""
}
// simulator metadata
simulator {
// status messages
status "on": "on/off: 1"
status "off": "on/off: 0"
// reply messages
reply "zcl on-off on": "on/off: 1"
reply "zcl on-off off": "on/off: 0"
}
// UI 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", 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 "turningOff", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 1, height: 1) {
state "default", label: "", action: "refresh.refresh", icon: "st.secondary.refresh"
}
valueTile("energy", "device.energy", decoration: "flat", width: 1, height: 1) {
state "energy", label: '${currentValue} kWh'
}
valueTile("power", "device.power", decoration: "flat", width: 1, height: 1) {
state "power", label: '${currentValue} W'
}
valueTile("voltage", "device.voltage", decoration: "flat", width: 1, height: 1) {
state "voltage", label: '${currentValue} V'
}
valueTile("current", "device.current", decoration: "flat", width: 1, height: 1) {
state "current", label: '${currentValue} A'
}
valueTile("frequency", "device.frequency", decoration: "flat", width: 1, height: 1) {
state "frequency", label: '${currentValue} Hz'
}
valueTile("powerFactor", "device.powerFactor", decoration: "flat", width: 1, height: 1) {
state "powerFactor", label: 'Power Factor ${currentValue}'
}
valueTile("apparentPower", "device.apparentPower", decoration: "flat", width: 1, height: 1) {
state "apparentPower", label: '${currentValue} VA'
}
main(["switch", "energy", "power", "voltage", "current", "frequency", "powerFactor", "apparentPower"])
details(["switch", "energy", "power", "voltage", "current", "frequency", "powerFactor", "apparentPower", "refresh"])
}
}
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "Parse description $description"
def events = []
if (description?.startsWith("catchall:")) {
def descMap = parseCatchAllAsMap(description)
log.debug "Catch all parsing: $description"
// Command 01 is Read Attributes response and Command 0A is Report Attributes response.
if (descMap.command == "01" || descMap.command == "0A") {
if (descMap.clusterId == "0006") {
// The last byte is the on/off value = 01/00.
def value = descMap.raw.endsWith("01") ? "on" : "off"
def event = createEvent(name: "switch", value: value)
events.add(event)
} else if (descMap.clusterId == "0702") {
// The last 21 bytes are the energy data payload, which is 42 characters.
def payload = descMap.raw.substring(descMap.raw.length() - 42, descMap.raw.length())
log.debug "payload is $payload"
events.addAll(parseEnergyPayload(payload))
}
}
} else if (description?.startsWith("read attr -")) {
def descMap = parseDescriptionAsMap(description)
log.debug "Read attr: $description"
if (descMap.cluster == "0006" && descMap.attrId == "0000") {
def value = descMap.value.endsWith("01") ? "on" : "off"
def event = createEvent(name: "switch", value: value)
events.add(event)
} else if (descMap.cluster == "0702" && descMap.attrId == "8000") {
// Payload length is 21 bytes, which is 42 characters
def payload = descMap.raw.substring(descMap.raw.length() - 42, descMap.raw.length())
log.trace "payload is $payload"
events.addAll(parseEnergyPayload(payload))
}
} else if (description?.startsWith("on/off:")) {
log.debug "Switch command"
def value = description?.endsWith(" 1") ? "on" : "off"
def event = createEvent(name: "switch", value: value)
events.add(event)
}
log.debug "Parse returned ${events}"
return events
}
def parseEnergyPayload(payload) {
def events = []
// Decode the various parameters from the payload
def voltage = Integer.parseInt(payload.substring(0, 4), 16) / 100
log.trace "voltage is $voltage"
def voltageEvent = createEvent(name: "voltage", value: voltage)
events.add(voltageEvent)
def current = Integer.parseInt(payload.substring(4, 8), 16) / 100
log.trace "current is $current"
def currentEvent = createEvent(name: "current", value: current)
events.add(currentEvent)
def frequency = Integer.parseInt(payload.substring(8, 12), 16) / 100
log.trace "frequency is $frequency"
def frequencyEvent = createEvent(name: "frequency", value: frequency)
events.add(frequencyEvent)
def powerFactor = Integer.parseInt(payload.substring(12, 14), 16) / 100
log.trace "powerFactor is $powerFactor"
def powerFactorEvent = createEvent(name: "powerFactor", value: powerFactor)
events.add(powerFactorEvent)
def activePower = Integer.parseInt(payload.substring(14, 22), 16) / 100
log.trace "activePower is $activePower"
def powerEvent = createEvent(name: "power", value: activePower)
events.add(powerEvent)
def apparentPower = Integer.parseInt(payload.substring(22, 30), 16) / 100
log.trace "apparentPower is $apparentPower"
def apparentPowerEvent = createEvent(name: "apparentPower", value: apparentPower)
events.add(apparentPowerEvent)
def mainEnergy = Integer.parseInt(payload.substring(30, 42), 16) / 1000
log.trace "mainEnergy is $mainEnergy"
def energyEvent = createEvent(name: "energy", value: mainEnergy)
events.add(energyEvent)
return events
}
def parseDescriptionAsMap(description) {
(description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()): nameAndValue[1].trim()]
}
}
def parseCatchAllAsMap(description) {
def seg = (description - "catchall: ").split(" ")
def zigbeeMap = [:]
zigbeeMap += [raw: (description - "catchall: ")]
zigbeeMap += [profileId: seg[0]]
zigbeeMap += [clusterId: seg[1]]
zigbeeMap += [sourceEndpoint: seg[2]]
zigbeeMap += [destinationEndpoint: seg[3]]
zigbeeMap += [options: seg[4]]
zigbeeMap += [messageType: seg[5]]
zigbeeMap += [dni: seg[6]]
zigbeeMap += [isClusterSpecific: Short.valueOf(seg[7], 16) != 0]
zigbeeMap += [isManufacturerSpecific: Short.valueOf(seg[8], 16) != 0]
zigbeeMap += [manufacturerId: seg[9]]
zigbeeMap += [command: seg[10]]
zigbeeMap += [direction: seg[11]]
zigbeeMap += [data: seg.size() > 12 ? seg[12].split("").findAll { it }.collate(2).collect {
it.join('')
} : []]
zigbeeMap
}
// Commands to device
def on() {
// Fire event for on since meter doesn't suppport zigbee bind
sendEvent(name: "switch", value: "on")
'zcl on-off on'
}
def off() {
// Fire event for off since meter doesn't suppport zigbee bind
sendEvent(name: "switch", value: "off")
'zcl on-off off'
}
def configure() {
meterConfig() + onOffConfig() + refresh()
}
// Meter reporting, min inteval 3 min and reporting interval if no activity as 4 min
// min change in value is 01
def meterConfig() {
[
"zcl global send-me-a-report 0x0702 0x8000 0x41 180 240 {01}",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
]
}
// Switch reporting, min interval 5 min and reporting interval if no activity as 10 min
// min change in value is 01
def onOffConfig() {
[
"zcl global send-me-a-report 6 0 0x10 300 600 {01}",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
]
}
// Read the meter and on/off cluster attributes
def refresh() {
[
"st rattr 0x${device.deviceNetworkId} 1 6 0", "delay 500",
"st rattr 0x${device.deviceNetworkId} 1 0x0702 0x8000"
]
}

View File

@@ -40,7 +40,7 @@ metadata {
}
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4){
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", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"

View File

@@ -153,31 +153,37 @@ def refresh()
//}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16) / 100
if(getTemperatureScale() == "C"){
return celsius
} else {
return celsiusToFahrenheit(celsius) as Integer
if (value != null) {
def celsius = Integer.parseInt(value, 16) / 100
if (getTemperatureScale() == "C") {
return celsius
} else {
return Math.round(celsiusToFahrenheit(celsius))
}
}
}
def setHeatingSetpoint(degrees) {
def temperatureScale = getTemperatureScale()
def degreesInteger = degrees as Integer
log.debug "setHeatingSetpoint({$degreesInteger} ${temperatureScale})"
sendEvent("name":"heatingSetpoint", "value":degreesInteger)
def celsius = (getTemperatureScale() == "C") ? degreesInteger : (fahrenheitToCelsius(degreesInteger) as Double).round(2)
"st wattr 0x${device.deviceNetworkId} 1 0x201 0x12 0x29 {" + hex(celsius*100) + "}"
if (degrees != null) {
def temperatureScale = getTemperatureScale()
def degreesInteger = Math.round(degrees)
log.debug "setHeatingSetpoint({$degreesInteger} ${temperatureScale})"
sendEvent("name": "heatingSetpoint", "value": degreesInteger)
def celsius = (getTemperatureScale() == "C") ? degreesInteger : (fahrenheitToCelsius(degreesInteger) as Double).round(2)
"st wattr 0x${device.deviceNetworkId} 1 0x201 0x12 0x29 {" + hex(celsius * 100) + "}"
}
}
def setCoolingSetpoint(degrees) {
def degreesInteger = degrees as Integer
log.debug "setCoolingSetpoint({$degreesInteger} ${temperatureScale})"
sendEvent("name":"coolingSetpoint", "value":degreesInteger)
def celsius = (getTemperatureScale() == "C") ? degreesInteger : (fahrenheitToCelsius(degreesInteger) as Double).round(2)
"st wattr 0x${device.deviceNetworkId} 1 0x201 0x11 0x29 {" + hex(celsius*100) + "}"
if (degrees != null) {
def degreesInteger = Math.round(degrees)
log.debug "setCoolingSetpoint({$degreesInteger} ${temperatureScale})"
sendEvent("name": "coolingSetpoint", "value": degreesInteger)
def celsius = (getTemperatureScale() == "C") ? degreesInteger : (fahrenheitToCelsius(degreesInteger) as Double).round(2)
"st wattr 0x${device.deviceNetworkId} 1 0x201 0x11 0x29 {" + hex(celsius * 100) + "}"
}
}
def modes() {

View File

@@ -143,8 +143,7 @@ def setLevel(value) {
def configure() {
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting and Bindings."
log.debug "Configuring Reporting and Bindings."
def configCmds = [
//Switch Reporting

View File

@@ -330,8 +330,7 @@ def setLevel(value) {
def configure() {
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting and Bindings."
log.debug "Configuring Reporting and Bindings."
def configCmds = [
//Switch Reporting

View File

@@ -23,36 +23,28 @@ metadata {
// TODO: define status and reply messages here
}
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821"
state "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff"
}
standardTile("reset", "device.reset", inactiveLabel: false, decoration: "flat") {
state "default", label:"Color Reset", action:"reset", icon:"st.lights.philips.hue-single"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
controlTile("rgbSelector", "device.color", "color", height: 3, width: 3, inactiveLabel: false) {
state "color", action:"setAdjustedColor"
}
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false, range:"(0..100)") {
state "level", action:"switch level.setLevel"
}
valueTile("level", "device.level", inactiveLabel: false, decoration: "flat") {
state "level", label: 'Level ${currentValue}%'
}
controlTile("saturationSliderControl", "device.saturation", "slider", height: 1, width: 2, inactiveLabel: false) {
state "saturation", action:"color control.setSaturation"
}
valueTile("saturation", "device.saturation", inactiveLabel: false, decoration: "flat") {
state "saturation", label: 'Sat ${currentValue} '
}
controlTile("hueSliderControl", "device.hue", "slider", height: 1, width: 2, inactiveLabel: false) {
state "hue", action:"color control.setHue"
}
valueTile("hue", "device.hue", inactiveLabel: false, decoration: "flat") {
state "hue", label: 'Hue ${currentValue} '
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.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
tileAttribute ("device.color", key: "COLOR_CONTROL") {
attributeState "color", action:"setAdjustedColor"
}
}
standardTile("reset", "device.reset", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"Reset Color", action:"reset", icon:"st.lights.philips.hue-single"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
}
main(["switch"])

View File

@@ -201,10 +201,10 @@ def refresh()
def configure() {
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting, IAS CIE, and Bindings."
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeId}}", "delay 200",
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global send-me-a-report 1 0x20 0x20 0x3600 0x3600 {01}", "delay 200",

View File

@@ -280,7 +280,7 @@ private List parseIasMessage(String description) {
}
def configure() {
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
def configCmds = [
//battery reporting and heartbeat
@@ -290,7 +290,7 @@ def configure() {
// Writes CIE attribute on end device to direct reports to the hub's EUID
"zcl global write 0x500 0x10 0xf0 {${zigbeeId}}", "delay 200",
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
]

View File

@@ -41,7 +41,7 @@ metadata {
}
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4){
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", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
@@ -287,7 +287,8 @@ def isDescriptionPower(descMap) {
def powerValue = "undefined"
if (descMap.cluster == "0B04") {
if (descMap.attrId == "050b") {
powerValue = convertHexToInt(descMap.value)
if(descMap.value!="ffff")
powerValue = convertHexToInt(descMap.value)
}
}
else if (descMap.clusterId == "0B04") {
@@ -327,10 +328,9 @@ def levelConfig() {
//min change in value is 05
def powerConfig() {
[
//Meter (Power) Reporting
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x0B04 0x050B 0x2A 1 600 {05}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500"
"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
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
]
}

View File

@@ -1,8 +1,19 @@
/**
* CentraLite Switch
* 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.
*
* SmartPower Outlet (CentraLite)
*
* Author: SmartThings
* Date: 2013-12-02
* Date: 2015-08-23
*/
metadata {
// Automatically generated. Make future change here.
@@ -31,22 +42,33 @@ metadata {
reply "zcl on-off off": "on/off: 0"
}
preferences {
section {
image(name: 'educationalcontent', multiple: true, images: [
"http://cdn.device-gse.smartthings.com/Outlet/US/OutletUS1.png",
"http://cdn.device-gse.smartthings.com/Outlet/US/OutletUS2.png"
])
}
}
// UI tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4){
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
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: "#79b821", nextState: "turningOff"
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "turningOn", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "turningOff", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
}
tileAttribute ("power", key: "SECONDARY_CONTROL") {
attributeState "power", label:'${currentValue} W'
}
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
main "switch"
details(["switch","refresh"])
}
@@ -54,67 +76,92 @@ metadata {
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "Parse description $description"
def name = null
def value = null
log.debug "description is $description"
// save heartbeat (i.e. last time we got a message from device)
state.heartbeat = Calendar.getInstance().getTimeInMillis()
if (description?.startsWith("read attr -")) {
def descMap = parseDescriptionAsMap(description)
log.debug "Read attr: $description"
if (descMap.cluster == "0006" && descMap.attrId == "0000") {
name = "switch"
value = descMap.value.endsWith("01") ? "on" : "off"
} else if (descMap.cluster.equalsIgnoreCase("0B04") && descMap.attrId.equalsIgnoreCase("050b")) {
def reportValue = descMap.value
name = "power"
//power divisor is 10
value = Integer.parseInt(reportValue, 16) / 10
def finalResult = zigbee.getKnownDescription(description)
//TODO: Remove this after getKnownDescription can parse it automatically
if (!finalResult && description!="updated")
finalResult = getPowerDescription(zigbee.parseDescriptionAsMap(description))
if (finalResult) {
log.info finalResult
if (finalResult.type == "update") {
log.info "$device updates: ${finalResult.value}"
}
else if (finalResult.type == "power") {
def powerValue = (finalResult.value as Integer)/10
sendEvent(name: "power", value: powerValue)
/*
Dividing by 10 as the Divisor is 10000 and unit is kW for the device. AttrId: 0302 and 0300. Simplifying to 10
power level is an integer. The exact power level with correct units needs to be handled in the device type
to account for the different Divisor value (AttrId: 0302) and POWER Unit (AttrId: 0300). CLUSTER for simple metering is 0702
*/
}
else {
sendEvent(name: finalResult.type, value: finalResult.value)
}
} else if (description?.startsWith("on/off:")) {
log.debug "Switch command"
name = "switch"
value = description?.endsWith(" 1") ? "on" : "off"
}
def result = createEvent(name: name, value: value)
log.debug "Parse returned ${result?.descriptionText}"
return result
}
def parseDescriptionAsMap(description) {
(description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbee.parseDescriptionAsMap(description)
}
}
// Commands to device
def on() {
'zcl on-off on'
}
def off() {
'zcl on-off off'
zigbee.off()
}
def meter() {
"st rattr 0x${device.deviceNetworkId} 1 0xB04 0x50B"
def on() {
zigbee.on()
}
def refresh() {
sendEvent(name: "heartbeat", value: "alive", displayed:false)
[
"st rattr 0x${device.deviceNetworkId} 1 0xB04 0x50B"
]
zigbee.onOffRefresh() + zigbee.refreshData("0x0B04", "0x050B")
}
def configure() {
def configCmds = [
"zdo bind 0x${device.deviceNetworkId} 1 1 6 {${device.zigbeeId}} {}", "delay 200",
"zdo bind 0x${device.deviceNetworkId} 1 1 0xB04 {${device.zigbeeId}} {}", "delay 200"
]
return configCmds + refresh() // send refresh cmds as part of config
zigbee.onOffConfig() + powerConfig() + refresh()
}
//power config for devices with min reporting interval as 1 seconds and reporting interval if no activity as 10min (600s)
//min change in value is 01
def powerConfig() {
[
"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
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
]
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
//TODO: Remove this after getKnownDescription can parse it automatically
def getPowerDescription(descMap) {
def powerValue = "undefined"
if (descMap.cluster == "0B04") {
if (descMap.attrId == "050b") {
if(descMap.value!="ffff")
powerValue = zigbee.convertHexToInt(descMap.value)
}
}
else if (descMap.clusterId == "0B04") {
if(descMap.command=="07"){
return [type: "update", value : "power (0B04) capability configured successfully"]
}
}
if (powerValue != "undefined"){
return [type: "power", value : powerValue]
}
else {
return [:]
}
}

View File

@@ -22,11 +22,11 @@ metadata {
capability "Water Sensor"
command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-S"
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"
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"
}
@@ -35,18 +35,27 @@ metadata {
}
preferences {
input description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
input "tempOffset", "number", title: "Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
section {
image(name: 'educationalcontent', multiple: true, images: [
"http://cdn.device-gse.smartthings.com/Moisture/Moisture1.png",
"http://cdn.device-gse.smartthings.com/Moisture/Moisture2.png",
"http://cdn.device-gse.smartthings.com/Moisture/Moisture3.png"
])
}
section {
input description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
input "tempOffset", "number", title: "Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
}
}
tiles(scale: 2) {
multiAttributeTile(name:"water", type: "generic", width: 6, height: 4){
tileAttribute ("device.water", key: "PRIMARY_CONTROL") {
attributeState "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
attributeState "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
attributeState "dry", label: "Dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
attributeState "wet", label: "Wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
}
}
valueTile("temperature", "device.temperature", inactiveLabel: false) {
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
state "temperature", label:'${currentValue}°',
backgroundColors:[
[value: 31, color: "#153591"],
@@ -64,7 +73,7 @@ metadata {
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main (["water", "temperature"])
details(["water", "temperature", "battery", "refresh"])
}
@@ -255,52 +264,53 @@ private Map getMoistureResult(value) {
]
}
def refresh()
{
def refresh() {
log.debug "Refreshing Temperature and Battery"
[
def refreshCmds = [
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20"
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
]
return refreshCmds + enrollResponse()
}
def configure() {
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting, IAS CIE, and Bindings."
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeId}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zcl global send-me-a-report 1 0x20 0x20 300 0600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 1 0x001 {${device.zigbeeId}} {}", "delay 1000",
"raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1000",
"zdo bind 0x${device.deviceNetworkId} 1 1 0x001 {${device.zigbeeId}} {}", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
}
def enrollResponse() {
log.debug "Sending enroll response"
[
"raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1"
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
[
//Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response
"raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
]
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
private hex(value) {
new BigInteger(Math.round(value).toString()).toString(16)
}

View File

@@ -35,8 +35,8 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"water", type: "generic", width: 6, height: 4){
tileAttribute ("device.water", key: "PRIMARY_CONTROL") {
attributeState "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
attributeState "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
attributeState "dry", label: "Dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
attributeState "wet", label: "Wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
}
}
standardTile("temperature", "device.temperature", width: 2, height: 2) {
@@ -47,6 +47,7 @@ metadata {
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
state "battery", label:'${currentValue}% battery', unit:""
}
main (["water", "temperature"])
details(["water", "temperature", "battery"])
}
@@ -128,6 +129,15 @@ def zwaveEvent(physicalgraph.zwave.commands.alarmv2.AlarmReport cmd)
map
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
def map = [:]
map.name = "water"
map.value = cmd.value ? "wet" : "dry"
map.descriptionText = "${device.displayName} is ${map.value}"
map
}
def zwaveEvent(physicalgraph.zwave.Command cmd)
{
log.debug "COMMAND CLASS: $cmd"

View File

@@ -37,8 +37,17 @@ metadata {
}
preferences {
input description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
input "tempOffset", "number", title: "Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
section {
image(name: 'educationalcontent', multiple: true, images: [
"http://cdn.device-gse.smartthings.com/Motion/Motion1.png",
"http://cdn.device-gse.smartthings.com/Motion/Motion2.png",
"http://cdn.device-gse.smartthings.com/Motion/Motion3.png"
])
}
section {
input description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
input "tempOffset", "number", title: "Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
}
}
tiles(scale: 2) {
@@ -137,10 +146,6 @@ private boolean shouldProcessMessage(cluster) {
return !ignoredMessage
}
private int getHumidity(value) {
return Math.round(Double.parseDouble(value))
}
private Map parseReportAttributeMessage(String description) {
Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
@@ -226,29 +231,30 @@ def getTemperature(value) {
private Map getBatteryResult(rawValue) {
log.debug 'Battery'
def linkText = getLinkText(device)
log.debug rawValue
def result = [
name: 'battery',
value: '--'
]
log.debug rawValue
def result = [
name: 'battery',
value: '--'
]
def volts = rawValue / 10
def descriptionText
if (rawValue == 0) {}
else {
if (volts > 3.5) {
result.descriptionText = "${linkText} battery has too much power (${volts} volts)."
if (rawValue == 0) {}
else {
if (volts > 3.5) {
result.descriptionText = "${linkText} battery has too much power (${volts} volts)."
}
else if (volts > 0){
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
}
else if (volts > 0){
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
result.descriptionText = "${linkText} battery was ${result.value}%"
}}
return result
}
@@ -280,53 +286,54 @@ private Map getMotionResult(value) {
]
}
def refresh()
{
def refresh() {
log.debug "refresh called"
[
def refreshCmds = [
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20"
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
]
return refreshCmds + enrollResponse()
}
def configure() {
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting, IAS CIE, and Bindings."
def configCmds = [
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x402 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500",
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x20 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 1 0x20 0x20 300 3600 {01}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500",
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x001 {${device.zigbeeId}} {}", "delay 200",
"zcl global write 0x500 0x10 0xf0 {${zigbeeId}}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}"
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x20 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 1 0x20 0x20 300 3600 {01}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x402 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 1 {${device.zigbeeId}} {}", "delay 200"
]
return configCmds + enrollResponse() + refresh() // send refresh cmds as part of config
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
return configCmds + refresh() // send refresh cmds as part of config
}
def enrollResponse() {
log.debug "Sending enroll response"
[
"raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}"
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
[
//Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response
"raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
]
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
private hex(value) {
new BigInteger(Math.round(value).toString()).toString(16)
}

View File

@@ -21,6 +21,7 @@ metadata {
capability "Battery"
capability "Temperature Measurement"
capability "Refresh"
capability "Sensor"
command "enrollResponse"
@@ -136,10 +137,6 @@ private boolean shouldProcessMessage(cluster) {
return !ignoredMessage
}
private int getHumidity(value) {
return Math.round(Double.parseDouble(value))
}
private Map parseReportAttributeMessage(String description) {
Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
@@ -225,22 +222,29 @@ def getTemperature(value) {
private Map getBatteryResult(rawValue) {
log.debug 'Battery'
def linkText = getLinkText(device)
def result = [
name: 'battery'
]
log.debug rawValue
def result = [
name: 'battery',
value: '--'
]
def volts = rawValue / 10
def descriptionText
if (volts > 3.5) {
result.descriptionText = "${linkText} battery has too much power (${volts} volts)."
}
if (rawValue == 0) {}
else {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
result.descriptionText = "${linkText} battery was ${result.value}%"
if (volts > 3.5) {
result.descriptionText = "${linkText} battery has too much power (${volts} volts)."
}
else if (volts > 0){
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
}
return result
@@ -273,50 +277,54 @@ private Map getMotionResult(value) {
]
}
def refresh()
{
def refresh() {
log.debug "refresh called"
[
def refreshCmds = [
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20"
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
]
return refreshCmds + enrollResponse()
}
def configure() {
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting, IAS CIE, and Bindings."
def configCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeId}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global send-me-a-report 1 0x20 0x20 300 3600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zdo bind 0x${device.deviceNetworkId} 1 1 0x402 {${device.zigbeeId}} {}", "delay 200",
"zdo bind 0x${device.deviceNetworkId} 1 1 0x001 {${device.zigbeeId}} {}", "delay 1500",
"raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x20 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 1 0x20 0x20 300 3600 {01}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x402 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 1 {${device.zigbeeId}} {}", "delay 200"
]
return configCmds + refresh() // send refresh cmds as part of config
}
def enrollResponse() {
log.debug "Sending enroll response"
[
"raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1"
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
[
//Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response
"raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
]
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
private hex(value) {
new BigInteger(Math.round(value).toString()).toString(16)
}

View File

@@ -30,7 +30,8 @@
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"
attribute "status", "string"
}
simulator {
@@ -51,18 +52,36 @@
status "x,y,z: 0,0,1000": "x: 0, y: 0, z: 1000"
}
preferences {
input description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
input "tempOffset", "number", title: "Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
section {
image(name: 'educationalcontent', multiple: true, images: [
"http://cdn.device-gse.smartthings.com/Multi/Multi1.png",
"http://cdn.device-gse.smartthings.com/Multi/Multi2.png",
"http://cdn.device-gse.smartthings.com/Multi/Multi3.png",
"http://cdn.device-gse.smartthings.com/Multi/Multi4.png"
])
}
section {
input description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
input "tempOffset", "number", title: "Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
}
section {
input("garageSensor", "enum", title: "Do you want to use this sensor on a garage door?", options: ["Yes", "No"], defaultValue: "No", required: false, displayDuringSetup: false)
}
}
tiles(scale: 2) {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){
tileAttribute ("device.status", 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 "garage-open", label:'Open', icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e"
attributeState "garage-closed", label:'Closed', icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821"
}
}
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")
}
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")
@@ -90,8 +109,9 @@
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main(["contact", "acceleration", "temperature"])
details(["contact", "acceleration", "temperature", "3axis", "battery", "refresh"])
main(["status", "acceleration", "temperature"])
details(["status", "acceleration", "temperature", "3axis", "battery", "refresh"])
}
}
@@ -158,10 +178,6 @@ private boolean shouldProcessMessage(cluster) {
return !ignoredMessage
}
private int getHumidity(value) {
return Math.round(Double.parseDouble(value))
}
private Map parseReportAttributeMessage(String description) {
Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
@@ -202,11 +218,15 @@ private Map parseIasMessage(String description) {
Map resultMap = [:]
switch(msgCode) {
case '0x0020': // Closed/No Motion/Dry
resultMap = getContactResult('closed')
if (garageSensor != "Yes"){
resultMap = getContactResult('closed')
}
break
case '0x0021': // Open/Motion/Wet
resultMap = getContactResult('open')
if (garageSensor != "Yes"){
resultMap = getContactResult('open')
}
break
case '0x0022': // Tamper Alarm
@@ -216,11 +236,15 @@ private Map parseIasMessage(String description) {
break
case '0x0024': // Supervision Report
resultMap = getContactResult('closed')
if (garageSensor != "Yes"){
resultMap = getContactResult('closed')
}
break
case '0x0025': // Restore Report
resultMap = getContactResult('open')
if (garageSensor != "Yes"){
resultMap = getContactResult('open')
}
break
case '0x0026': // Trouble/Failure
@@ -232,6 +256,29 @@ private Map parseIasMessage(String description) {
return resultMap
}
def updated() {
log.debug "updated called"
log.info "garage value : $garageSensor"
if (garageSensor == "Yes") {
def descriptionText = "Updating device to garage sensor"
if (device.latestValue("status") == "open") {
sendEvent(name: 'status', value: 'garage-open', descriptionText: descriptionText)
}
else if (device.latestValue("status") == "closed") {
sendEvent(name: 'status', value: 'garage-closed', descriptionText: descriptionText)
}
}
else {
def descriptionText = "Updating device to open/close sensor"
if (device.latestValue("status") == "garage-open") {
sendEvent(name: 'status', value: 'open', descriptionText: descriptionText)
}
else if (device.latestValue("status") == "garage-closed") {
sendEvent(name: 'status', value: 'closed', descriptionText: descriptionText)
}
}
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
@@ -291,11 +338,8 @@ def getTemperature(value) {
log.debug "Contact"
def linkText = getLinkText(device)
def descriptionText = "${linkText} was ${value == 'open' ? 'opened' : 'closed'}"
return [
name: 'contact',
value: value,
descriptionText: descriptionText
]
sendEvent(name: 'contact', value: value, descriptionText: descriptionText, displayed:false)
sendEvent(name: 'status', value: value, descriptionText: descriptionText)
}
private getAccelerationResult(numValue) {
@@ -313,52 +357,48 @@ def getTemperature(value) {
]
}
def refresh()
{
def refresh() {
log.debug "Refreshing Values "
[
def refreshCmds = [
/* sensitivity - default value (8) */
"zcl mfg-code 0x104E", "delay 200",
"zcl global write 0xFC02 0 0x20 {02}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 400",
"zcl mfg-code 0x104E", "delay 200",
"zcl global read 0xFC02 0x0000", "delay 200",
"send 0x${device.deviceNetworkId} 1 1","delay 400",
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200",
"zcl mfg-code 0x104E", "delay 200",
"zcl global read 0xFC02 0x0010", "delay 100",
"zcl global read 0xFC02 0x0010",
"send 0x${device.deviceNetworkId} 1 1","delay 400",
"zcl mfg-code 0x104E", "delay 200",
"zcl global read 0xFC02 0x0012", "delay 100",
"zcl global read 0xFC02 0x0012",
"send 0x${device.deviceNetworkId} 1 1","delay 400",
"zcl mfg-code 0x104E", "delay 200",
"zcl global read 0xFC02 0x0013", "delay 100",
"zcl global read 0xFC02 0x0013",
"send 0x${device.deviceNetworkId} 1 1","delay 400",
"zcl mfg-code 0x104E", "delay 200",
"zcl global read 0xFC02 0x0014", "delay 100",
"send 0x${device.deviceNetworkId} 1 1"
"zcl global read 0xFC02 0x0014",
"send 0x${device.deviceNetworkId} 1 1", "delay 400"
]
]
return refreshCmds + enrollResponse()
}
def configure() {
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting"
def configCmds = [
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 1 {${device.zigbeeId}} {}", "delay 200",
"zcl global write 0x500 0x10 0xf0 {${zigbeeId}}",
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x20 {${device.zigbeeId}} {}", "delay 200",
@@ -397,11 +437,14 @@ private getEndpointId() {
def enrollResponse() {
log.debug "Sending enroll response"
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
[
"raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1"
//Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response
"raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
]
}
@@ -430,13 +473,33 @@ private Map parseAxis(String description) {
def signedZ = unsignedZ > 32767 ? unsignedZ - 65536 : unsignedZ
xyzResults.z = signedZ
log.debug "Z Part: ${signedZ}"
if (garageSensor == "Yes")
garageEvent(signedZ)
}
}
getXyzResult(xyzResults, description)
}
def garageEvent(zValue) {
def absValue = zValue.abs()
def contactValue = null
def garageValue = null
if (absValue>900) {
contactValue = 'closed'
garageValue = 'garage-closed'
}
else if (absValue < 100) {
contactValue = 'open'
garageValue = 'garage-open'
}
if (contactValue != null){
def linkText = getLinkText(device)
def descriptionText = "${linkText} was ${contactValue == 'open' ? 'opened' : 'closed'}"
sendEvent(name: 'contact', value: contactValue, descriptionText: descriptionText, displayed:false)
sendEvent(name: 'status', value: garageValue, descriptionText: descriptionText)
}
}
private Map getXyzResult(results, description) {
def name = "threeAxis"

View File

@@ -284,52 +284,61 @@ def getTemperature(value) {
]
}
def refresh()
{
def refresh() {
log.debug "Refreshing Temperature and Battery "
[
def refreshCmds = [
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
//"st rattr 0x${device.deviceNetworkId} 1 0xFC02 2", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20"
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
]
return refreshCmds + enrollResponse()
}
def configure() {
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting, IAS CIE, and Bindings."
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeId}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zcl global send-me-a-report 1 0x20 0x20 600 3600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x20 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 1 0x20 0x20 600 3600 {01}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global send-me-a-report 0xFC02 2 0x18 300 3600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zdo bind 0x${device.deviceNetworkId} 1 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 1 0xFC02 {${device.zigbeeId}} {}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}"
"zcl global send-me-a-report 0xFC02 2 0x18 300 3600 {01}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
}
def enrollResponse() {
log.debug "Sending enroll response"
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
[
"raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1"
//Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response
"raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
]
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
private hex(value) {
new BigInteger(Math.round(value).toString()).toString(16)
}

View File

@@ -260,30 +260,29 @@ private Map getContactResult(value) {
]
}
def refresh()
{
def refresh() {
log.debug "Refreshing Temperature and Battery"
[
def refreshCmds = [
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20"
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
]
return refreshCmds + enrollResponse()
}
def configure() {
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting, IAS CIE, and Bindings."
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeId}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zcl global send-me-a-report 1 0x20 0x20 600 3600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global send-me-a-report 1 0x20 0x20 600 3600 {01}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
//"raw 0x500 {01 23 00 00 00}", "delay 200",
@@ -291,20 +290,28 @@ def configure() {
"zdo bind 0x${device.deviceNetworkId} 1 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}"
"zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
}
def enrollResponse() {
log.debug "Sending enroll response"
[
"raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1"
]
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
[
//Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response
"raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
]
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
private hex(value) {
new BigInteger(Math.round(value).toString()).toString(16)
}

View File

@@ -31,6 +31,15 @@ metadata {
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.png",
"http://cdn.device-gse.smartthings.com/Arrival/Arrival2.png"
])
}
}
tiles {
standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) {
state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#53a7c0"

View File

@@ -251,8 +251,7 @@ def refresh()
def configure() {
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting and Bindings."
log.debug "Configuring Reporting and Bindings."
def configCmds = [

View File

@@ -21,6 +21,7 @@ metadata {
capability "Illuminance Measurement"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Sensor"
attribute "localSunrise", "string"
attribute "localSunset", "string"

View File

@@ -270,12 +270,12 @@ def refresh()
def configure() {
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting, IAS CIE, and Bindings."
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
"delay 1000",
"zcl global write 0x500 0x10 0xf0 {${zigbeeId}}", "delay 200",
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global send-me-a-report 1 0x20 0x20 600 3600 {01}", "delay 200",

View File

@@ -134,8 +134,7 @@ def setLevel(value) {
def configure() {
String zigbeeId = swapEndianHex(device.hub.zigbeeId)
log.debug "Confuguring Reporting and Bindings."
log.debug "Configuring Reporting and Bindings."
def configCmds = [
//Switch Reporting

View File

@@ -30,7 +30,7 @@ definition(
name: "Carpool Notifier",
namespace: "smartthings",
author: "SmartThings",
description: "This SmartApp is designed to send notifications to your carpooling buddies when you arrive to pick them up. What separates this SmartApp from other notification SmartApps is that it will only send a notification if your carpool buddy is not with you. If the person you are picking up is present, and has been for 5 minutes or more, they will get a notification when you become present.",
description: "Send notifications to your carpooling buddies when you arrive to pick them up. If the person you are picking up is home, and has been for 5 minutes or more, they will get a notification when you arrive.",
category: "Green Living",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Family/App-IMadeIt.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Family/App-IMadeIt@2x.png"

View File

@@ -27,7 +27,7 @@ definition(
name: "Gentle Wake Up",
namespace: "smartthings",
author: "SmartThings",
description: "Gentle Wake Up dims your lights slowly, allowing you to wake up more naturally. Once your lights have finished dimming, optionally turn on more things or send yourself a text for a more gentle nudge into the waking world (you may want to set your normal alarm as a backup plan).",
description: "Dim your lights up slowly, allowing you to wake up more naturally.",
category: "Health & Wellness",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/HealthAndWellness/App-SleepyTime.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/HealthAndWellness/App-SleepyTime@2x.png"

View File

@@ -23,7 +23,7 @@ definition(
name: "Notify Me When",
namespace: "smartthings",
author: "SmartThings",
description: "Get a push notification or text message when any of a variety of SmartThings is activated. Supports button push, motion, contact, acceleration, moisture and presence sensors as well as switches.",
description: "Receive notifications when anything happens in your home.",
category: "Convenience",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/window_contact.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/window_contact@2x.png"

View File

@@ -622,7 +622,7 @@ def greyedOutTime(starting, ending){
}
result
}
private anyoneIsHome() {
def result = false
@@ -634,10 +634,10 @@ private anyoneIsHome() {
return result
}
page(name: "timeIntervalInput", title: "Only during a certain time", refreshAfterSelection:true) {
section {
input "starting", "time", title: "Starting (both are required)", required: false
input "ending", "time", title: "Ending (both are required)", required: false
}
}
}