Compare commits
1 Commits
user186_7
...
MSA-2426-1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f5f1056ff |
@@ -28,12 +28,7 @@ metadata {
|
||||
capability "Health Check"
|
||||
|
||||
fingerprint manufacturer: "015D", prod: "0221", model: "251C", deviceJoinName: "Show Home 2-Channel Smart Plug"
|
||||
fingerprint manufacturer: "0312", prod: "0221", model: "251C", deviceJoinName: "Inovelli 2-Channel Smart Plug"
|
||||
fingerprint manufacturer: "0312", prod: "B221", model: "251C", deviceJoinName: "Inovelli 2-Channel Smart Plug"
|
||||
fingerprint manufacturer: "0312", prod: "0221", model: "611C", deviceJoinName: "Inovelli 2-Channel Outdoor Smart Plug"
|
||||
fingerprint manufacturer: "015D", prod: "0221", model: "611C", deviceJoinName: "Inovelli 2-Channel Outdoor Smart Plug"
|
||||
fingerprint manufacturer: "015D", prod: "6100", model: "6100", deviceJoinName: "Inovelli 2-Channel Outdoor Smart Plug"
|
||||
fingerprint manufacturer: "015D", prod: "2500", model: "2500", deviceJoinName: "Inovelli 2-Channel Smart Plug w/Scene"
|
||||
}
|
||||
simulator {}
|
||||
preferences {}
|
||||
|
||||
@@ -24,10 +24,7 @@ metadata {
|
||||
capability "Temperature Measurement"
|
||||
capability "Health Check"
|
||||
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x20, 0x86, 0x72, 0x5A, 0x59, 0x85, 0x73, 0x84, 0x80, 0x71, 0x56, 0x70, 0x31, 0x8E, 0x22, 0x30, 0x9C, 0x98, 0x7A", outClusters: ""
|
||||
fingerprint mfr:"010F", prod:"0801", model:"2001"
|
||||
fingerprint mfr:"010F", prod:"0801", model:"1001"
|
||||
|
||||
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x20, 0x86, 0x72, 0x5A, 0x59, 0x85, 0x73, 0x84, 0x80, 0x71, 0x56, 0x70, 0x31, 0x8E, 0x22, 0x30, 0x9C, 0x98, 0x7A", outClusters: ""
|
||||
}
|
||||
|
||||
simulator {
|
||||
|
||||
173
devicetypes/smartthings-users/nest.src/nest.groovy
Normal file
173
devicetypes/smartthings-users/nest.src/nest.groovy
Normal file
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* Nest
|
||||
*
|
||||
* Copyright 2017 dianoga7@3dgo.net
|
||||
*
|
||||
* 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: "Nest", namespace: "smartthings-users", author: "dianoga7@3dgo.net") {
|
||||
capability "Polling"
|
||||
capability "Presence Sensor"
|
||||
capability "Relative Humidity Measurement"
|
||||
capability "Sensor"
|
||||
capability "Temperature Measurement"
|
||||
capability "Thermostat"
|
||||
|
||||
attribute "temperatureUnit", "string"
|
||||
|
||||
command "away"
|
||||
command "present"
|
||||
command "setPresence"
|
||||
command "heatingSetpointUp"
|
||||
command "heatingSetPointDown"
|
||||
command "setFarenheit"
|
||||
command "setCelsius"
|
||||
}
|
||||
|
||||
|
||||
simulator {
|
||||
// TODO: define status and reply messages here
|
||||
}
|
||||
|
||||
tiles {
|
||||
// TODO: define your main and details tiles here
|
||||
}
|
||||
}
|
||||
|
||||
// parse events into attributes
|
||||
def parse(String description) {
|
||||
log.debug "Parsing '${description}'"
|
||||
// TODO: handle 'presence' attribute
|
||||
// TODO: handle 'humidity' attribute
|
||||
// TODO: handle 'temperature' attribute
|
||||
// TODO: handle 'temperature' attribute
|
||||
// TODO: handle 'heatingSetpoint' attribute
|
||||
// TODO: handle 'coolingSetpoint' attribute
|
||||
// TODO: handle 'thermostatSetpoint' attribute
|
||||
// TODO: handle 'thermostatMode' attribute
|
||||
// TODO: handle 'thermostatFanMode' attribute
|
||||
// TODO: handle 'thermostatOperatingState' attribute
|
||||
// TODO: handle 'schedule' attribute
|
||||
// TODO: handle 'coolingSetpointRange' attribute
|
||||
// TODO: handle 'heatingSetpointRange' attribute
|
||||
// TODO: handle 'supportedThermostatFanModes' attribute
|
||||
// TODO: handle 'supportedThermostatModes' attribute
|
||||
// TODO: handle 'thermostatSetpointRange' attribute
|
||||
// TODO: handle 'temperatureUnit' attribute
|
||||
|
||||
}
|
||||
|
||||
// handle commands
|
||||
def poll() {
|
||||
log.debug "Executing 'poll'"
|
||||
// TODO: handle 'poll' command
|
||||
}
|
||||
|
||||
def setHeatingSetpoint() {
|
||||
log.debug "Executing 'setHeatingSetpoint'"
|
||||
// TODO: handle 'setHeatingSetpoint' command
|
||||
}
|
||||
|
||||
def setCoolingSetpoint() {
|
||||
log.debug "Executing 'setCoolingSetpoint'"
|
||||
// TODO: handle 'setCoolingSetpoint' command
|
||||
}
|
||||
|
||||
def off() {
|
||||
log.debug "Executing 'off'"
|
||||
// TODO: handle 'off' command
|
||||
}
|
||||
|
||||
def heat() {
|
||||
log.debug "Executing 'heat'"
|
||||
// TODO: handle 'heat' command
|
||||
}
|
||||
|
||||
def emergencyHeat() {
|
||||
log.debug "Executing 'emergencyHeat'"
|
||||
// TODO: handle 'emergencyHeat' command
|
||||
}
|
||||
|
||||
def cool() {
|
||||
log.debug "Executing 'cool'"
|
||||
// TODO: handle 'cool' command
|
||||
}
|
||||
|
||||
def setThermostatMode() {
|
||||
log.debug "Executing 'setThermostatMode'"
|
||||
// TODO: handle 'setThermostatMode' command
|
||||
}
|
||||
|
||||
def fanOn() {
|
||||
log.debug "Executing 'fanOn'"
|
||||
// TODO: handle 'fanOn' command
|
||||
}
|
||||
|
||||
def fanAuto() {
|
||||
log.debug "Executing 'fanAuto'"
|
||||
// TODO: handle 'fanAuto' command
|
||||
}
|
||||
|
||||
def fanCirculate() {
|
||||
log.debug "Executing 'fanCirculate'"
|
||||
// TODO: handle 'fanCirculate' command
|
||||
}
|
||||
|
||||
def setThermostatFanMode() {
|
||||
log.debug "Executing 'setThermostatFanMode'"
|
||||
// TODO: handle 'setThermostatFanMode' command
|
||||
}
|
||||
|
||||
def auto() {
|
||||
log.debug "Executing 'auto'"
|
||||
// TODO: handle 'auto' command
|
||||
}
|
||||
|
||||
def setSchedule() {
|
||||
log.debug "Executing 'setSchedule'"
|
||||
// TODO: handle 'setSchedule' command
|
||||
}
|
||||
|
||||
def away() {
|
||||
log.debug "Executing 'away'"
|
||||
// TODO: handle 'away' command
|
||||
}
|
||||
|
||||
def present() {
|
||||
log.debug "Executing 'present'"
|
||||
// TODO: handle 'present' command
|
||||
}
|
||||
|
||||
def setPresence() {
|
||||
log.debug "Executing 'setPresence'"
|
||||
// TODO: handle 'setPresence' command
|
||||
}
|
||||
|
||||
def heatingSetpointUp() {
|
||||
log.debug "Executing 'heatingSetpointUp'"
|
||||
// TODO: handle 'heatingSetpointUp' command
|
||||
}
|
||||
|
||||
def heatingSetPointDown() {
|
||||
log.debug "Executing 'heatingSetPointDown'"
|
||||
// TODO: handle 'heatingSetPointDown' command
|
||||
}
|
||||
|
||||
def setFarenheit() {
|
||||
log.debug "Executing 'setFarenheit'"
|
||||
// TODO: handle 'setFarenheit' command
|
||||
}
|
||||
|
||||
def setCelsius() {
|
||||
log.debug "Executing 'setCelsius'"
|
||||
// TODO: handle 'setCelsius' command
|
||||
}
|
||||
@@ -18,6 +18,7 @@ metadata {
|
||||
capability "Actuator"
|
||||
capability "Switch"
|
||||
capability "Configuration"
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
|
||||
@@ -166,6 +167,10 @@ def setLevel(value, duration) {
|
||||
zwave.switchMultilevelV2.switchMultilevelSet(value: value, dimmingDuration: dimmingDuration).format()
|
||||
}
|
||||
|
||||
def poll() {
|
||||
zwave.switchMultilevelV1.switchMultilevelGet().format()
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
zwave.switchMultilevelV1.switchMultilevelGet().format()
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "Aeon Multisensor 6", namespace: "smartthings", author: "SmartThings", runLocally: true, minHubCoreVersion: '000.020.00008', executeCommandsLocally: true) {
|
||||
definition (name: "Aeon Multisensor 6", namespace: "smartthings", author: "SmartThings") {
|
||||
capability "Motion Sensor"
|
||||
capability "Temperature Measurement"
|
||||
capability "Relative Humidity Measurement"
|
||||
|
||||
@@ -31,6 +31,7 @@ metadata {
|
||||
status "no motion (basic)" : "command: 2001, payload: 00"
|
||||
status "motion (binary)" : "command: 3003, payload: FF"
|
||||
status "no motion (binary)" : "command: 3003, payload: 00"
|
||||
status "wakeup" : "command: 8407, payload: "
|
||||
|
||||
for (int i = 0; i <= 100; i += 20) {
|
||||
status "temperature ${i}F": new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
|
||||
@@ -85,12 +86,20 @@ metadata {
|
||||
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||
state "battery", label:'${currentValue}% battery', unit:""
|
||||
}
|
||||
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
|
||||
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
|
||||
}
|
||||
|
||||
main(["motion", "temperature", "humidity", "illuminance"])
|
||||
details(["motion", "temperature", "humidity", "illuminance", "battery", "configure"])
|
||||
details(["motion", "temperature", "humidity", "illuminance", "battery"])
|
||||
}
|
||||
|
||||
preferences {
|
||||
input description: "Please consult the operating manual for advanced setting options. You can skip this configuration to use default settings",
|
||||
title: "Advanced Configuration", displayDuringSetup: true, type: "paragraph", element: "paragraph"
|
||||
// these are cribbed from the newer aeon-multisensor-6
|
||||
input "motionDelayTime", "enum", title: "Motion Sensor Delay Time",
|
||||
options: ["20 seconds", "40 seconds", "1 minute", "2 minutes", "3 minutes", "4 minutes"], defaultValue: "${motionDelayTime}", displayDuringSetup: true
|
||||
|
||||
input "reportInterval", "enum", title: "Sensors Report Interval",
|
||||
options: ["5 minutes", "8 minutes", "15 minutes", "30 minutes", "1 hour", "6 hours", "12 hours", "18 hours", "24 hours"], defaultValue: "${reportInterval}", displayDuringSetup: true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,25 +111,42 @@ def installed(){
|
||||
def updated(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
|
||||
|
||||
log.debug "Updated with settings: ${settings}"
|
||||
|
||||
//preferences changed, so we should reconfigure on next wakeup
|
||||
setConfigured("false")
|
||||
}
|
||||
|
||||
// Parse incoming device messages to generate events
|
||||
def parse(String description)
|
||||
{
|
||||
def result = []
|
||||
def cmd = zwave.parse(description, [0x31: 2, 0x30: 1, 0x84: 1])
|
||||
if (cmd) {
|
||||
if( cmd.CMD == "8407" ) { result << new physicalgraph.device.HubAction(zwave.wakeUpV1.wakeUpNoMoreInformation().format()) }
|
||||
result << createEvent(zwaveEvent(cmd))
|
||||
def results = []
|
||||
log.debug("parsing")
|
||||
if (description.startsWith("Err")) {
|
||||
results = createEvent(descriptionText:description, displayed:true)
|
||||
} else {
|
||||
def cmd = zwave.parse(description, [0x31: 2, 0x30: 1, 0x84: 1])
|
||||
if(cmd) results = zwaveEvent(cmd)
|
||||
if(!results) results = [ descriptionText: cmd, displayed: false ]
|
||||
}
|
||||
log.debug "Parse returned ${result}"
|
||||
return result
|
||||
log.debug("Parsed '$description' to $results")
|
||||
return results
|
||||
}
|
||||
|
||||
// Event Generation
|
||||
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
|
||||
{
|
||||
[descriptionText: "${device.displayName} woke up", isStateChange: false]
|
||||
def results = []
|
||||
def cmds = []
|
||||
results << createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)
|
||||
// If we haven't configured yet, then do so now
|
||||
if (!isConfigured()) {
|
||||
cmds = configure()
|
||||
}
|
||||
cmds += zwave.wakeUpV1.wakeUpNoMoreInformation()
|
||||
results << response(cmds)
|
||||
return results
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv2.SensorMultilevelReport cmd)
|
||||
@@ -147,7 +173,7 @@ def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv2.SensorMultilevelR
|
||||
map.name = "humidity"
|
||||
break;
|
||||
}
|
||||
map
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
|
||||
@@ -156,20 +182,19 @@ def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
|
||||
map.value = cmd.batteryLevel > 0 ? cmd.batteryLevel.toString() : 1
|
||||
map.unit = "%"
|
||||
map.displayed = false
|
||||
map
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cmd) {
|
||||
def map = [:]
|
||||
def map = [name : "motion"]
|
||||
map.value = cmd.sensorValue ? "active" : "inactive"
|
||||
map.name = "motion"
|
||||
if (map.value == "active") {
|
||||
map.descriptionText = "$device.displayName detected motion"
|
||||
}
|
||||
else {
|
||||
map.descriptionText = "$device.displayName motion has stopped"
|
||||
}
|
||||
map
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
|
||||
@@ -182,12 +207,12 @@ def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
|
||||
else {
|
||||
map.descriptionText = "$device.displayName motion has stopped"
|
||||
}
|
||||
map
|
||||
createEvent(map)
|
||||
}
|
||||
|
||||
def zwaveEvent(physicalgraph.zwave.Command cmd) {
|
||||
log.debug "Catchall reached for cmd: ${cmd.toString()}}"
|
||||
[:]
|
||||
createEvent([:])
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,17 +223,57 @@ def ping() {
|
||||
}
|
||||
|
||||
def configure() {
|
||||
def defaultTimeout = motionDelayTime ? timeOptionValueMap[motionDelayTime] : 20
|
||||
def defaultPeriod = reportInterval ? timeOptionValueMap[reportInterval]: 5*60
|
||||
|
||||
setConfigured("true")
|
||||
|
||||
delayBetween([
|
||||
// send remove association to avoid double reports
|
||||
zwave.associationV1.associationRemove(groupingIdentifier: 1, nodeId: zwaveHubNodeId).format(),
|
||||
|
||||
// send binary sensor report instead of basic set for motion
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: 2).format(),
|
||||
|
||||
// send no-motion report 15 seconds after motion stops
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 3, size: 2, scaledConfigurationValue: 15).format(),
|
||||
// send no-motion report after a user-specified period (default 20 seconds) after motion stops
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 3, size: 2, scaledConfigurationValue: defaultTimeout).format(),
|
||||
|
||||
// send all data (temperature, humidity, illuminance & battery) periodically
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 225).format(),
|
||||
// send all data (temperature, humidity, & illuminance) periodically
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 224).format(),
|
||||
|
||||
// set data reporting period to 5 minutes
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 300).format()
|
||||
])
|
||||
// set data reporting period for above to a user-specified period (default 5 minutes)
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: defaultPeriod).format(),
|
||||
|
||||
// send a battery report less frequently
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 1).format(),
|
||||
|
||||
// like once every 12 hours
|
||||
zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 12*60*60).format()
|
||||
]) + ["delay 5000"]
|
||||
}
|
||||
|
||||
private def getTimeOptionValueMap() { [
|
||||
"20 seconds" : 20,
|
||||
"40 seconds" : 40,
|
||||
"1 minute" : 60,
|
||||
"2 minutes" : 2*60,
|
||||
"3 minutes" : 3*60,
|
||||
"4 minutes" : 4*60,
|
||||
"5 minutes" : 5*60,
|
||||
"8 minutes" : 8*60,
|
||||
"15 minutes" : 15*60,
|
||||
"30 minutes" : 30*60,
|
||||
"1 hours" : 1*60*60,
|
||||
"6 hours" : 6*60*60,
|
||||
"12 hours" : 12*60*60,
|
||||
"18 hours" : 6*60*60,
|
||||
"24 hours" : 24*60*60,
|
||||
]}
|
||||
|
||||
private setConfigured(configure) {
|
||||
updateDataValue("configured", configure)
|
||||
}
|
||||
|
||||
private isConfigured() {
|
||||
getDataValue("configured") == "true"
|
||||
}
|
||||
@@ -17,6 +17,7 @@ metadata {
|
||||
capability "Actuator"
|
||||
capability "Switch"
|
||||
capability "Configuration"
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
|
||||
@@ -121,6 +122,13 @@ def off() {
|
||||
])
|
||||
}
|
||||
|
||||
def poll() {
|
||||
delayBetween([
|
||||
zwave.switchBinaryV1.switchBinaryGet().format(),
|
||||
zwave.meterV2.meterGet().format()
|
||||
])
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
zwave.switchBinaryV1.switchBinaryGet().format()
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ metadata {
|
||||
capability "Actuator"
|
||||
capability "Indicator"
|
||||
capability "Switch"
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
capability "Health Check"
|
||||
@@ -25,6 +26,7 @@ metadata {
|
||||
fingerprint mfr:"0063", prod:"4457", deviceJoinName: "GE In-Wall Smart Dimmer"
|
||||
fingerprint mfr:"0063", prod:"4944", deviceJoinName: "GE In-Wall Smart Dimmer"
|
||||
fingerprint mfr:"0063", prod:"5044", deviceJoinName: "GE Plug-In Smart Dimmer"
|
||||
fingerprint mfr:"0063", prod:"4944", model:"3034", deviceJoinName: "GE In-Wall Smart Fan Control"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -240,6 +242,10 @@ def setLevel(value, duration) {
|
||||
zwave.switchMultilevelV1.switchMultilevelGet().format()], getStatusDelay)
|
||||
}
|
||||
|
||||
def poll() {
|
||||
zwave.switchMultilevelV1.switchMultilevelGet().format()
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
|
||||
@@ -124,10 +124,6 @@ metadata {
|
||||
input "holdType", "enum", title: "Hold Type",
|
||||
description: "When changing temperature, use Temporary (Until next transition) or Permanent hold (default)",
|
||||
required: false, options:["Temporary", "Permanent"]
|
||||
input "deadbandSetting", "number", title: "Minimum temperature difference between the desired Heat and Cool " +
|
||||
"temperatures in Auto mode:\nNote! This must be the same as configured on the thermostat",
|
||||
description: "temperature difference °F", defaultValue: 5,
|
||||
required: false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -176,7 +172,7 @@ def generateEvent(Map results) {
|
||||
if (name=="temperature" || name=="heatingSetpoint" || name=="coolingSetpoint" ) {
|
||||
sendValue = getTempInLocalScale(value, "F") // API return temperature values in F
|
||||
event << [value: sendValue, unit: locationScale]
|
||||
} else if (name=="maxCoolingSetpoint" || name=="minCoolingSetpoint" || name=="maxHeatingSetpoint" || name=="minHeatingSetpoint") {
|
||||
} else if (name=="maxCoolingSetpoint" || name=="minCoolingSetpoint" || name=="maxHeatingSetpoint" || name=="minHeatingSetpoint") {
|
||||
// Old attributes, keeping for backward compatibility
|
||||
sendValue = getTempInLocalScale(value, "F") // API return temperature values in F
|
||||
event << [value: sendValue, unit: locationScale, displayed: false]
|
||||
@@ -469,7 +465,7 @@ def enforceSetpointLimits(setpoint, data, raise = null) {
|
||||
def maxSetpoint = (setpoint == "heatingSetpoint") ? device.getDataValue("maxHeatingSetpointFahrenheit") : device.getDataValue("maxCoolingSetpointFahrenheit")
|
||||
minSetpoint = minSetpoint ? Double.parseDouble(minSetpoint) : ((setpoint == "heatingSetpoint") ? 45 : 65) // default 45 heat, 65 cool
|
||||
maxSetpoint = maxSetpoint ? Double.parseDouble(maxSetpoint) : ((setpoint == "heatingSetpoint") ? 79 : 92) // default 79 heat, 92 cool
|
||||
def deadband = deadbandSetting ? deadbandSetting : 5 // °F
|
||||
def deadband = 5 // °F
|
||||
def delta = (locationScale == "F") ? 1 : 0.5
|
||||
def targetValue = getTempInDeviceScale(data.targetValue, locationScale)
|
||||
def heatingSetpoint = getTempInDeviceScale(data.heatingSetpoint, locationScale)
|
||||
@@ -479,8 +475,8 @@ def enforceSetpointLimits(setpoint, data, raise = null) {
|
||||
targetValue = maxSetpoint
|
||||
} else if (targetValue < minSetpoint) {
|
||||
targetValue = minSetpoint
|
||||
} else if ((raise != null) && ((setpoint == "heatingSetpoint" && targetValue == heatingSetpoint) ||
|
||||
(setpoint == "coolingSetpoint" && targetValue == coolingSetpoint))) {
|
||||
} else if ((setpoint == "heatingSetpoint" && targetValue == heatingSetpoint) ||
|
||||
(setpoint == "coolingSetpoint" && targetValue == coolingSetpoint)){
|
||||
// Ensure targetValue differes from old. When location scale differs from device,
|
||||
// converting between C -> F -> C may otherwise result in no change.
|
||||
targetValue += raise ? delta : - delta
|
||||
|
||||
@@ -46,16 +46,15 @@
|
||||
capability "Illuminance Measurement"
|
||||
capability "Sensor"
|
||||
capability "Battery"
|
||||
capability "Health Check"
|
||||
capability "Health Check"
|
||||
|
||||
command "resetParams2StDefaults"
|
||||
command "listCurrentParams"
|
||||
command "updateZwaveParam"
|
||||
command "test"
|
||||
command "configure"
|
||||
command "resetParams2StDefaults"
|
||||
command "listCurrentParams"
|
||||
command "updateZwaveParam"
|
||||
command "test"
|
||||
command "configure"
|
||||
|
||||
fingerprint mfr:"010F", prod:"0800", model:"2001"
|
||||
fingerprint mfr:"010F", prod:"0800", model:"1001"
|
||||
fingerprint deviceId: "0x2001", inClusters: "0x30,0x84,0x85,0x80,0x8F,0x56,0x72,0x86,0x70,0x8E,0x31,0x9C,0xEF,0x30,0x31,0x9C"
|
||||
}
|
||||
|
||||
simulator {
|
||||
|
||||
@@ -171,9 +171,8 @@ private Map getBatteryResult(rawValue) {
|
||||
def pct = batteryMap[volts]
|
||||
result.value = pct
|
||||
} else {
|
||||
def useOldBatt = shouldUseOldBatteryReporting()
|
||||
def minVolts = useOldBatt ? 2.1 : 2.4
|
||||
def maxVolts = useOldBatt ? 3.0 : 2.7
|
||||
def minVolts = 2.4
|
||||
def maxVolts = 2.7
|
||||
// Get the current battery percentage as a multiplier 0 - 1
|
||||
def curValVolts = Integer.parseInt(device.currentState("battery")?.value ?: "100") / 100.0
|
||||
// Find the corresponding voltage from our range
|
||||
@@ -184,16 +183,15 @@ private Map getBatteryResult(rawValue) {
|
||||
// OR we have received the same reading twice in a row
|
||||
// OR we don't currently have a battery reading
|
||||
// OR the value we just received is at least 2 steps off from the last reported value
|
||||
// OR the device's firmware is older than 1.15.7
|
||||
if(useOldBatt || state?.lastVolts == null || state?.lastVolts == volts || device.currentState("battery")?.value == null || Math.abs(curValVolts - volts) > 0.1) {
|
||||
if(state?.lastVolts == null || state?.lastVolts == volts || device.currentState("battery")?.value == null || Math.abs(curValVolts - volts) > 0.1) {
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.value = Math.min(100, roundedPct)
|
||||
} else {
|
||||
// Don't update as we want to smooth the battery values, but do report the last battery state for record keeping purposes
|
||||
result.value = device.currentState("battery").value
|
||||
// Don't update as we want to smooth the battery values
|
||||
result = null
|
||||
}
|
||||
state.lastVolts = volts
|
||||
}
|
||||
@@ -239,22 +237,3 @@ def configure() {
|
||||
// battery minReport 30 seconds, maxReportTime 6 hrs by default
|
||||
return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config
|
||||
}
|
||||
|
||||
private shouldUseOldBatteryReporting() {
|
||||
def isFwVersionLess = true // By default use the old battery reporting
|
||||
def deviceFwVer = "${device.getFirmwareVersion()}"
|
||||
def deviceVersion = deviceFwVer.tokenize('.') // We expect the format ###.###.### where ### is some integer
|
||||
|
||||
if (deviceVersion.size() == 3) {
|
||||
def targetVersion = [1, 15, 7] // Centralite Firmware 1.15.7 contains battery smoothing fixes, so versions before that should NOT be smoothed
|
||||
def devMajor = deviceVersion[0] as int
|
||||
def devMinor = deviceVersion[1] as int
|
||||
def devBuild = deviceVersion[2] as int
|
||||
|
||||
isFwVersionLess = ((devMajor < targetVersion[0]) ||
|
||||
(devMajor == targetVersion[0] && devMinor < targetVersion[1]) ||
|
||||
(devMajor == targetVersion[0] && devMinor == targetVersion[1] && devBuild < targetVersion[2]))
|
||||
}
|
||||
|
||||
return isFwVersionLess // If f/w version is less than 1.15.7 then do NOT smooth battery reports and use the old reporting
|
||||
}
|
||||
|
||||
@@ -273,10 +273,8 @@ private Map getBatteryResult(rawValue) {
|
||||
def pct = batteryMap[volts]
|
||||
result.value = pct
|
||||
} else {
|
||||
def useOldBatt = shouldUseOldBatteryReporting()
|
||||
def minVolts = 2.1
|
||||
def maxVolts = useOldBatt ? 3.0 : 2.7
|
||||
|
||||
def maxVolts = 2.7
|
||||
// Get the current battery percentage as a multiplier 0 - 1
|
||||
def curValVolts = Integer.parseInt(device.currentState("battery")?.value ?: "100") / 100.0
|
||||
// Find the corresponding voltage from our range
|
||||
@@ -287,16 +285,15 @@ private Map getBatteryResult(rawValue) {
|
||||
// OR we have received the same reading twice in a row
|
||||
// OR we don't currently have a battery reading
|
||||
// OR the value we just received is at least 2 steps off from the last reported value
|
||||
// OR the device's firmware is older than 1.15.7
|
||||
if(useOldBatt || state?.lastVolts == null || state?.lastVolts == volts || device.currentState("battery")?.value == null || Math.abs(curValVolts - volts) > 0.1) {
|
||||
if(state?.lastVolts == null || state?.lastVolts == volts || device.currentState("battery")?.value == null || Math.abs(curValVolts - volts) > 0.1) {
|
||||
def pct = (volts - minVolts) / (maxVolts - minVolts)
|
||||
def roundedPct = Math.round(pct * 100)
|
||||
if (roundedPct <= 0)
|
||||
roundedPct = 1
|
||||
result.value = Math.min(100, roundedPct)
|
||||
} else {
|
||||
// Don't update as we want to smooth the battery values, but do report the last battery state for record keeping purposes
|
||||
result.value = device.currentState("battery").value
|
||||
// Don't update as we want to smooth the battery values
|
||||
result = null
|
||||
}
|
||||
state.lastVolts = volts
|
||||
}
|
||||
@@ -416,25 +413,6 @@ private getManufacturerCode() {
|
||||
}
|
||||
}
|
||||
|
||||
private shouldUseOldBatteryReporting() {
|
||||
def isFwVersionLess = true // By default use the old battery reporting
|
||||
def deviceFwVer = "${device.getFirmwareVersion()}"
|
||||
def deviceVersion = deviceFwVer.tokenize('.') // We expect the format ###.###.### where ### is some integer
|
||||
|
||||
if (deviceVersion.size() == 3) {
|
||||
def targetVersion = [1, 15, 7] // Centralite Firmware 1.15.7 contains battery smoothing fixes, so versions before that should NOT be smoothed
|
||||
def devMajor = deviceVersion[0] as int
|
||||
def devMinor = deviceVersion[1] as int
|
||||
def devBuild = deviceVersion[2] as int
|
||||
|
||||
isFwVersionLess = ((devMajor < targetVersion[0]) ||
|
||||
(devMajor == targetVersion[0] && devMinor < targetVersion[1]) ||
|
||||
(devMajor == targetVersion[0] && devMinor == targetVersion[1] && devBuild < targetVersion[2]))
|
||||
}
|
||||
|
||||
return isFwVersionLess // If f/w version is less than 1.15.7 then do NOT smooth battery reports and use the old reporting
|
||||
}
|
||||
|
||||
private hexToInt(value) {
|
||||
new BigInteger(value, 16)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "Simulated Dimmer Switch", namespace: "smartthings/testing", author: "SmartThings", runLocally: true, minHubCoreVersion: '000.020.00008', executeCommandsLocally: true) {
|
||||
definition (name: "Simulated Dimmer Switch", namespace: "smartthings/testing", author: "SmartThings") {
|
||||
capability "Actuator"
|
||||
capability "Sensor"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
metadata {
|
||||
|
||||
definition (name: "Simulated Switch", namespace: "smartthings/testing", author: "bob", runLocally: true, minHubCoreVersion: '000.020.00008', executeCommandsLocally: true) {
|
||||
definition (name: "Simulated Switch", namespace: "smartthings/testing", author: "bob") {
|
||||
capability "Switch"
|
||||
capability "Relay Switch"
|
||||
capability "Sensor"
|
||||
|
||||
@@ -30,13 +30,8 @@ metadata {
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05", outClusters: "0019", manufacturer: "OSRAM SYLVANIA", model: "iQBR30", deviceJoinName: "Sylvania Ultra iQ"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY PAR38 ON/OFF/DIM", deviceJoinName: "SYLVANIA Smart PAR38 Soft White"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY BR ON/OFF/DIM", deviceJoinName: "SYLVANIA Smart BR30 Soft White"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-G13", deviceJoinName: "Sengled Element Classic"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-G14", deviceJoinName: "Sengled Element Classic"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-G23", deviceJoinName: "Sengled Element Classic"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-G33", deviceJoinName: "Sengled Element Classic"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E12-N13", deviceJoinName: "Sengled Element Classic"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E12-N14", deviceJoinName: "Sengled Element Classic"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E12-N15", deviceJoinName: "Sengled Element Classic"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-G13", deviceJoinName: "Sengled Element Classic A19"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E12-N14", deviceJoinName: "Sengled Element Classic BR30"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL6HD", deviceJoinName: "Leviton Dimmer Switch"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL3HL", deviceJoinName: "Leviton Lumina RF Plug-In Dimmer"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL1KD", deviceJoinName: "Leviton Lumina RF Dimmer Switch"
|
||||
|
||||
@@ -32,7 +32,7 @@ metadata {
|
||||
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0009,000A,0101,0020", outClusters: "000A,0019", manufacturer: "Yale", model: "YRD210 PB DB", deviceJoinName: "Yale Push Button Deadbolt Lock"
|
||||
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0009,000A,0101,0020", outClusters: "000A,0019", manufacturer: "Yale", model: "YRD220/240 TSDB", deviceJoinName: "Yale Touch Screen Deadbolt Lock"
|
||||
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0009,000A,0101,0020", outClusters: "000A,0019", manufacturer: "Yale", model: "YRL210 PB LL", deviceJoinName: "Yale Push Button Lever Lock"
|
||||
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0009,000A,0101,0020", outClusters: "000A,0019", manufacturer: "Yale", model: "YRD226/246 TSDB", deviceJoinName: "Yale Assure Lock"
|
||||
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0009,000A,0101,0020", outClusters: "000A,0019", manufacturer: "Yale", model: "YRD226/246 TSDB", deviceJoinName: "Yale Touch Screen Deadbolt Lock"
|
||||
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0009,0020,0101,0402,0B05,FDBD", outClusters: "000A,0019", manufacturer: "Kwikset", model: "SMARTCODE_DEADBOLT_5", deviceJoinName: "Kwikset 5-Button Deadbolt"
|
||||
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0009,0020,0101,0402,0B05,FDBD", outClusters: "000A,0019", manufacturer: "Kwikset", model: "SMARTCODE_LEVER_5", deviceJoinName: "Kwikset 5-Button Lever"
|
||||
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0009,0020,0101,0402,0B05,FDBD", outClusters: "000A,0019", manufacturer: "Kwikset", model: "SMARTCODE_DEADBOLT_10", deviceJoinName: "Kwikset 10-Button Deadbolt"
|
||||
|
||||
@@ -38,10 +38,7 @@ metadata {
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic A60 TW", deviceJoinName: "OSRAM LIGHTIFY LED Classic A60 Tunable White"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY A19 Tunable White", deviceJoinName: "SYLVANIA Smart A19 Tunable White"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic B40 TW - LIGHTIFY", deviceJoinName: "OSRAM LIGHTIFY Classic B40 Tunable White"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "Z01-A19NAE26", deviceJoinName: "Sengled Element Plus"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "Z01-A191AE26W", deviceJoinName: "Sengled Element Plus"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "Z01-A60EAB22", deviceJoinName: "Sengled Element Plus"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "Z01-A60EAE27", deviceJoinName: "Sengled Element Plus"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "Z01-A19NAE26", deviceJoinName: "Sengled Element plus"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, 0B05, FC01, FC08", outClusters: "0003, 0019", manufacturer: "LEDVANCE", model: "A19 TW 10 year", deviceJoinName: "SYLVANIA Smart 10Y A19 TW"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Conv Under Cabinet TW", deviceJoinName: "SYLVANIA Smart Convertible Under Cabinet"
|
||||
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "ColorstripRGBW", deviceJoinName: "SYLVANIA Smart Convertible Under Cabinet"
|
||||
|
||||
@@ -31,13 +31,6 @@ metadata {
|
||||
fingerprint mfr:"001D", prod:"0401", model:"0334", deviceJoinName: "Leviton 600W Incandescent Dimmer"
|
||||
fingerprint mfr:"0111", prod:"8200", model:"0200", deviceJoinName: "Remotec Technology Plug-In Dimmer"
|
||||
fingerprint mfr:"1104", prod:"001D", model:"0501", deviceJoinName: "Leviton 1000W Incandescant Dimmer"
|
||||
fingerprint mfr:"0039", prod:"5044", model:"3033", deviceJoinName: "Honeywell Z-Wave Plug-in Dimmer (Dual Outlet)"
|
||||
fingerprint mfr:"0039", prod:"5044", model:"3038", deviceJoinName: "Honeywell Z-Wave Plug-in Dimmer"
|
||||
fingerprint mfr:"0039", prod:"4944", model:"3038", deviceJoinName: "Honeywell Z-Wave In-Wall Smart Dimmer"
|
||||
fingerprint mfr:"0039", prod:"4944", model:"3130", deviceJoinName: "Honeywell Z-Wave In-Wall Smart Toggle Dimmer"
|
||||
fingerprint mfr:"0063", prod:"4944", model:"3034", deviceJoinName: "GE In-Wall Smart Fan Control"
|
||||
fingerprint mfr:"0063", prod:"4944", model:"3131", deviceJoinName: "GE In-Wall Smart Fan Control"
|
||||
fingerprint mfr:"0039", prod:"4944", model:"3131", deviceJoinName: "Honeywell Z-Wave Plus In-Wall Fan Speed Control"
|
||||
}
|
||||
|
||||
simulator {
|
||||
@@ -88,7 +81,6 @@ metadata {
|
||||
def installed(){
|
||||
// Device-Watch simply pings if no device events received for 32min(checkInterval)
|
||||
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
|
||||
response(refresh())
|
||||
}
|
||||
|
||||
def updated(){
|
||||
|
||||
@@ -48,7 +48,7 @@ metadata {
|
||||
fingerprint mfr:"0129", prod:"0004", model:"0800", deviceJoinName: "Yale Push Button Deadbolt Door Lock" // YRD110
|
||||
fingerprint mfr:"0129", prod:"0004", model:"0000", deviceJoinName: "Yale Push Button Deadbolt Door Lock" // YRD210
|
||||
fingerprint mfr:"0129", prod:"0001", model:"0000", deviceJoinName: "Yale Push Button Lever Door Lock" // YRD210
|
||||
fingerprint mfr:"0129", prod:"8002", model:"0600", deviceJoinName: "Yale Assure Lock" //YRD416, YRD426, YRD446
|
||||
fingerprint mfr:"0129", prod:"8002", model:"0600", deviceJoinName: "Yale Assure Lock with Bluetooth" //YRD416, YRD426, YRD446
|
||||
fingerprint mfr:"0129", prod:"0007", model:"0001", deviceJoinName: "Yale Keyless Connected Smart Door Lock"
|
||||
fingerprint mfr:"0129", prod:"8004", model:"0600", deviceJoinName: "Yale Assure Lock Push Button Deadbolt" //YRD216
|
||||
// Samsung
|
||||
@@ -320,18 +320,7 @@ def zwaveEvent(DoorLockOperationReport cmd) {
|
||||
result << response(secure(zwave.associationV1.associationGet(groupingIdentifier:1)))
|
||||
}
|
||||
}
|
||||
if (generatesDoorLockOperationReportBeforeAlarmReport()) {
|
||||
// we're expecting lock events to come after notification events, but for specific yale locks they come out of order
|
||||
runIn(3, "delayLockEvent", [data: [map: map]])
|
||||
return [:]
|
||||
} else {
|
||||
return result ? [createEvent(map), *result] : createEvent(map)
|
||||
}
|
||||
}
|
||||
|
||||
def delayLockEvent(data) {
|
||||
log.debug "Sending cached lock operation: $data.map"
|
||||
sendEvent(data.map)
|
||||
result ? [createEvent(map), *result] : createEvent(map)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -398,7 +387,7 @@ private def handleAccessAlarmReport(cmd) {
|
||||
break
|
||||
case 5: // Locked with keypad
|
||||
if (cmd.eventParameter || cmd.alarmLevel) {
|
||||
codeID = readCodeSlotId(cmd)
|
||||
codeID = cmd.eventParameter[2] ?: cmd.alarmLevel
|
||||
codeName = getCodeName(lockCodes, codeID)
|
||||
map.descriptionText = "Locked by \"$codeName\""
|
||||
map.data = [ usedCode: codeID, codeName: codeName, method: "keypad" ]
|
||||
@@ -409,7 +398,7 @@ private def handleAccessAlarmReport(cmd) {
|
||||
break
|
||||
case 6: // Unlocked with keypad
|
||||
if (cmd.eventParameter || cmd.alarmLevel) {
|
||||
codeID = readCodeSlotId(cmd)
|
||||
codeID = cmd.eventParameter[2] ?: cmd.alarmLevel
|
||||
codeName = getCodeName(lockCodes, codeID)
|
||||
map.descriptionText = "Unlocked by \"$codeName\""
|
||||
map.data = [ usedCode: codeID, codeName: codeName, method: "keypad" ]
|
||||
@@ -442,7 +431,7 @@ private def handleAccessAlarmReport(cmd) {
|
||||
break
|
||||
case 0xD: // User code deleted
|
||||
if (cmd.eventParameter || cmd.alarmLevel) {
|
||||
codeID = readCodeSlotId(cmd)
|
||||
codeID = cmd.eventParameter[2] ?: cmd.alarmLevel
|
||||
if (lockCodes[codeID.toString()]) {
|
||||
codeName = getCodeName(lockCodes, codeID)
|
||||
map = [ name: "codeChanged", value: "$codeID deleted", isStateChange: true ]
|
||||
@@ -454,7 +443,7 @@ private def handleAccessAlarmReport(cmd) {
|
||||
break
|
||||
case 0xE: // Master or user code changed/set
|
||||
if (cmd.eventParameter || cmd.alarmLevel) {
|
||||
codeID = readCodeSlotId(cmd)
|
||||
codeID = cmd.eventParameter[2] ?: cmd.alarmLevel
|
||||
if(codeID == 0 && isKwiksetLock()) {
|
||||
//Ignoring this AlarmReport as Kwikset reports codeID 0 when all slots are full and user tries to set another lock code manually
|
||||
//Kwikset locks don't send AlarmReport when Master code is set
|
||||
@@ -475,7 +464,7 @@ private def handleAccessAlarmReport(cmd) {
|
||||
break
|
||||
case 0xF: // Duplicate Pin-code error
|
||||
if (cmd.eventParameter || cmd.alarmLevel) {
|
||||
codeID = readCodeSlotId(cmd)
|
||||
codeID = cmd.eventParameter[2] ?: cmd.alarmLevel
|
||||
clearStateForSlot(codeID)
|
||||
map = [ name: "codeChanged", value: "$codeID failed", descriptionText: "User code is duplicate and not added",
|
||||
isStateChange: true, data: [isCodeDuplicate: true] ]
|
||||
@@ -603,14 +592,14 @@ private def handleAlarmReportUsingAlarmType(cmd) {
|
||||
case 19: // Unlocked with keypad
|
||||
map = [ name: "lock", value: "unlocked" ]
|
||||
if (cmd.alarmLevel != null) {
|
||||
codeID = readCodeSlotId(cmd)
|
||||
codeID = cmd.alarmLevel
|
||||
codeName = getCodeName(lockCodes, codeID)
|
||||
map.descriptionText = "Unlocked by \"$codeName\""
|
||||
map.data = [ usedCode: codeID, codeName: codeName, method: "keypad" ]
|
||||
}
|
||||
break
|
||||
case 18: // Locked with keypad
|
||||
codeID = readCodeSlotId(cmd)
|
||||
codeID = cmd.alarmLevel
|
||||
map = [ name: "lock", value: "locked" ]
|
||||
// Kwikset lock reporting code id as 0 when locked using the lock keypad button
|
||||
if (isKwiksetLock() && codeID == 0) {
|
||||
@@ -657,7 +646,7 @@ private def handleAlarmReportUsingAlarmType(cmd) {
|
||||
result << createEvent(name: "lockCodes", value: util.toJson([:]), displayed: false, descriptionText: "'lockCodes' attribute updated")
|
||||
break
|
||||
case 33: // User code deleted
|
||||
codeID = readCodeSlotId(cmd)
|
||||
codeID = cmd.alarmLevel
|
||||
if (lockCodes[codeID.toString()]) {
|
||||
codeName = getCodeName(lockCodes, codeID)
|
||||
map = [ name: "codeChanged", value: "$codeID deleted", isStateChange: true ]
|
||||
@@ -671,7 +660,7 @@ private def handleAlarmReportUsingAlarmType(cmd) {
|
||||
break
|
||||
case 13:
|
||||
case 112: // Master or user code changed/set
|
||||
codeID = readCodeSlotId(cmd)
|
||||
codeID = cmd.alarmLevel
|
||||
if(codeID == 0 && isKwiksetLock()) {
|
||||
//Ignoring this AlarmReport as Kwikset reports codeID 0 when all slots are full and user tries to set another lock code manually
|
||||
//Kwikset locks don't send AlarmReport when Master code is set
|
||||
@@ -692,7 +681,7 @@ private def handleAlarmReportUsingAlarmType(cmd) {
|
||||
break
|
||||
case 34:
|
||||
case 113: // Duplicate Pin-code error
|
||||
codeID = readCodeSlotId(cmd)
|
||||
codeID = cmd.alarmLevel
|
||||
clearStateForSlot(codeID)
|
||||
map = [ name: "codeChanged", value: "$codeID failed", descriptionText: "User code is duplicate and not added",
|
||||
isStateChange: true, data: [isCodeDuplicate: true] ]
|
||||
@@ -1668,30 +1657,3 @@ def isYaleLock() {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this lock generates door lock operation report before alarm report, false otherwise
|
||||
* @return true if this lock generates door lock operation report before alarm report, false otherwise
|
||||
*/
|
||||
def generatesDoorLockOperationReportBeforeAlarmReport() {
|
||||
//Fix for ICP-2367, ICP-2366
|
||||
if(isYaleLock() && "0007" == zwaveInfo.prod && "0001" == zwaveInfo.model) {
|
||||
//Yale Keyless Connected Smart Door Lock
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic function for reading code Slot ID from AlarmReport command
|
||||
* @param cmd: The AlarmReport command
|
||||
* @return user code slot id
|
||||
*/
|
||||
def readCodeSlotId(physicalgraph.zwave.commands.alarmv2.AlarmReport cmd) {
|
||||
if(cmd.numberOfEventParameters == 1) {
|
||||
return cmd.eventParameter[0]
|
||||
} else if(cmd.numberOfEventParameters >= 3) {
|
||||
return cmd.eventParameter[2]
|
||||
}
|
||||
return cmd.alarmLevel
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ metadata {
|
||||
capability "Actuator"
|
||||
capability "Switch"
|
||||
capability "Power Meter"
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Configuration"
|
||||
capability "Sensor"
|
||||
@@ -200,6 +201,14 @@ def off() {
|
||||
]
|
||||
}
|
||||
|
||||
def poll() {
|
||||
delayBetween([
|
||||
zwave.switchBinaryV1.switchBinaryGet().format(),
|
||||
zwave.meterV2.meterGet(scale: 0).format(),
|
||||
zwave.meterV2.meterGet(scale: 2).format()
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
* */
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
metadata {
|
||||
definition (name: "Z-Wave Plus Door/Window Sensor", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.contact", runLocally: true, minHubCoreVersion: '000.020.00008', executeCommandsLocally: true) {
|
||||
definition (name: "Z-Wave Plus Door/Window Sensor", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.contact") {
|
||||
capability "Contact Sensor"
|
||||
capability "Configuration"
|
||||
capability "Battery"
|
||||
|
||||
@@ -31,12 +31,6 @@ metadata {
|
||||
fingerprint mfr:"001D", prod:"1603", model:"0334", deviceJoinName: "Leviton 15A Split Duplex Receptacle"
|
||||
fingerprint mfr:"011A", prod:"0101", model:"0102", deviceJoinName: "Enerwave On/Off Switch"
|
||||
fingerprint mfr:"011A", prod:"0101", model:"0603", deviceJoinName: "Enerwave Duplex Receptacle"
|
||||
fingerprint mfr:"0039", prod:"5052", model:"3038", deviceJoinName: "Honeywell Z-Wave Plug-in Switch"
|
||||
fingerprint mfr:"0039", prod:"5052", model:"3033", deviceJoinName: "Honeywell Z-Wave Plug-in Switch (Dual Outlet)"
|
||||
fingerprint mfr:"0039", prod:"4F50", model:"3032", deviceJoinName: "Honeywell Z-Wave Plug-in Outdoor Smart Switch"
|
||||
fingerprint mfr:"0039", prod:"4952", model:"3036", deviceJoinName: "Honeywell Z-Wave In-Wall Smart Switch"
|
||||
fingerprint mfr:"0039", prod:"4952", model:"3037", deviceJoinName: "Honeywell Z-Wave In-Wall Smart Toggle Switch"
|
||||
fingerprint mfr:"0039", prod:"4952", model:"3133", deviceJoinName: "Honeywell Z-Wave In-Wall Tamper Resistant Duplex Receptacle"
|
||||
}
|
||||
|
||||
// simulator metadata
|
||||
|
||||
@@ -16,6 +16,7 @@ metadata {
|
||||
capability "Actuator"
|
||||
capability "Indicator"
|
||||
capability "Switch"
|
||||
capability "Polling"
|
||||
capability "Refresh"
|
||||
capability "Sensor"
|
||||
capability "Health Check"
|
||||
@@ -176,6 +177,13 @@ def off() {
|
||||
])
|
||||
}
|
||||
|
||||
def poll() {
|
||||
delayBetween([
|
||||
zwave.switchBinaryV1.switchBinaryGet().format(),
|
||||
zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* PING is used by Device-Watch in attempt to reach the Device
|
||||
**/
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/**
|
||||
* Copyright 2017 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.
|
||||
*
|
||||
* Thermostats
|
||||
*
|
||||
* Author: Juan Pablo Risso
|
||||
* Date: 2017-12-05
|
||||
*
|
||||
*/
|
||||
|
||||
definition(
|
||||
name: "Thermostats",
|
||||
namespace: "smartthings",
|
||||
author: "SmartThings",
|
||||
description: "Receive notifications when anything happens in your home.",
|
||||
category: "SmartSolutions",
|
||||
iconUrl: "https://s3.amazonaws.com/smartapp-icons/SafetyAndSecurity/Cat-SafetyAndSecurity.png",
|
||||
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/SafetyAndSecurity/Cat-SafetyAndSecurity@2x.png",
|
||||
singleInstance: true
|
||||
)
|
||||
|
||||
preferences {
|
||||
section("Choose one or more, when..."){
|
||||
input "smokeDevices", "capability.smokeDetector", title: "Smoke Detected", required: false, multiple: true
|
||||
input "carbonMonoxideDevices", "capability.carbonMonoxideDetector", title: "Carbon Monoxide Detected", required: false, multiple: true
|
||||
}
|
||||
section("Turn off these thermostats"){
|
||||
input "thermostatDevices", "capability.thermostat", title: "Thermostats", required: true, multiple: true
|
||||
}
|
||||
section("Send this message (optional, sends standard status message if not specified)"){
|
||||
input "messageText", "text", title: "Message Text", required: false
|
||||
}
|
||||
section("Via a push notification and/or an SMS message"){
|
||||
input("recipients", "contact", title: "Send notifications to") {
|
||||
input "phone", "phone", title: "Enter a phone number to get SMS", required: false
|
||||
paragraph "If outside the US please make sure to enter the proper country code"
|
||||
input "pushAndPhone", "enum", title: "Notify me via Push Notification", required: false, options: ["Yes", "No"]
|
||||
}
|
||||
}
|
||||
section("Minimum time between messages (optional, defaults to every message)") {
|
||||
input "frequency", "decimal", title: "Minutes", required: false
|
||||
}
|
||||
}
|
||||
|
||||
def installed() {
|
||||
log.debug "Installed with settings: ${settings}"
|
||||
subscribeToEvents()
|
||||
}
|
||||
|
||||
def updated() {
|
||||
log.debug "Updated with settings: ${settings}"
|
||||
unsubscribe()
|
||||
subscribeToEvents()
|
||||
}
|
||||
|
||||
def subscribeToEvents() {
|
||||
subscribe(smokeDevices, "smoke.detected", eventHandler)
|
||||
subscribe(smokeDevices, "smoke.tested", eventHandler)
|
||||
subscribe(smokeDevices, "carbonMonoxide.detected", eventHandler)
|
||||
subscribe(carbonMonoxideDevices, "carbonMonoxide.detected", eventHandler)
|
||||
}
|
||||
|
||||
def eventHandler(evt) {
|
||||
log.debug "Notify got evt ${evt}"
|
||||
// Turn off thermostat
|
||||
thermostatDevices*.setThermostatMode("off")
|
||||
if (frequency) {
|
||||
def lastTime = state[evt.deviceId]
|
||||
if (lastTime == null || now() - lastTime >= frequency * 60000) {
|
||||
sendMessage(evt)
|
||||
}
|
||||
}
|
||||
else {
|
||||
sendMessage(evt)
|
||||
}
|
||||
}
|
||||
|
||||
private sendMessage(evt) {
|
||||
String msg = messageText
|
||||
Map options = [:]
|
||||
|
||||
if (!messageText) {
|
||||
msg = '{{ triggerEvent.descriptionText }}'
|
||||
options = [translatable: true, triggerEvent: evt]
|
||||
}
|
||||
log.debug "$evt.name:$evt.value, pushAndPhone:$pushAndPhone, '$msg'"
|
||||
|
||||
if (location.contactBookEnabled) {
|
||||
sendNotificationToContacts(msg, recipients, options)
|
||||
} else {
|
||||
if (phone) {
|
||||
options.phone = phone
|
||||
if (pushAndPhone != 'No') {
|
||||
log.debug 'Sending push and SMS'
|
||||
options.method = 'both'
|
||||
} else {
|
||||
log.debug 'Sending SMS'
|
||||
options.method = 'phone'
|
||||
}
|
||||
} else if (pushAndPhone != 'No') {
|
||||
log.debug 'Sending push'
|
||||
options.method = 'push'
|
||||
} else {
|
||||
log.debug 'Sending nothing'
|
||||
options.method = 'none'
|
||||
}
|
||||
sendNotification(msg, options)
|
||||
}
|
||||
if (frequency) {
|
||||
state[evt.deviceId] = now()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user