The bluetooth on my RPi seems to be dead⊠I did not use it since a while, so I donât know what happened there, Iâll look into it.
But!
This one seems to work on my laptop. The original recype is for RPi with Pipewire, my laptop has now Debian with PW as sound server.
So slightly modified the recype.
If you have PW in your Linux box, this should work.
For me the dependencies were already installed, I did not need to apt install anything.
So what I did now (everything done as root, so append âsudoâ before the commands if you do it from your regular user account):
- put this into
/opt/pw-speaker
, for example
nano /opt/pw-speaker
#!/usr/bin/python3
# SPDX-License-Identifier: LGPL-2.1-or-later
import dbus
import dbus.service
import dbus.mainloop.glib
from gi.repository import GLib
BUS_NAME = 'org.bluez'
AGENT_INTERFACE = 'org.bluez.Agent1'
AGENT_PATH = "/speaker/agent"
A2DP = '0000110d-0000-1000-8000-00805f9b34fb'
AVRCP = '0000110e-0000-1000-8000-00805f9b34fb'
bus = None
class Rejected(dbus.DBusException):
_dbus_error_name = "org.bluez.Error.Rejected"
class Agent(dbus.service.Object):
exit_on_release = True
def set_exit_on_release(self, exit_on_release):
self.exit_on_release = exit_on_release
@dbus.service.method(AGENT_INTERFACE,
in_signature="", out_signature="")
def Release(self):
print("Release")
if self.exit_on_release:
mainloop.quit()
@dbus.service.method(AGENT_INTERFACE,
in_signature="os", out_signature="")
def AuthorizeService(self, device, uuid):
# Always authorize A2DP and AVRCP connection
if uuid in [A2DP, AVRCP]:
print("AuthorizeService (%s, %s)" % (device, uuid))
return
else:
print("Service rejected (%s, %s)" % (device, uuid))
raise Rejected("Connection rejected by user")
@dbus.service.method(AGENT_INTERFACE,
in_signature="", out_signature="")
def Cancel(self):
print("Cancel")
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
agent = Agent(bus, AGENT_PATH)
mainloop = GLib.MainLoop()
# By default Bluetooth adapter is not discoverable and there's
# a 3 min timeout
# Set it as always discoverable
adapter = dbus.Interface(bus.get_object(BUS_NAME, "/org/bluez/hci0"),
"org.freedesktop.DBus.Properties")
adapter.Set("org.bluez.Adapter1", "DiscoverableTimeout", dbus.UInt32(0))
adapter.Set("org.bluez.Adapter1", "Discoverable", True)
print("RPi speaker discoverable")
# As the RPi speaker will not have any interface, create a pairing
# agent with NoInputNoOutput capability
obj = bus.get_object(BUS_NAME, "/org/bluez")
manager = dbus.Interface(obj, "org.bluez.AgentManager1")
manager.RegisterAgent(AGENT_PATH, "NoInputNoOutput")
print("Agent registered")
manager.RequestDefaultAgent(AGENT_PATH)
mainloop.run()
Donât forget to chmod +x:
chmod +x /opt/pw-speaker
Create a systemd service as follows:
Make a file with this content in
/etc/systemd/user/speaker-agent.service
[Unit]
Description=Bluetooth speaker agent
[Service]
ExecStart=/opt/pw-speaker
[Install]
WantedBy=default.target
Make systemd know about changes, and enable this service for all users:
systemctl --global daemon-reload
systemctl --global enable speaker-agent
sed -i 's/#JustWorksRepairing.*/JustWorksRepairing = always/' /etc/bluetooth/main.conf
I rebooted, logged in, and bingo.
My phone connects to my laptop, and plays audio on the laptops speaker.
I think the sound would be routed to the headphone output when attached, I still need to confirm, this really works.
Let me know, how it goes for you