Sonos application

I can get sonos to play the playlist, but what is driving me crazy is it keeps playing the same order. For example I have a playlist which it set on random and to be looped. When I trigger a motion sensor in the bathroom it will press play on the sonos. When I turn off the light it stops the sonos, but it will always go back to the first song played in the playlist… after that when it resumes again it plays the same songs, in the same order!

Anyone have a way around this?

Also for anyone having troubles getting the songs to show up in Mood Music.

  • Play the playlist or track through the sonos app
  • Go into smartthings app
  • Go into the Sonos player you are playing on
  • Press the “Refresh” button within the app

It should now show the current playing song within the smartthings app and it will now show up when you go to add the “Mood Music” program.

I managed to fix my problem this morning. I went into Smartthings IDE, used the Sonos Control template and edited the “Play/Pause” function to just “Pause”. Now when I turn off a switch or leave the house the Sonos’s just pause rather than STOP so the play order will continue to be random and not start from the beginning of the playlist.

Depending on your playlist size you may need to remove it and re-add it once in awhile to refresh the play order (random & repeat).

If anyone needs help doing this let me know.

1 Like

I am also unable to get any playlist or songs to show up under the Mood Music smartapp. I noticed in the activity of the device that it was throwing an error “Cannot get Property Displayname on null object”.

I just received my v2 hub and I have been racking my brain to try to figure out how to get the sonos to play a specific playlist. Like someone above, I want a playlist to play for the dogs when I leave the house. So far I can get this to work but when I check on it later in the day it has stopped. I load up the playlist to have more than enough songs to play all day. I have to press the “paused” on the sonos in smartthings to get it to start playing again. And when I come home I would like it to change to a different playlist. However, it says “Welcome Home” and then doesn’t start again even though I have set it to continue playing after greeting. Has anybody figured this out?

That’s how I solved this.

I would like to know how you did this?

Hi @Magnustengborn, you can try this

Create a new SmartApp. Select ‘From Template’. Choose ‘Sonos Control’. Within the app change this code.

section(“Perform this action”){
input “actionType”, “enum”, title: “Action?”, required: true, defaultValue: “play”, options: [
“Play”,
“Pause”,
“Stop Playing”,
“Skip to Next Track”,
“Play Previous Track”

OK, sorry for the dumb question but I am new to this. Does this override the Sonos Control that is already in my smartthings?

No it will not… when creating the App give it a unique name "Sonos Control New’. Once you publish the App you will be able to find it on your phone under ‘Marketplace’ -> ‘SmartApps’ -> ‘My Apps’. From there you connect to your Sonos.

OK, I think I am understanding. I found this on another post that allows you to select multiple sonos. You could add this also. You just need to add the multiple: true to the following line in the code:

input “sonos”, “capability.musicPlayer”, title: “Sonos music player”, required: true, multiple: true

I cannot find the “Refresh” button mentioned by scottduggan.

I can only see one track as an option in smart things. Even if I add and play other tracks they do not appear as an option. I would like it to play a radio staion but that doesnt seem possible either!

A

I didn’t mean a ‘Refresh’ button, just to refresh your playlist within the Sonos App. If you use the default Smartthings Sonos App you need to play the songs in order for them to show up in Smartthings. I found this to be annoying so instead I have Smartthings press ‘Play’ on the Sonos when I perform an action and ‘Pause’ when I do another. By doing this whatever playlist you have in the Sonos App will never change (unless your power goes out)… BTW I have a BIG playlist set on random and repeat.

I hope this makes sense.

Sorry… I just found the thread where I wrote ‘Refresh Button’. If you go into one of your Sonos’s within the Smartthings App, under ‘Things’ you will see the Refresh Button at the bottom of the screen (below the volume control).

I’m having this same issue. Pushing the Refresh button on my Sonos speaker in ST does not show the current track. Therefore, I am unable to choose a different track or playlist.

Hey @scottduggan, it looks like the Sonos Control template is no longer available in the IDE after the latest update. Any ideas on other workarounds for the “turning off Sonos stops the music rather than pausing it” issue?

It looks like capability.musicPlayer is under active development, evidenced by the fact that the device seems to have gotten some new features in the latest version, and a new multiAttributeTile.

Hey… sorry it took so long to get back to you, I have been away. Here is the code.

/**

  • 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.
  • Sonos Control
  • Author: SmartThings
  • Date: 2013-12-10
    */
    definition(
    name: “Sonos Control Scott”,
    namespace: “smartthings”,
    author: “SmartThings”,
    description: “Play or pause your Sonos 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 Sonos 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”,
“Pause”,
“Stop Playing”,
“Skip to Next Track”,
“Play Previous Track”
]
}
section {
input “sonos”, “capability.musicPlayer”, title: “Sonos 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 "Pause":
		options ? sonos.pause(options) : sonos.pause()
		break    
	case "Stop Playing":
		options ? sonos.off(options) : sonos.off()
		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