Compare commits

..

1 Commits

Author SHA1 Message Date
정재훈
5c673e7ad7 MSA-1312: 소리남 2016-05-26 02:57:57 -05:00
8 changed files with 335 additions and 349 deletions

View File

@@ -21,7 +21,6 @@ metadata {
attribute "tamper", "enum", ["detected", "clear"]
attribute "heatAlarm", "enum", ["overheat detected", "clear", "rapid temperature rise", "underheat detected"]
fingerprint deviceId: "0x0701", inClusters: "0x5E, 0x86, 0x72, 0x5A, 0x59, 0x85, 0x73, 0x84, 0x80, 0x71, 0x56, 0x70, 0x31, 0x8E, 0x22, 0x9C, 0x98, 0x7A", outClusters: "0x20, 0x8B"
fingerprint mfr:"010F", prod:"0C02", model:"1002"
}
simulator {
//battery

View File

@@ -1,110 +0,0 @@
/**
* Hue White Ambiance Bulb
*
* Philips Hue Type "Color Temperature Light"
*
* Author: SmartThings
*/
// for the UI
metadata {
// Automatically generated. Make future change here.
definition (name: "Hue White Ambiance Bulb", namespace: "smartthings", author: "SmartThings") {
capability "Switch Level"
capability "Actuator"
capability "Color Temperature"
capability "Switch"
capability "Refresh"
command "refresh"
}
simulator {
// TODO: define status and reply messages here
}
tiles (scale: 2){
multiAttributeTile(name:"rich-control", 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", range:"(0..100)"
}
}
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2000..6500)") {
state "colorTemperature", action:"color temperature.setColorTemperature"
}
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "colorTemperature", label: '${currentValue} K'
}
standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main(["rich-control"])
details(["rich-control", "colorTempSliderControl", "colorTemp", "refresh"])
}
}
// parse events into attributes
def parse(description) {
log.debug "parse() - $description"
def results = []
def map = description
if (description instanceof String) {
log.debug "Hue Ambience Bulb stringToMap - ${map}"
map = stringToMap(description)
}
if (map?.name && map?.value) {
results << createEvent(name: "${map?.name}", value: "${map?.value}")
}
results
}
// handle commands
void on() {
log.trace parent.on(this)
sendEvent(name: "switch", value: "on")
}
void off() {
log.trace parent.off(this)
sendEvent(name: "switch", value: "off")
}
void setLevel(percent) {
log.debug "Executing 'setLevel'"
if (percent != null && percent >= 0 && percent <= 100) {
parent.setLevel(this, percent)
sendEvent(name: "level", value: percent)
sendEvent(name: "switch", value: "on")
} else {
log.warn "$percent is not 0-100"
}
}
void setColorTemperature(value) {
if (value) {
log.trace "setColorTemperature: ${value}k"
parent.setColorTemperature(this, value)
sendEvent(name: "colorTemperature", value: value)
sendEvent(name: "switch", value: "on")
} else {
log.warn "Invalid color temperature"
}
}
void refresh() {
log.debug "Executing 'refresh'"
parent.manualRefresh()
}

View File

@@ -1,2 +0,0 @@
.st-ignore
README.md

View File

@@ -1,30 +0,0 @@
# Smartsense Motion Sensor
Works with:
* [Samsung SmartThings Motion Sensor](https://shop.smartthings.com/#!/products/samsung-smartthings-motion-sensor)
## Table of contents
* [Capabilities](#capabilities)
* [Health]($health)
## Capabilities
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Motion Sensor** - can detect motion
* **Battery** - defines device uses a battery
* **Refresh** - _refresh()_ command for status updates
* **Health Check** - indicates ability to get device health notifications
## Device Health
A Category C2 motion sensor that has 120min check-in interval

View File

@@ -0,0 +1,316 @@
/**
* 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.
*
* Speaker Control
*
* Author: SmartThings
*
* Date: 2013-12-10
*/
definition(
name: "스피커 컨트롤",
namespace: "smartthings",
author: "jung`s",
description: "Play or pause your Speaker when certain actions take place in your home.",
category: "SmartThings Labs",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/sonos.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/sonos@2x.png"
)
preferences {
page(name: "mainPage", title: "Control your Speaker when something happens", install: true, uninstall: true)
page(name: "timeIntervalInput", title: "Only during a certain time") {
section {
input "starting", "time", title: "Starting", required: false
input "ending", "time", title: "Ending", required: false
}
}
}
def mainPage() {
dynamicPage(name: "mainPage") {
def anythingSet = anythingSet()
if (anythingSet) {
section("When..."){
ifSet "motion", "capability.motionSensor", title: "Motion Here", required: false, multiple: true
ifSet "contact", "capability.contactSensor", title: "Contact Opens", required: false, multiple: true
ifSet "contactClosed", "capability.contactSensor", title: "Contact Closes", required: false, multiple: true
ifSet "acceleration", "capability.accelerationSensor", title: "Acceleration Detected", required: false, multiple: true
ifSet "mySwitch", "capability.switch", title: "Switch Turned On", required: false, multiple: true
ifSet "mySwitchOff", "capability.switch", title: "Switch Turned Off", required: false, multiple: true
ifSet "arrivalPresence", "capability.presenceSensor", title: "Arrival Of", required: false, multiple: true
ifSet "departurePresence", "capability.presenceSensor", title: "Departure Of", required: false, multiple: true
ifSet "smoke", "capability.smokeDetector", title: "Smoke Detected", required: false, multiple: true
ifSet "water", "capability.waterSensor", title: "Water Sensor Wet", required: false, multiple: true
ifSet "button1", "capability.button", title: "Button Press", required:false, multiple:true //remove from production
ifSet "triggerModes", "mode", title: "System Changes Mode", required: false, multiple: true
ifSet "timeOfDay", "time", title: "At a Scheduled Time", required: false
}
}
section(anythingSet ? "Select additional triggers" : "When...", hideable: anythingSet, hidden: true){
ifUnset "motion", "capability.motionSensor", title: "Motion Here", required: false, multiple: true
ifUnset "contact", "capability.contactSensor", title: "Contact Opens", required: false, multiple: true
ifUnset "contactClosed", "capability.contactSensor", title: "Contact Closes", required: false, multiple: true
ifUnset "acceleration", "capability.accelerationSensor", title: "Acceleration Detected", required: false, multiple: true
ifUnset "mySwitch", "capability.switch", title: "Switch Turned On", required: false, multiple: true
ifUnset "mySwitchOff", "capability.switch", title: "Switch Turned Off", required: false, multiple: true
ifUnset "arrivalPresence", "capability.presenceSensor", title: "Arrival Of", required: false, multiple: true
ifUnset "departurePresence", "capability.presenceSensor", title: "Departure Of", required: false, multiple: true
ifUnset "smoke", "capability.smokeDetector", title: "Smoke Detected", required: false, multiple: true
ifUnset "water", "capability.waterSensor", title: "Water Sensor Wet", required: false, multiple: true
ifUnset "button1", "capability.button", title: "Button Press", required:false, multiple:true //remove from production
ifUnset "triggerModes", "mode", title: "System Changes Mode", required: false, multiple: true
ifUnset "timeOfDay", "time", title: "At a Scheduled Time", required: false
}
section("Perform this action"){
input "actionType", "enum", title: "Action?", required: true, defaultValue: "play", options: [
"Play",
"Stop Playing",
"Toggle Play/Pause",
"Skip to Next Track",
"Play Previous Track"
]
}
section {
input "sonos", "capability.musicPlayer", title: "Speaker music player", required: true
}
section("More options", hideable: true, hidden: true) {
input "volume", "number", title: "Set the volume volume", description: "0-100%", required: false
input "frequency", "decimal", title: "Minimum time between actions (defaults to every event)", description: "Minutes", required: false
href "timeIntervalInput", title: "Only during a certain time", description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : "incomplete"
input "days", "enum", title: "Only on certain days of the week", multiple: true, required: false,
options: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
if (settings.modes) {
input "modes", "mode", title: "Only when mode is", multiple: true, required: false
}
input "oncePerDay", "bool", title: "Only once per day", required: false, defaultValue: false
}
section([mobileOnly:true]) {
label title: "Assign a name", required: false
mode title: "Set for specific mode(s)"
}
}
}
private anythingSet() {
for (name in ["motion","contact","contactClosed","acceleration","mySwitch","mySwitchOff","arrivalPresence","departurePresence","smoke","water","button1","triggerModes","timeOfDay"]) {
if (settings[name]) {
return true
}
}
return false
}
private ifUnset(Map options, String name, String capability) {
if (!settings[name]) {
input(options, name, capability)
}
}
private ifSet(Map options, String name, String capability) {
if (settings[name]) {
input(options, name, capability)
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
subscribeToEvents()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
unschedule()
subscribeToEvents()
}
def subscribeToEvents() {
log.trace "subscribeToEvents()"
subscribe(app, appTouchHandler)
subscribe(contact, "contact.open", eventHandler)
subscribe(contactClosed, "contact.closed", eventHandler)
subscribe(acceleration, "acceleration.active", eventHandler)
subscribe(motion, "motion.active", eventHandler)
subscribe(mySwitch, "switch.on", eventHandler)
subscribe(mySwitchOff, "switch.off", eventHandler)
subscribe(arrivalPresence, "presence.present", eventHandler)
subscribe(departurePresence, "presence.not present", eventHandler)
subscribe(smoke, "smoke.detected", eventHandler)
subscribe(smoke, "smoke.tested", eventHandler)
subscribe(smoke, "carbonMonoxide.detected", eventHandler)
subscribe(water, "water.wet", eventHandler)
subscribe(button1, "button.pushed", eventHandler)
if (triggerModes) {
subscribe(location, modeChangeHandler)
}
if (timeOfDay) {
schedule(timeOfDay, scheduledTimeHandler)
}
}
def eventHandler(evt) {
if (allOk) {
def lastTime = state[frequencyKey(evt)]
if (oncePerDayOk(lastTime)) {
if (frequency) {
if (lastTime == null || now() - lastTime >= frequency * 60000) {
takeAction(evt)
}
else {
log.debug "Not taking action because $frequency minutes have not elapsed since last action"
}
}
else {
takeAction(evt)
}
}
else {
log.debug "Not taking action because it was already taken today"
}
}
}
def modeChangeHandler(evt) {
log.trace "modeChangeHandler $evt.name: $evt.value ($triggerModes)"
if (evt.value in triggerModes) {
eventHandler(evt)
}
}
def scheduledTimeHandler() {
eventHandler(null)
}
def appTouchHandler(evt) {
takeAction(evt)
}
private takeAction(evt) {
log.debug "takeAction($actionType)"
def options = [:]
if (volume) {
sonos.setLevel(volume as Integer)
options.delay = 1000
}
switch (actionType) {
case "Play":
options ? sonos.on(options) : sonos.on()
break
case "Stop Playing":
options ? sonos.off(options) : sonos.off()
break
case "Toggle Play/Pause":
def currentStatus = sonos.currentValue("status")
if (currentStatus == "playing") {
options ? sonos.pause(options) : sonos.pause()
}
else {
options ? sonos.play(options) : sonos.play()
}
break
case "Skip to Next Track":
options ? sonos.nextTrack(options) : sonos.nextTrack()
break
case "Play Previous Track":
options ? sonos.previousTrack(options) : sonos.previousTrack()
break
default:
log.error "Action type '$actionType' not defined"
}
if (frequency) {
state.lastActionTimeStamp = now()
}
}
private frequencyKey(evt) {
//evt.deviceId ?: evt.value
"lastActionTimeStamp"
}
private dayString(Date date) {
def df = new java.text.SimpleDateFormat("yyyy-MM-dd")
if (location.timeZone) {
df.setTimeZone(location.timeZone)
}
else {
df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
}
df.format(date)
}
private oncePerDayOk(Long lastTime) {
def result = true
if (oncePerDay) {
result = lastTime ? dayString(new Date()) != dayString(new Date(lastTime)) : true
log.trace "oncePerDayOk = $result"
}
result
}
// TODO - centralize somehow
private getAllOk() {
modeOk && daysOk && timeOk
}
private getModeOk() {
def result = !modes || modes.contains(location.mode)
log.trace "modeOk = $result"
result
}
private getDaysOk() {
def result = true
if (days) {
def df = new java.text.SimpleDateFormat("EEEE")
if (location.timeZone) {
df.setTimeZone(location.timeZone)
}
else {
df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
}
def day = df.format(new Date())
result = days.contains(day)
}
log.trace "daysOk = $result"
result
}
private getTimeOk() {
def result = true
if (starting && ending) {
def currTime = now()
def start = timeToday(starting, location?.timeZone).time
def stop = timeToday(ending, location?.timeZone).time
result = start < stop ? currTime >= start && currTime <= stop : currTime <= stop || currTime >= start
}
log.trace "timeOk = $result"
result
}
private hhmm(time, fmt = "h:mm a")
{
def t = timeToday(time, location.timeZone)
def f = new java.text.SimpleDateFormat(fmt)
f.setTimeZone(location.timeZone ?: timeZone(time))
f.format(t)
}
private timeIntervalLabel()
{
(starting && ending) ? hhmm(starting) + "-" + hhmm(ending, "h:mm a z") : ""
}
// TODO - End Centralize

View File

@@ -323,8 +323,6 @@ private getDeviceType(hueType) {
return "Hue Bulb"
else if (hueType?.equalsIgnoreCase("Color Light"))
return "Hue Bloom"
else if (hueType?.equalsIgnoreCase("Color Temperature Light"))
return "Hue White Ambiance Bulb"
else
return null
}

View File

@@ -107,8 +107,8 @@ mappings {
path("/locks") {
action: [
GET: "listLocks",
PUT: "updateLocks",
POST: "updateLocks"
PUT: "updateLock",
POST: "updateLock"
]
}
path("/locks/:id") {
@@ -442,87 +442,31 @@ def executePhrase() {
}
private void updateAll(devices) {
def type = params.param1
def command = request.JSON?.command
if (!devices) {
httpError(404, "Devices not found")
}
if (command){
devices.each { device ->
executeCommand(device, type, command)
}
if (command)
{
command = command.toLowerCase()
devices."$command"()
}
}
private void update(devices) {
log.debug "update, request: ${request.JSON}, params: ${params}, devices: $devices.id"
def type = params.param1
def command = request.JSON?.command
def device = devices?.find { it.id == params.id }
if (!device) {
//def command = request.JSON?.command
def command = params.command
if (command)
{
command = command.toLowerCase()
def device = devices.find { it.id == params.id }
if (!device)
{
httpError(404, "Device not found")
}
else
{
device."$command"()
}
}
if (command) {
executeCommand(device, type, command)
}
}
/**
* Validating the command passed by the user based on capability.
* @return boolean
*/
def validateCommand(device, deviceType, command) {
def capabilityCommands = getDeviceCapabilityCommands(device.capabilities)
def currentDeviceCapability = getCapabilityName(deviceType)
if (capabilityCommands[currentDeviceCapability]) {
return command in capabilityCommands[currentDeviceCapability] ? true : false
} else {
// Handling other device types here, which don't accept commands
httpError(400, "Bad request.")
}
}
/**
* Need to get the attribute name to do the lookup. Only
* doing it for the device types which accept commands
* @return attribute name of the device type
*/
def getCapabilityName(type) {
switch(type) {
case "switches":
return "Switch"
case "locks":
return "Lock"
default:
return type
}
}
/**
* Constructing the map over here of
* supported commands by device capability
* @return a map of device capability -> supported commands
*/
def getDeviceCapabilityCommands(deviceCapabilities) {
def map = [:]
deviceCapabilities.collect {
map[it.name] = it.commands.collect{ it.name.toString() }
}
return map
}
/**
* Validates and executes the command
* on the device or devices
*/
def executeCommand(device, type, command) {
if (validateCommand(device, type, command)) {
device."$command"()
} else {
httpError(403, "Access denied. This command is not supported by current capability.")
}
}
private show(devices, type) {

View File

@@ -1,129 +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.
*
* Alfred Workflow
*
* Author: SmartThings
*/
definition(
name: "김신동",
namespace: "vlaminck",
author: "SmartThings",
description: "This SmartApp allows you to interact with the things in your physical graph through Alfred.",
category: "Convenience",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/alfred-app.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/alfred-app@2x.png",
oauth: [displayName: "SmartThings Alfred Workflow", displayLink: ""]
)
preferences {
section("Allow Alfred to Control These Things...") {
input "switches", "capability.switch", title: "Which Switches?", multiple: true, required: false
input "locks", "capability.lock", title: "Which Locks?", multiple: true, required: false
}
}
mappings {
path("/switches") {
action: [
GET: "listSwitches",
PUT: "updateSwitches"
]
}
path("/switches/:id") {
action: [
GET: "showSwitch",
PUT: "updateSwitch"
]
}
path("/locks") {
action: [
GET: "listLocks",
PUT: "updateLocks"
]
}
path("/locks/:id") {
action: [
GET: "showLock",
PUT: "updateLock"
]
}
}
def installed() {}
def updated() {}
def listSwitches() {
switches.collect { device(it,"switch") }
}
void updateSwitches() {
updateAll(switches)
}
def showSwitch() {
show(switches, "switch")
}
void updateSwitch() {
update(switches)
}
def listLocks() {
locks.collect { device(it, "lock") }
}
void updateLocks() {
updateAll(locks)
}
def showLock() {
show(locks, "lock")
}
void updateLock() {
update(locks)
}
private void updateAll(devices) {
def command = request.JSON?.command
if (command) {
devices."$command"()
}
}
private void update(devices) {
log.debug "update, request: ${request.JSON}, params: ${params}, devices: $devices.id"
def command = request.JSON?.command
if (command) {
def device = devices.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device."$command"()
}
}
}
private show(devices, name) {
def device = devices.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
}
else {
def s = device.currentState(name)
[id: device.id, label: device.displayName, name: device.displayName, state: s]
}
}
private device(it, name) {
if (it) {
def s = it.currentState(name)
[id: it.id, label: it.displayName, name: it.displayName, state: s]
}
}