micro-nova / AmpliPi

Whole House Audio System 🔊
https://amplipi.com
GNU General Public License v3.0
288 stars 23 forks source link

Feature: Add Bluetooth support #150

Closed linknum23 closed 11 months ago

linknum23 commented 3 years ago

How should Bluetooth support be added to AmpliPi?

linknum23 commented 3 years ago

@vszander has started working on integrating Bluetooth audio into AmpliPi, here's his question (with minor edits):

I was able to stream Bluetooth audio from my smart phone to my AmpliPi dev image using this method which is compatible with ALSA. The Bluetooth stream is going to the default channel on the soundcard. How can we make the Bluetooth stream an AmpliPi input?

linknum23 commented 3 years ago

First of all thanks for looking into this, @vszander! Based on how streams currently work it looks like you will want to test this by launching bluealsa-aplay from the command line on your pi (assuming you have already installed it). Looking at the docs for bluealsa-aplay it looks like you just need to specify the ALSA device using the -D flag, so you may want to test using bluealsa-aplay -D ch0 (and ch1, ch2...). Try it out and see how it works for you (and report back your findings).

kjk2010 commented 3 years ago

I was playing around with this today and have it working on my Pi 2b with a USB bluetooth adapter, outputting through ALSA to ch0/ch1/ch2/ch3. I think it would be easy to create a simple AmpliPi stream for this, and could quickly get more complicated if someone wanted to control specific Bluetooth devices or run multiple Bluetooth streams at once. Here is the information I used and how I configured it:

Setup Guide: https://gist.github.com/Pindar/e259bec5c3ab862f4ff5f1fbcb11bfc1 Controlling Bluetooth and Metadata: https://scribles.net/controlling-bluetooth-audio-on-raspberry-pi/ Bluealsa - Available Features (aac, apt-x): https://github.com/Arkq/bluez-alsa/wiki/Installation-from-source

INSTALL:

sudo apt-get install bluealsa python-dbus libasound2-dev

SETUP (these services should only be running when the AmpliPi stream is active):

sudo systemctl disable bluetooth sudo systemctl disable bluealsa

Edit /etc/bluetooth/main.conf:

Name = AmpliPi Bluetooth DiscoverableTimeout = 0 Class = 0x200400

Set up A2DP Bluetooth Agent for headless bluetooth discovery

https://gist.github.com/Pindar/e259bec5c3ab862f4ff5f1fbcb11bfc1#install-the-a2dp-bluetooth-agent

START (when the AmpliPi stream is started, run these in this order):

sudo systemctl start bluetooth sudo systemctl start bluealsa sudo systemctl start bt-agent-a2dp.service # This service is used to automatically allow bluetooth devices to connect) bluealsa-aplay -d ch0 00:00:00:00:00:00 # This is the process that takes the audio from bluetooth and sends to ALSA via -d. The 00:00... allows for any bluetooth device. Maybe this could be used to send different bluetooth devices out different AmpliPi outputs?

STOP (when AmpliPi stream is stopped, run these in this order):

kill bluealsa-aplay sudo systemctl stop bt-agent-a2dp.service sudo systemctl stop bluealsa sudo systemctl stop bluetooth

linknum23 commented 3 years ago

Is there a specific reason all of those Bluetooth services need to be stopped and started every time a Bluetooth stream is connected? Is this just so that we can have control over the name to connect to? Or maybe the security issue of always allowing any Bluetooth device to connect?

Here's what I am hoping the workflow for Bluetooth devices would look like:

Also as a side note, I'm guessing those of you that are using Bluetooth will be using a module with a nice antenna to get extra range? I was just looking at this: https://www.amazon.com/dp/B08LVH5BCP, maybe we should buy one and test it out around Jason's house.,.

kjk2010 commented 3 years ago

My reasoning behind starting and stopping the services is that my phone will stay connected to the RPi's Bluetooth and continue streaming audio, even though bluealsa-aplay isn't running. At least in my use case, I would only want my phone to connect to Bluetooth on the AmpliPi when one of the sources has a Bluetooth stream running, then disconnect from it when the stream has been stopped. It might be possible to script something with bluetoothctl to allow and drop connected devices when a stream is activated and deactivated, but I'm not sure.

I don't believe it's a security issue leaving the services running and automatically accepting connections, as long as the Class setting is set to 0x200400 which says only audio devices can connect (http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html).

I like the look of that Bluetooth adapter. I do plan on using one like that instead of my current tiny dongle that only reaches 10ft.

linknum23 commented 3 years ago

I think that use case makes the most sense. Is there anyway to enable/disable a single Bluetooth device, instead of the whole service? That could potentially simplify things here and also provide a longer term route to support 2 or more Bluetooth devices/streams.

kjk2010 commented 3 years ago

The bluetoothctl has the ability to disconnect devices, but then they'll automatically reconnect at some point. There are also trust/untrust options, as well as block/unblock options, but then you have to deal with finding specific device IDs for the commands.

One potential option might be to turn the Bluetooth power on and off using bluetoothctl: bluetoothctl -- power off bluetoothctl -- power on

This would disconnect active Bluetooth connections when power is off, and allow them to reconnect when power is back on. All the background services can stay running.

On Mon, Aug 16, 2021 at 7:54 AM Lincoln Lorenz @.***> wrote:

I think that use case makes the most sense. Is there anyway to enable/disable a single Bluetooth device, instead of the whole service? That could potentially simplify things here and also provide a longer term route to support 2 or more Bluetooth devices/streams.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/micro-nova/AmpliPi/issues/150#issuecomment-899576681, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKNOZ24BJWOBPSUSLQO3EQDT5ERDJANCNFSM5BI7IS2A . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .

--

KJ Koning Shout! Radio Services http://www.shoutservices.com

linknum23 commented 3 years ago

Please forgive me if I messed something up here as I don't have a Bluetooth device connected to AmpliPi to test with.

  1. Doesn't the device name already exist in some paired devices list, since it needs to be paired with the Rpi's Bluetooth? We could expose this device list in the API to build a drop down, in addition to having some way indicate a wildcard device.
  2. If you gracefully signal the bluealsa-aplay process (e.g. via Ctrl-c), does it disconnect from your phone/Bluetooth-audio-source?

I'm still trying to reduce the complexity of starting and stopping the Bluetooth stack here...

kjk2010 commented 3 years ago
  1. Yes. sudo bluetoothctl devices will provide a list of paired devices, connected or not. You can use the device ID to query the status of the device itself: sudo bluetoothctl info 01:23:45:67:89:01 - Name: moto g(7) power Alias: moto g(7) power Class: 0x005a020c Icon: phone Paired: yes Trusted: no Blocked: no Connected: yes LegacyPairing: no UUID: OBEX Object Push (00001105-0000-1000-8000-00805f9b34fb) UUID: Audio Source (0000110a-0000-1000-8000-00805f9b34fb) UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb) UUID: Advanced Audio Distribu.. (0000110d-0000-1000-8000-00805f9b34fb) UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb) UUID: Headset AG (00001112-0000-1000-8000-00805f9b34fb) UUID: PANU (00001115-0000-1000-8000-00805f9b34fb) UUID: NAP (00001116-0000-1000-8000-00805f9b34fb) UUID: Handsfree Audio Gateway (0000111f-0000-1000-8000-00805f9b34fb) UUID: Phonebook Access Server (0000112f-0000-1000-8000-00805f9b34fb) UUID: Message Access Server (00001132-0000-1000-8000-00805f9b34fb) UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb) UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb) UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb) Modalias: bluetooth:v001Dp1200d1436

Unfortunately, it doesn't have a single command to return the status, and I haven't been able to get a bash single line command to work, although it should be possible (none of these worked for me: https://superuser.com/questions/1500383/bluetoothctl-list-connected-devices)

  1. Gracefully stopping bluealsa-aplay does not disconnect the phone's bluetooth connection or the phone's bluetooth audio source, so (at least in my single test) my phone continues to play music as if it's connected. It does this without starting bluealsa-aplay too. I can envision a script that starts and stops bluealsa-aplay and also connects/disconnects devices or powers on/off the Bluetooth adapter, depending on the desired behavior.

On Mon, Aug 16, 2021 at 12:37 PM Lincoln Lorenz @.***> wrote:

Please forgive me if I messaged something up here as I don't have a Bluetooth device connected to AmpliPi to test with.

  1. Doesn't the device name already exist in some paired devices list, since it needs to be paired with the Rpi's Bluetooth? We could expose this device list in the API to build a drop down, in addition to having some way indicate a wildcard device.
  2. If you gracefully signal the bluealsa-aplay process (e.g. via Ctrl-c), does it disconnect from your phone/Bluetooth-audio-source?

I'm still trying to reduce the complexity of starting and stopping the Bluetooth stack here...

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/micro-nova/AmpliPi/issues/150#issuecomment-899768054, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKNOZ2ZU2PJ4C7M4COOJGXDT5FSI3ANCNFSM5BI7IS2A . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .

--

KJ Koning Shout! Radio Services http://www.shoutservices.com

bs42 commented 3 years ago

A vote for supporting more than 1 Bluetooth stream.

Scenario: 2 kids each with a set of ceiling speakers in their rooms.

I was planning to get a pair of BT to RCA devices to handle this, but if it could be done directly on the device with a BT dongle instead of using up RCA inputs that would be fantastic!

vszander commented 3 years ago

Sorry I dropped off line recently....
I love kjk2010's suggested approach. Unfortunately, I was unable to implement - but I didn't take time to MAKE the suggested driver. I also like supporting multiple bluetooth. @kjk2010 , super writeup !

kjk2010 commented 3 years ago

I've set up basic Bluetooth support on my dev Pi, and the good news is it can support at least 2 active streams to different zones using a single Bluetooth dongle. I still have to figure out how to handle disconnecting devices when the Bluetooth stream isn't active, reconnecting when it is active, pairing new devices, and the possibility of accessing metadata and using remote controls (next,.prev, start, pause).

linknum23 commented 3 years ago

@kjk2010 We are getting a long range Bluetooth adapter tomorrow, Let us know if there's anything you would like help with.

bs42 commented 2 years ago

I had a thought today, this would be a low priority item but it could be really useful to have bluetooth output as an option.

Use case: I have a yamaha receiver running a room with 7ch speakers and want to sync that up with the music playing in the rest of the house and bluetooth is something built into that receiver which could be a way to accomplish that link other than trying to run a set of RCA cables through the walls to get them over to the AmpliPi and take up one of it's outputs.

linknum23 commented 2 years ago

I haven't fully thought through how to handle extra outputs, one limitation of the current design of AmpliPi would only be able to support this for digital/streaming input sources. That said Bluetooth would be a pretty cool way to support this. Another way to integrate with smart receivers would be with DLNA.

kjkoning commented 1 year ago

I've put together a basic, but fully-functioning Bluetooth stream example here: https://github.com/kjkoning/amplipi-bluetooth-example It requires a USB Bluetooth dongle. I'm using this one on my AmpliPi: https://www.amazon.com/gp/product/B08LVH5BCP/, but it should work with any Linux-compatible adapter.

I'm curious for any feedback, both on if it works at all for others, and if the way it works makes sense and is user-friendly. If this is something worthy of a PR to include in a future version, there will need to be some work on making sure a Bluetooth adapter is installed and working before allowing the Bluetooth stream to be selected.

linknum23 commented 1 year ago

Awesome! We'll try integrating this and see where it goes. I think the combination of this and our initial start on bluetooth here will hopefully get us -pretty far.

jonahshader commented 1 year ago

@kjkoning I'm trying out your code and I can connect and play music to the Bluetooth stream successfully! Did you also get the media controls working? For me, bluetooth.py is crashing because the dbus module doesn't exist for some reason, which is needed by dbus_tools in bluezero. I have python-dbus/python3-dbus installed so the dbus module should exist.

jonahshader commented 1 year ago

Ah I fixed it. The packages were only in the venv, so I had to change the subprocess launches to use the venv instead of python3.

linknum23 commented 1 year ago

We added a prerelease with Bluetooth support. Check it out at https://github.com/micro-nova/AmpliPi/releases/tag/0.2.1-bluetooth-beta.0

linknum23 commented 1 year ago

Has anyone had a chance to evaluate this? We haven't gotten any feedback yet...

rwarner commented 1 year ago

Was just looking into bluetooth to add onto the AmpliPi and stumbled across this feature thread.

I already ordered a bluetooth receiver and some RCA cables because the distance from the unit to my need of bluetooth might not cover it. But, a USB extension may assist in that regard and not have the need for either and not need to power another entity.

Would I lose my settings switching to the pre-release bluetooth support build and/or if I wanted to switch off of it? Not sure when you guys were looking to fold it into the future 0.2.2+

linknum23 commented 1 year ago

You won't lose your settings. The forward migration should work fine. If anything its going back to the 0.2.1 release where you might? have some issues. I would back up your config before grabbing the Bluetooth pre release. That way you can roll back to that if you decide to go back to 0.2.1 before we make a new release.

On Thu, Aug 3, 2023, 16:27 Ryan Warner @.***> wrote:

Was just looking into bluetooth to add onto the AmpliPi and stumbled across this feature thread.

I ordered already ordered a bluetooth receiver and some RCA cables because the distance from the unit to my need of bluetooth might not cover it. But, a USB extension may assist in that regard.

Would I lose my settings switching to the pre-release bluetooth support build and/or if I wanted to switch off of it? Not sure when you guys were looking to fold it into the future 0.2.2+

— Reply to this email directly, view it on GitHub https://github.com/micro-nova/AmpliPi/issues/150#issuecomment-1664604605, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEZPO5FRECUWIGVZVKTAU3XTQCSDANCNFSM5BI7IS2A . You are receiving this because you authored the thread.Message ID: @.***>

kjkoning commented 1 year ago

I've been using the prerelease, and it's working well. No issues to report yet.

linknum23 commented 1 year ago

Sweet. It will be integrated in our 0.3.0 release coming in the next week or so.

On Sun, Sep 3, 2023, 15:11 kjkoning @.***> wrote:

I've been using the prerelease, and it's working well. No issues to report yet.

— Reply to this email directly, view it on GitHub https://github.com/micro-nova/AmpliPi/issues/150#issuecomment-1704379017, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEZPOYQXI25BGVL6ZOQN33XYTI7DANCNFSM5BI7IS2A . You are receiving this because you authored the thread.Message ID: @.***>