Audio Handoff with Sonos Speakers

With Apple’s introduction of the HomePod Mini they touted a feature which lets you hand-off music and audio between iPhone to your HomePod simply by bringing your iPhone close. A handy feature to have!

(Video clip credit to Marques Brownlee)

But what if you don’t own a HomePod and instead use other Airplay 2 speakers such as Sonos’. Well with Shortcuts, NFC tags, and Home Assistant we can recreate the same feature!

This tutorial should work provided you have:

  1. An iPhone XS and later – Earlier iPhone’s do not support background tag reading and as such require you to open an NFC scanning app. It’s still possible to follow this tutorial, but the major benefit of always being able to transfer audio without extra steps will be lost for older phones.
  2. The iOS Shortcuts app – App store download can be found here.
  3. NFC tags or stickers – Depending on your use case, NFC tags can be bought as stickers or as plastic cards. For this setup, I prefer using the stickers. Check for compatibility with iPhone’s before purchasing. If they are NTAG215 tags they should work fine with iPhone’s.
  4. An Airplay 2 compatible speaker – Unfortunately in the iOS Shortcuts app, switching the audio source only allows Airplay 2 compatible devices (e.g. Sonos speakers and Apple TV’s). Fortunately, most of the newer Sonos speakers are Airplay 2 compatible!
  5. Home Assistant – The music/audio handoff feature will work to transfer music from your iPhone to Home Assistant, however, to transfer music back, I’ve used Home Assistant. I believe there are other ways to achieve this feature, however, they likely involve a paid iOS app or storing variables in iCloud documents or Notes. I think my solution is the simplest if you are already are running Home Assistant.

Step-by-Step Guide

I will make the assumption that you are already running Home Assistant. If you aren’t, then there are many guides to get started!

Adding Sonos speakers to Home Assistant can be done through the UI, under the Integration tab. More information can be found on the Home Assistant Sonos Integration Page.

For this guide I’ve used Sonos speakers. This guide should also work for other Airplay 2 compatible devices however.

First, we are going to create input booleans for each of our speakers to track if the speaker is playing or idle. I have two Sonos speakers, my Kitchen Sonos, and my Living Room Sonos. Therefore, for my home, in the Home Assistant configuration.yaml file,

input_boolean:
  kitchen_sonos_status:
    name: "Kitchen Sonos Play Status"
    initial: off
  livingroom_sonos_status:
    name: "Living Room Sonos Play Status"
    initial: off

Save and reload the input booleans under, Configuration > Server Controls > Reload Input Booleans

Next, we need to add our input booleans to Homekit. If you’ve already added the HomeKit Bridge integration to your iPhone, then simply expose the newly created booleans to the HomeKit Bridge. Otherwise, in configuration.yaml,

homekit:
  filter:
    include_entities:
      - input_boolean.kitchen_sonos_status
      - input_boolean.livingroom_sonos_status

This will let us track both of those entities in HomeKit. To add the HomeKit Bridge to the iOS Home App, you can follow the instructions found here.

If all went well, you should see your new entities in the Home app on your iPhone:

We need to keep track of the state of the speakers, depending on if they are playing audio or on standby/idle. I’ve created the automation in Node-RED, however I am sure that this automation can be achieved through the built in Automation editor in Home Assistant.

Essentially, if the speaker’s state is “playing”, then turn on the input boolean created in the previous step. And, if the state is anything but “playing” then turn off the input boolean.

The automation in Node-RED is shown below. In this example, my kitchen speaker’s media name is “Symfonisk”.

[{"id":"e6fac9d2.9de47","type":"server-state-changed","z":"63748c50.3ec924","name":"Kitchen Speaker","server":"","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"media_player.symfonisk","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"playing","halt_if_type":"str","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"x":160,"y":1660,"wires":[["c478a5cd.ae77c8"],["b2ffaab5.f98f08"]]},{"id":"c478a5cd.ae77c8","type":"api-call-service","z":"63748c50.3ec924","name":"Sonos Status - ON","server":"","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_on","entityId":"input_boolean.portable_sonos_status","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":370,"y":1620,"wires":[[]]},{"id":"b2ffaab5.f98f08","type":"api-call-service","z":"63748c50.3ec924","name":"Sonos Status - OFF","server":"","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_off","entityId":"input_boolean.portable_sonos_status","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":380,"y":1700,"wires":[[]]},{"id":"e7f76522.c1a328","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false,"cacheJson":true}]

Finally, we need to create an iOS Shortcut to trigger the audio handoff when we scan the NFC tag. I’ve included the link to install the Shortcut which you can find here.

I’ll walk through the Shortcut however, the only section you should have to modify is the if statement to change it from “Kitchen Sonos” to the input boolean created for your own speaker:

  • The text (1) here is actually an mp3 audio file that has been converted to Base64. This lets us decode (2) and play it as a custom sound in our Shortcut. Its not necessary to include this audio, but I appreciate the sound that’s played to let me know that the audio has been handed off.
  • The if statement (3) is where we check if the speaker is playing audio. If the Sonos is playing audio than the input boolean and entity in our Home will be on. Therefore when the Shortcut is run, it will switch the playback destination to our iPhone (a).
  • And, if the input boolean and entity is off, then the Sonos speaker is idle, and we will transfer the playback destination from our iPhone to the speaker, which in this case, is named Portable (b).

Now, in the Shortcuts app, we can create a Personal Automation, set the trigger to NFC, scan the NFC tag we want to associate to the speaker, and set “Run Shortcut” to run the “Sonos Handoff” shortcut I linked above.

Create a Personal Automation
Set the trigger to NFC and scan your NFC tag
Set the NFC scan to “Run Shortcut” for the Sonos Handoff Shortcut and disable “Ask Before Running”

In my case, using the IKEA Symfonisk speaker, it has a removable front grill. I can remove that grill, stick the NFC sticker to the backside, and then replace it. Now, when I bring my phone close to the speaker controls, it automatically hands off the music. And, if the music is playing on the speaker and I bring my phone close, it transfers back to my phone!

The NFC sticker fits nicely behind the speaker grill
And is completely invisible once the grill is reattached

That’s it!

By utilizing the Airplay playback destination feature, the audio does not only have to be a music source. If you’re listening to a podcast for example, you can easily transfer the audio from your phone to your speaker. I’ve been using this setup for a little while now and its been working really reliably with a surprisingly fast audio handoff speed.

Let me know of other NFC implementations, or, if you’re looking for my DIY projects, how about building your own smart motorized shades?