Sonos music/TV follows you around the house

So we have a Sonos Playbar hooked up to our TV in the living room, and a Sonos 3 in the kitchen (permanently grouped to the Playbar) that we sometimes unmute when cooking. Wouldn’t it be cooler if it automatically unmuted when cooking or when I walk in to grab a beer?

I’ve also been thinking - if you group all of your Sonos speakers as one, you could have your music follow you anywhere in the house, as long as they’re paired with motion detectors. Pretty baller if you ask me.

/**
 *  Sonos Unmute on Motion, Mute on No Motion
 *  Based on a couple of other templates/scripts, which I can't be bothered to dig up
 *
 *  Author: Alex Keybl
 */

definition(
    name: "Sonos on Motion",
    namespace: "alexkeybl",
    author: "alexkeybl",
    description: "Sonos unmute on motion, mute on no motion. For grouped Sonos, mostly.",
    category: "Convenience",
	iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/sonos.png",
	iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/sonos@2x.png"
	)

preferences {
	section("On motion (or lack of)...") {
		input "motions", "capability.motionSensor", multiple: true, title: "Where?", required: true
	}
	section("Mute/unmute...") {
		input "sonos", "capability.musicPlayer", multiple: true, title: "Which Sonos?", required: true
	}
	section("And off when there's been no movement for..."){
		input "minutes1", "number", title: "Minutes?", required: true
	}
}

def installed()
{
	subscribe(motions, "motion", motionHandler)
}

def updated()
{
	unsubscribe()
	subscribe(motions, "motion", motionHandler)
}

def motionHandler(evt) {
	log.debug "$evt.name: $evt.value"
	if (evt.value == "active") {
		log.debug "unmuting Sonos"
		sonos?.each {
        	it.unmute()
        }
	} else if (evt.value == "inactive") {
		runIn(minutes1 * 60, scheduleCheck, [overwrite: false])
	}
}

def scheduleCheck() {
	log.debug "schedule check"
	def is_motion = false
    def last_time = 0
    
    motions?.each {
    	if(it.currentState("motion").value != "inactive") {
    		is_motion = true
    	}
        else if(it.currentState("motion").rawDateCreated.time > last_time) {
        	last_time = it.currentState("motion").rawDateCreated.time
        }
    }

    if (is_motion == false) {
        def elapsed = now() - last_time
    	def threshold = 1000 * 60 * minutes1 - 1000
    	if (elapsed >= threshold) {
            log.debug "Motion has stayed inactive long enough since last check ($elapsed ms):  muting Sonos"
            sonos?.each {
            	it.mute()
            }
    	} else {
        	log.debug "Motion has not stayed inactive long enough since last check ($elapsed ms):  doing nothing"
        }
    } else {
    	log.debug "Motion is active, do nothing and wait for inactive"
    }
}
3 Likes

I’ve always wanted a theme song that followed me around where ever I go. I’d make a terrible ninja though.

This is extremely awesome! Sound is hard to convey over video, but I would love to see your setup!

What do you mean with “permanently grouped”?