Compare commits

...

1 Commits

Author SHA1 Message Date
박춘영
2a871b66b4 MSA-934: 스마트싱작업 테스트해보는중입니다 2016-03-08 03:23:23 -06:00
2 changed files with 410 additions and 317 deletions

View File

@@ -0,0 +1,93 @@
/**
* TEST
*
* Copyright 2016 박춘영
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
definition (name: "TEST", namespace: "스마트보안", author: "박춘영") {
capability "Button"
capability "Samsung TV"
}
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 'button' attribute
// TODO: handle 'volume' attribute
// TODO: handle 'mute' attribute
// TODO: handle 'pictureMode' attribute
// TODO: handle 'soundMode' attribute
// TODO: handle 'switch' attribute
// TODO: handle 'messageButton' attribute
}
// handle commands
def volumeUp() {
log.debug "Executing 'volumeUp'"
// TODO: handle 'volumeUp' command
}
def volumeDown() {
log.debug "Executing 'volumeDown'"
// TODO: handle 'volumeDown' command
}
def setVolume() {
log.debug "Executing 'setVolume'"
// TODO: handle 'setVolume' command
}
def mute() {
log.debug "Executing 'mute'"
// TODO: handle 'mute' command
}
def unmute() {
log.debug "Executing 'unmute'"
// TODO: handle 'unmute' command
}
def setPictureMode() {
log.debug "Executing 'setPictureMode'"
// TODO: handle 'setPictureMode' command
}
def setSoundMode() {
log.debug "Executing 'setSoundMode'"
// TODO: handle 'setSoundMode' command
}
def on() {
log.debug "Executing 'on'"
// TODO: handle 'on' command
}
def off() {
log.debug "Executing 'off'"
// TODO: handle 'off' command
}
def showMessage() {
log.debug "Executing 'showMessage'"
// TODO: handle 'showMessage' command
}

View File

@@ -1,317 +1,317 @@
/** /**
* Copyright 2015 SmartThings * Copyright 2015 SmartThings
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * 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: * in compliance with the License. You may obtain a copy of the License at:
* *
* http://www.apache.org/licenses/LICENSE-2.0 * 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 * 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 * 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. * for the specific language governing permissions and limitations under the License.
* *
* Smart Security * Smart Security
* *
* Author: SmartThings * Author: SmartThings
* Date: 2013-03-07 * Date: 2013-03-07
*/ */
definition( definition(
name: "Smart Security", name: "Smart Security",
namespace: "smartthings", namespace: "smartthings",
author: "SmartThings", author: "SmartThings",
description: "Alerts you when there are intruders but not when you just got up for a glass of water in the middle of the night", description: "Alerts you when there are intruders but not when you just got up for a glass of water in the middle of the night",
category: "Safety & Security", category: "Safety & Security",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/SafetyAndSecurity/App-IsItSafe.png", iconUrl: "https://s3.amazonaws.com/smartapp-icons/SafetyAndSecurity/App-IsItSafe.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/SafetyAndSecurity/App-IsItSafe@2x.png" iconX2Url: "https://s3.amazonaws.com/smartapp-icons/SafetyAndSecurity/App-IsItSafe@2x.png"
) )
preferences { preferences {
section("Sensors detecting an intruder") { section("Sensors detecting an intruder") {
input "intrusionMotions", "capability.motionSensor", title: "Motion Sensors", multiple: true, required: false input "intrusionMotions", "capability.motionSensor", title: "Motion Sensors", multiple: true, required: false
input "intrusionContacts", "capability.contactSensor", title: "Contact Sensors", multiple: true, required: false input "intrusionContacts", "capability.contactSensor", title: "Contact Sensors", multiple: true, required: false
} }
section("Sensors detecting residents") { section("Sensors detecting residents") {
input "residentMotions", "capability.motionSensor", title: "Motion Sensors", multiple: true, required: false input "residentMotions", "capability.motionSensor", title: "Motion Sensors", multiple: true, required: false
} }
section("Alarm settings and actions") { section("Alarm settings and actions") {
input "alarms", "capability.alarm", title: "Which Alarm(s)", multiple: true, required: false input "alarms", "capability.alarm", title: "Which Alarm(s)", multiple: true, required: false
input "silent", "enum", options: ["Yes","No"], title: "Silent alarm only (Yes/No)" input "silent", "enum", options: ["Yes","No"], title: "Silent alarm only (Yes/No)"
input "seconds", "number", title: "Delay in seconds before siren sounds" input "seconds", "number", title: "Delay in seconds before siren sounds"
input "lights", "capability.switch", title: "Flash these lights (optional)", multiple: true, required: false input "lights", "capability.switch", title: "Flash these lights (optional)", multiple: true, required: false
input "newMode", "mode", title: "Change to this mode (optional)", required: false input "newMode", "mode", title: "Change to this mode (optional)", required: false
} }
section("Notify others (optional)") { section("Notify others (optional)") {
input "textMessage", "text", title: "Send this message", multiple: false, required: false input "textMessage", "text", title: "Send this message", multiple: false, required: false
input("recipients", "contact", title: "Send notifications to") { input("recipients", "contact", title: "Send notifications to") {
input "phone", "phone", title: "To this phone", multiple: false, required: false input "phone", "phone", title: "To this phone", multiple: false, required: false
} }
} }
section("Arm system when residents quiet for (default 3 minutes)") { section("Arm system when residents quiet for (default 3 minutes)") {
input "residentsQuietThreshold", "number", title: "Time in minutes", required: false input "residentsQuietThreshold", "number", title: "Time in minutes", required: false
} }
} }
def installed() { def installed() {
log.debug "INSTALLED" log.debug "INSTALLED"
subscribeToEvents() subscribeToEvents()
state.alarmActive = null state.alarmActive = null
} }
def updated() { def updated() {
log.debug "UPDATED" log.debug "UPDATED"
unsubscribe() unsubscribe()
subscribeToEvents() subscribeToEvents()
unschedule() unschedule()
state.alarmActive = null state.alarmActive = null
state.residentsAreUp = null state.residentsAreUp = null
state.lastIntruderMotion = null state.lastIntruderMotion = null
alarms?.off() alarms?.off()
} }
private subscribeToEvents() private subscribeToEvents()
{ {
subscribe intrusionMotions, "motion", intruderMotion subscribe intrusionMotions, "motion", intruderMotion
subscribe residentMotions, "motion", residentMotion subscribe residentMotions, "motion", residentMotion
subscribe intrusionContacts, "contact", contact subscribe intrusionContacts, "contact", contact
subscribe alarms, "alarm", alarm subscribe alarms, "alarm", alarm
subscribe(app, appTouch) subscribe(app, appTouch)
} }
private residentsHaveBeenQuiet() private residentsHaveBeenQuiet()
{ {
def threshold = ((residentsQuietThreshold != null && residentsQuietThreshold != "") ? residentsQuietThreshold : 3) * 60 * 1000 def threshold = ((residentsQuietThreshold != null && residentsQuietThreshold != "") ? residentsQuietThreshold : 3) * 60 * 1000
def result = true def result = true
def t0 = new Date(now() - threshold) def t0 = new Date(now() - threshold)
for (sensor in residentMotions) { for (sensor in residentMotions) {
def recentStates = sensor.statesSince("motion", t0) def recentStates = sensor.statesSince("motion", t0)
if (recentStates.find{it.value == "active"}) { if (recentStates.find{it.value == "active"}) {
result = false result = false
break break
} }
} }
log.debug "residentsHaveBeenQuiet: $result" log.debug "residentsHaveBeenQuiet: $result"
result result
} }
private intruderMotionInactive() private intruderMotionInactive()
{ {
def result = true def result = true
for (sensor in intrusionMotions) { for (sensor in intrusionMotions) {
if (sensor.currentMotion == "active") { if (sensor.currentMotion == "active") {
result = false result = false
break break
} }
} }
result result
} }
private isResidentMotionSensor(evt) private isResidentMotionSensor(evt)
{ {
residentMotions?.find{it.id == evt.deviceId} != null residentMotions?.find{it.id == evt.deviceId} != null
} }
def appTouch(evt) def appTouch(evt)
{ {
alarms?.off() alarms?.off()
state.alarmActive = false state.alarmActive = false
} }
// Here to handle old subscriptions // Here to handle old subscriptions
def motion(evt) def motion(evt)
{ {
if (isResidentMotionSensor(evt)) { if (isResidentMotionSensor(evt)) {
log.debug "resident motion, $evt.name: $evt.value" log.debug "resident motion, $evt.name: $evt.value"
residentMotion(evt) residentMotion(evt)
} }
else { else {
log.debug "intruder motion, $evt.name: $evt.value" log.debug "intruder motion, $evt.name: $evt.value"
intruderMotion(evt) intruderMotion(evt)
} }
} }
def intruderMotion(evt) def intruderMotion(evt)
{ {
if (evt.value == "active") { if (evt.value == "active") {
log.debug "motion by potential intruder, residentsAreUp: $state.residentsAreUp" log.debug "motion by potential intruder, residentsAreUp: $state.residentsAreUp"
if (!state.residentsAreUp) { if (!state.residentsAreUp) {
log.trace "checking if residents have been quiet" log.trace "checking if residents have been quiet"
if (residentsHaveBeenQuiet()) { if (residentsHaveBeenQuiet()) {
log.trace "calling startAlarmSequence" log.trace "calling startAlarmSequence"
startAlarmSequence() startAlarmSequence()
} }
else { else {
log.trace "calling disarmIntrusionDetection" log.trace "calling disarmIntrusionDetection"
disarmIntrusionDetection() disarmIntrusionDetection()
} }
} }
} }
state.lastIntruderMotion = now() state.lastIntruderMotion = now()
} }
def residentMotion(evt) def residentMotion(evt)
{ {
// Don't think we need this any more // Don't think we need this any more
//if (evt.value == "inactive") { //if (evt.value == "inactive") {
// if (state.residentsAreUp) { // if (state.residentsAreUp) {
// startReArmSequence() // startReArmSequence()
// } // }
//} //}
} }
def contact(evt) def contact(evt)
{ {
if (evt.value == "open") { if (evt.value == "open") {
// TODO - check for residents being up? // TODO - check for residents being up?
if (!state.residentsAreUp) { if (!state.residentsAreUp) {
if (residentsHaveBeenQuiet()) { if (residentsHaveBeenQuiet()) {
startAlarmSequence() startAlarmSequence()
} }
else { else {
disarmIntrusionDetection() disarmIntrusionDetection()
} }
} }
} }
} }
def alarm(evt) def alarm(evt)
{ {
log.debug "$evt.name: $evt.value" log.debug "$evt.name: $evt.value"
if (evt.value == "off") { if (evt.value == "off") {
alarms?.off() alarms?.off()
state.alarmActive = false state.alarmActive = false
} }
} }
private disarmIntrusionDetection() private disarmIntrusionDetection()
{ {
log.debug "residents are up, disarming intrusion detection" log.debug "residents are up, disarming intrusion detection"
state.residentsAreUp = true state.residentsAreUp = true
scheduleReArmCheck() scheduleReArmCheck()
} }
private scheduleReArmCheck() private scheduleReArmCheck()
{ {
def cron = "0 * * * * ?" def cron = "0 * * * * ?"
schedule(cron, "checkForReArm") schedule(cron, "checkForReArm")
log.debug "Starting re-arm check, cron: $cron" log.debug "Starting re-arm check, cron: $cron"
} }
def checkForReArm() def checkForReArm()
{ {
def threshold = ((residentsQuietThreshold != null && residentsQuietThreshold != "") ? residentsQuietThreshold : 3) * 60 * 1000 def threshold = ((residentsQuietThreshold != null && residentsQuietThreshold != "") ? residentsQuietThreshold : 3) * 60 * 1000
log.debug "checkForReArm: threshold is $threshold" log.debug "checkForReArm: threshold is $threshold"
// check last intruder motion // check last intruder motion
def lastIntruderMotion = state.lastIntruderMotion def lastIntruderMotion = state.lastIntruderMotion
log.debug "checkForReArm: lastIntruderMotion=$lastIntruderMotion" log.debug "checkForReArm: lastIntruderMotion=$lastIntruderMotion"
if (lastIntruderMotion != null) if (lastIntruderMotion != null)
{ {
log.debug "checkForReArm, time since last intruder motion: ${now() - lastIntruderMotion}" log.debug "checkForReArm, time since last intruder motion: ${now() - lastIntruderMotion}"
if (now() - lastIntruderMotion > threshold) { if (now() - lastIntruderMotion > threshold) {
log.debug "re-arming intrusion detection" log.debug "re-arming intrusion detection"
state.residentsAreUp = false state.residentsAreUp = false
unschedule() unschedule()
} }
} }
else { else {
log.warn "checkForReArm: lastIntruderMotion was null, unable to check for re-arming intrusion detection" log.warn "checkForReArm: lastIntruderMotion was null, unable to check for re-arming intrusion detection"
} }
} }
private startAlarmSequence() private startAlarmSequence()
{ {
if (state.alarmActive) { if (state.alarmActive) {
log.debug "alarm already active" log.debug "alarm already active"
} }
else { else {
state.alarmActive = true state.alarmActive = true
log.debug "starting alarm sequence" log.debug "starting alarm sequence"
sendPush("Potential intruder detected!") sendPush("Potential intruder detected!")
if (newMode) { if (newMode) {
setLocationMode(newMode) setLocationMode(newMode)
} }
if (silentAlarm()) { if (silentAlarm()) {
log.debug "Silent alarm only" log.debug "Silent alarm only"
alarms?.strobe() alarms?.strobe()
if (location.contactBookEnabled) { if (location.contactBookEnabled) {
sendNotificationToContacts(textMessage ?: "Potential intruder detected", recipients) sendNotificationToContacts(textMessage ?: "Potential intruder detected", recipients)
} }
else { else {
if (phone) { if (phone) {
sendSms(phone, textMessage ?: "Potential intruder detected") sendSms(phone, textMessage ?: "Potential intruder detected")
} }
} }
} }
else { else {
def delayTime = seconds def delayTime = seconds
if (delayTime) { if (delayTime) {
alarms?.strobe() alarms?.strobe()
runIn(delayTime, "soundSiren") runIn(delayTime, "soundSiren")
log.debug "Sounding siren in $delayTime seconds" log.debug "Sounding siren in $delayTime seconds"
} }
else { else {
soundSiren() soundSiren()
} }
} }
if (lights) { if (lights) {
flashLights(Math.min((seconds/2) as Integer, 10)) flashLights(Math.min((seconds/2) as Integer, 10))
} }
} }
} }
def soundSiren() def soundSiren()
{ {
if (state.alarmActive) { if (state.alarmActive) {
log.debug "Sounding siren" log.debug "Sounding siren"
if (location.contactBookEnabled) { if (location.contactBookEnabled) {
sendNotificationToContacts(textMessage ?: "Potential intruder detected", recipients) sendNotificationToContacts(textMessage ?: "Potential intruder detected", recipients)
} }
else { else {
if (phone) { if (phone) {
sendSms(phone, textMessage ?: "Potential intruder detected") sendSms(phone, textMessage ?: "Potential intruder detected")
} }
} }
alarms?.both() alarms?.both()
if (lights) { if (lights) {
log.debug "continue flashing lights" log.debug "continue flashing lights"
continueFlashing() continueFlashing()
} }
} }
else { else {
log.debug "alarm activation aborted" log.debug "alarm activation aborted"
} }
unschedule("soundSiren") // Temporary work-around to scheduling bug unschedule("soundSiren") // Temporary work-around to scheduling bug
} }
def continueFlashing() def continueFlashing()
{ {
unschedule() unschedule()
if (state.alarmActive) { if (state.alarmActive) {
flashLights(10) flashLights(10)
schedule(util.cronExpression(now() + 10000), "continueFlashing") schedule(util.cronExpression(now() + 10000), "continueFlashing")
} }
} }
private flashLights(numFlashes) { private flashLights(numFlashes) {
def onFor = 1000 def onFor = 1000
def offFor = 1000 def offFor = 1000
log.debug "FLASHING $numFlashes times" log.debug "FLASHING $numFlashes times"
def delay = 1L def delay = 1L
numFlashes.times { numFlashes.times {
log.trace "Switch on after $delay msec" log.trace "Switch on after $delay msec"
lights?.on(delay: delay) lights?.on(delay: delay)
delay += onFor delay += onFor
log.trace "Switch off after $delay msec" log.trace "Switch off after $delay msec"
lights?.off(delay: delay) lights?.off(delay: delay)
delay += offFor delay += offFor
} }
} }
private silentAlarm() private silentAlarm()
{ {
silent?.toLowerCase() in ["yes","true","y"] silent?.toLowerCase() in ["yes","true","y"]
} }