Compare commits

..

2 Commits

Author SHA1 Message Date
PASCI
93219abcc8 Modifying 'Slightly smarter use of motion sensor' 2017-01-10 09:55:02 -08:00
PASCI
4b8e94b7ca MSA-1693: It control a SWITCH combining a MOTION SENSOR and a TIMEFRAME interval.
The MOTION works as expected outside the TIMEFRAME interval.
The SWITCH is always ON during the TIMEFRAME interval.
If there is no MOTION the SWITCH is turned OFF at the end of the TIMEFRAME interval.
2017-01-09 10:18:57 -08:00
2 changed files with 125 additions and 273 deletions

View File

@@ -1,273 +0,0 @@
/**
* Copyright 2015 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
* Z-Wave Door/Window Sensor
*
* Author: SmartThings
* Date: 2013-11-3
*/
metadata {
definition (name: "Z-Wave Door Sensor as Smoke Detector", namespace: "smartthings", author: "SmartThings") {
capability "Contact Sensor"
capability "Sensor"
capability "Battery"
capability "Configuration"
fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x85,0x86,0x72"
fingerprint deviceId: "0x07", inClusters: "0x30"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x98"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x80,0x71,0x85,0x70,0x72,0x86,0x30,0x31,0x84,0x59,0x73,0x5A,0x8F,0x98,0x7A", outClusters:"0x20" // Philio multi+
}
// simulator metadata
simulator {
// status messages
status "fire": "command: 2001, payload: FF"
status "safe": "command: 2001, payload: 00"
status "wake up": "command: 8407, payload: "
}
// UI tile definitions
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state "fire",label: '${name}',icon: "st.alarm.smoke.smoke",backgroundColor: "#ffa81e"
state "safe",label: '${name}',icon: "st.alarm.smoke.clear",backgroundColor: "#79b821"
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
}
main "contact"
details(["contact", "battery"])
}
}
def parse(String description) {
def result = null
if (description.startsWith("Err 106")) {
if (state.sec) {
log.debug description
} else {
result = createEvent(
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.",
eventType: "ALERT",
name: "secureInclusion",
value: "failed",
isStateChange: true,
)
}
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
log.debug "parsed '$description' to $result"
return result
}
def updated() {
def cmds = []
if (!state.MSR) {
cmds = [
command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()),
"delay 1200",
zwave.wakeUpV1.wakeUpNoMoreInformation().format()
]
} else if (!state.lastbat) {
cmds = []
} else {
cmds = [zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
response(cmds)
}
def configure() {
commands([
zwave.manufacturerSpecificV2.manufacturerSpecificGet(),
zwave.batteryV1.batteryGet()
], 6000)
}
def sensorValueEvent(value) {
if (value) {
createEvent(name: "contact", value: "fire", descriptionText: "$device.displayName fire detected")
} else {
createEvent(name: "contact", value: "safe", descriptionText: "$device.displayName is safe")
}
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv1.SensorBinaryReport cmd)
{
sensorValueEvent(cmd.sensorValue)
}
def zwaveEvent(physicalgraph.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)
{
sensorValueEvent(cmd.sensorState)
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd)
{
def result = []
if (cmd.notificationType == 0x06 && cmd.event == 0x16) {
result << sensorValueEvent(1)
} else if (cmd.notificationType == 0x06 && cmd.event == 0x17) {
result << sensorValueEvent(0)
} else if (cmd.notificationType == 0x07) {
if (cmd.v1AlarmType == 0x07) { // special case for nonstandard messages from Monoprice door/window sensors
result << sensorValueEvent(cmd.v1AlarmLevel)
} else if (cmd.event == 0x01 || cmd.event == 0x02) {
result << sensorValueEvent(1)
} else if (cmd.event == 0x03) {
result << createEvent(descriptionText: "$device.displayName covering was removed", isStateChange: true)
if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()))
} else if (cmd.event == 0x05 || cmd.event == 0x06) {
result << createEvent(descriptionText: "$device.displayName detected glass breakage", isStateChange: true)
} else if (cmd.event == 0x07) {
if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()))
result << createEvent(name: "motion", value: "active", descriptionText:"$device.displayName detected motion")
}
} else if (cmd.notificationType) {
def text = "Notification $cmd.notificationType: event ${([cmd.event] + cmd.eventParameter).join(", ")}"
result << createEvent(name: "notification$cmd.notificationType", value: "$cmd.event", descriptionText: text, displayed: false)
} else {
def value = cmd.v1AlarmLevel == 255 ? "active" : cmd.v1AlarmLevel ?: "inactive"
result << createEvent(name: "alarm $cmd.v1AlarmType", value: value, displayed: false)
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
def event = createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)
def cmds = []
if (!state.MSR) {
cmds << command(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
cmds << "delay 1200"
}
if (!state.lastbat || now() - state.lastbat > 53*60*60*1000) {
cmds << command(zwave.batteryV1.batteryGet())
} else {
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
}
[event, response(cmds)]
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} has a low battery"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbat = now()
[createEvent(map), response(zwave.wakeUpV1.wakeUpNoMoreInformation())]
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def result = []
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
log.debug "msr: $msr"
updateDataValue("MSR", msr)
retypeBasedOnMSR()
result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
if (msr == "011A-0601-0901") { // Enerwave motion doesn't always get the associationSet that the hub sends on join
result << response(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId))
} else if (!device.currentState("battery")) {
if (msr == "0086-0102-0059") {
result << response(zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.batteryV1.batteryGet()).format())
} else {
result << response(command(zwave.batteryV1.batteryGet()))
}
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
// log.debug "encapsulated: $encapsulatedCommand"
if (encapsulatedCommand) {
state.sec = 1
zwaveEvent(encapsulatedCommand)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: "$device.displayName: $cmd", displayed: false)
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec == 1) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=200) {
delayBetween(commands.collect{ command(it) }, delay)
}
def retypeBasedOnMSR() {
switch (state.MSR) {
case "0086-0002-002D":
log.debug "Changing device type to Z-Wave Water Sensor"
setDeviceType("Z-Wave Water Sensor")
break
case "011F-0001-0001": // Schlage motion
case "014A-0001-0001": // Ecolink motion
case "014A-0004-0001": // Ecolink motion +
case "0060-0001-0002": // Everspring SP814
case "0060-0001-0003": // Everspring HSP02
case "011A-0601-0901": // Enerwave ZWN-BPC
log.debug "Changing device type to Z-Wave Motion Sensor"
setDeviceType("Z-Wave Motion Sensor")
break
case "013C-0002-000D": // Philio multi +
log.debug "Changing device type to 3-in-1 Multisensor Plus (SG)"
setDeviceType("3-in-1 Multisensor Plus (SG)")
break
case "0109-2001-0106": // Vision door/window
log.debug "Changing device type to Z-Wave Plus Door/Window Sensor"
setDeviceType("Z-Wave Plus Door/Window Sensor")
break
case "0109-2002-0205": // Vision Motion
log.debug "Changing device type to Z-Wave Plus Motion/Temp Sensor"
setDeviceType("Z-Wave Plus Motion/Temp Sensor")
break
}
}

View File

@@ -0,0 +1,125 @@
//==================================================================================
/**
* Motion-Switch-Sched SmartApp
*
* Copyright 2017 PASCI Ciro Ippolito 2017
***********************************************************************************
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
//==================================================================================
definition(
name: "Motion Switch SmartTimeframe",
namespace: "PASCI",
author: "PASCI",
description: "Motion Activated switch + Override timeframe.",
category: "Convenience",
iconUrl: "http://cdn.device-icons.smartthings.com/Home/home30-icn@2x.png",
iconX2Url: "http://cdn.device-icons.smartthings.com/Home/home30-icn@2x.png",
iconX3Url: "http://cdn.device-icons.smartthings.com/Home/home30-icn@2x.png"
)
//iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
//iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
//iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
//==================================================================================
preferences {
section("When MOTION is detected") {
input "themotion", "capability.motionSensor", required: true, title: "WHERE"
}
section("Turn ON this SWITCH") {
input "OUTLE", "capability.switch", required: true, title: "WHICH"
}
section("ON for how long") {
input "minutes", "number", required: true, title: "MINUTES)"
}
section("ON OVERRIDE time frame (if there is no motion)") {
input "FROMTime", "time", title: "From", required: true
input "TOTime", "time", title: "To", required: true
}
}
//==================================================================================
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
//==================================================================================
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
//==================================================================================
def initialize() {
log.debug "Installata at: " + now()
schedule(FROMTime, handlerFROMTIME)
schedule(TOTime, handlerTOTime)
subscribe(themotion, "motion.active", handler_Motion___Active)
subscribe(themotion, "motion.inactive", handler_motion_inactive)
}
// HANDLERS
//==================================================================================
def handlerFROMTIME() {
log.debug "FROM TIME at ${new Date()}"
OUTLE.on()
}
//==================================================================================
def handlerTOTime() {
log.debug "TO TIME at ${new Date()}"
checkMotion();
/*
def motionState = themotion.currentState("motion")
log.debug "state of motion sensor is: " + motionState.value
log.debug "TURN OFF at ${new Date()}"
log.debug "state of motion sensor is: " + themotion.motion
if (motionState.value == "active"){
log.debug "state of motion sensor is ACTIVE"
}else{
OUTLE.off()
log.debug "state of motion sensor is INACTIVE"
}
*/
}
//==================================================================================
def handler_Motion___Active(evt) {
log.debug("MOT Active")
OUTLE.on()
}
//==================================================================================
def handler_motion_inactive(evt) {
log.debug("MOT Inactive")
def between = timeOfDayIsBetween(FROMTime, TOTime, new Date(), location.timeZone)
if (between) {
log.debug("It dasan't mattar Christopha")
OUTLE.on()
} else {
runIn(60 * minutes, checkMotion)
}
}
//==================================================================================
def checkMotion() {
log.debug "In checkMotion scheduled method"
// get the current state object for the motion sensor
def motionState = themotion.currentState("motion")
if (motionState.value == "inactive") {
def elapsed = now() - motionState.date.time // time elapsed between now and when the motion reported inactive
def threshold = 1000 * 60 * minutes // elapsed time is in milliseconds
if (elapsed >= threshold) {
log.debug "Motion has stayed inactive long enough since last check ($elapsed ms): turning switch off"
OUTLE.off()
} else {
log.debug "Motion has not stayed inactive long enough since last check ($elapsed ms): doing nothing"
}
} else {
// Motion active; just log it and do nothing
log.debug "Motion is active, do nothing and wait for inactive"
}
}
//==================================================================================
//==================================================================================