mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-09 13:21:53 +00:00
This version uses OAuth to simplify the setup process. It also uses child apps to make it easy for users to find the apps that work well with the devices. Please email me when you are testing and I can send a beta version of the Mac app to the tester(s).
314 lines
11 KiB
Groovy
314 lines
11 KiB
Groovy
/**
|
|
* obything Trigger Playlist
|
|
*
|
|
* Author: obycode
|
|
* Date: 2015-11-05
|
|
*/
|
|
|
|
import groovy.json.JsonSlurper
|
|
|
|
definition(
|
|
name: "obything Trigger Playlist",
|
|
namespace: "com.obycode",
|
|
author: "obycode, based on Sonos Mood Music by SmartThings",
|
|
description: "Plays a selected playlist on your Mac with obything",
|
|
category: "Convenience",
|
|
iconUrl: "http://obything.obycode.com/icons/obything-device.png",
|
|
iconX2Url: "http://obything.obycode.com/icons/obything-device.png"
|
|
)
|
|
|
|
preferences {
|
|
page(name: "mainPage", title: "Choose the trigger(s)", nextPage: "chooseTrackAndSpeakers", uninstall: true)
|
|
page(name: "chooseTrackAndSpeakers", title: "Choose the playlist and speaker(s)", 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("Play music 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
|
|
ifSet "triggerModes", "mode", title: "System Changes Mode", required: false, multiple: true
|
|
ifSet "timeOfDay", "time", title: "At a Scheduled Time", required: false
|
|
}
|
|
}
|
|
|
|
def hideable = anythingSet || app.installationState == "COMPLETE"
|
|
def sectionTitle = anythingSet ? "Select additional triggers" : "Play music when..."
|
|
|
|
section(sectionTitle, hideable: hideable, 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
|
|
ifUnset "triggerModes", "mode", title: "System Changes Mode", required: false, multiple: true
|
|
ifUnset "timeOfDay", "time", title: "At a Scheduled Time", required: false
|
|
}
|
|
section {
|
|
input "obything", "capability.musicPlayer", title: "On this obything music player", required: true
|
|
}
|
|
section("More options", hideable: true, hidden: true) {
|
|
input "volume", "number", title: "Set the 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: ["Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
|
|
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
|
|
}
|
|
}
|
|
}
|
|
|
|
def chooseTrackAndSpeakers() {
|
|
dynamicPage(name: "chooseTrackAndSpeakers") {
|
|
section {
|
|
input "playlist", "enum", title:"Play this playlist", required:true, multiple: false, options: playlistOptions()
|
|
input "speakers", "enum", title:"On these speakers", required:false, multiple: true, options: speakerOptions()
|
|
}
|
|
section([mobileOnly:true]) {
|
|
label title: "Assign a name", required: false
|
|
mode title: "Set for specific mode(s)", required: false
|
|
}
|
|
}
|
|
}
|
|
|
|
private playlistOptions() {
|
|
def playlistString = obything.currentValue("playlists")
|
|
log.debug "Playlists are $playlistString"
|
|
def jsonList = new JsonSlurper().parseText(playlistString)
|
|
log.debug("jsonList is $jsonList")
|
|
jsonList.collect {
|
|
it.name
|
|
}
|
|
}
|
|
|
|
def chooseSpeakers() {
|
|
dynamicPage(name: "chooseSpeakers") {
|
|
section{
|
|
input "speakers", "enum", title:"Play on these speakers", required:false, multiple: true, options: speakerOptions()
|
|
}
|
|
section([mobileOnly:true]) {
|
|
label title: "Assign a name", required: false
|
|
mode title: "Set for specific mode(s)", required: false
|
|
}
|
|
}
|
|
}
|
|
|
|
private speakerOptions() {
|
|
def speakersString = obything.currentValue("speakers")
|
|
log.debug "Speakers are $speakersString"
|
|
def slurper = new JsonSlurper()
|
|
slurper.parseText(speakersString)
|
|
}
|
|
|
|
private anythingSet() {
|
|
for (name in ["motion","contact","contactClosed","acceleration","mySwitch","mySwitchOff","arrivalPresence","departurePresence","smoke","water","button1","timeOfDay","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) {
|
|
runDaily(timeOfDay, scheduledTimeHandler)
|
|
}
|
|
}
|
|
|
|
def eventHandler(evt) {
|
|
log.debug "In eventHandler"
|
|
if (allOk) {
|
|
if (frequency) {
|
|
def lastTime = state[frequencyKey(evt)]
|
|
if (lastTime == null || now() - lastTime >= frequency * 60000) {
|
|
takeAction(evt)
|
|
}
|
|
}
|
|
else {
|
|
takeAction(evt)
|
|
}
|
|
}
|
|
}
|
|
|
|
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.info "Playing '$playlist'"
|
|
def speakerString
|
|
if (speakers) {
|
|
speakerString = ""
|
|
speakers.each {
|
|
speakerString += "\"$it\","
|
|
}
|
|
// remove the last comma and encode
|
|
speakerString = encode(speakerString[0..-2])
|
|
}
|
|
obything.playPlaylist(encode(playlist), speakerString, volume)
|
|
|
|
if (frequency || oncePerDay) {
|
|
state[frequencyKey(evt)] = now()
|
|
}
|
|
}
|
|
|
|
private frequencyKey(evt) {
|
|
"lastActionTimeStamp"
|
|
}
|
|
|
|
private encode(text) {
|
|
return URLEncoder.encode(text).replaceAll("\\+", "%20")
|
|
}
|
|
|
|
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 = 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).time
|
|
def stop = timeToday(ending).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") : ""
|
|
}
|