I have a python3 script that successfully opens a RFCOMM socket to a server using old-style bluetooth. I'm trying to accomplish the same thing using dbus, which is the way I'm reading you're supposed to use bluetooth on Linux these days. (This is a proof-of-concept for significant changes to be made to a Linux app written in C.)
When I run the script below I see this:
connecting...
ex from ConnectProfile(): g-io-error-quark: GDBus.Error:org.bluez.Error.NotAvailable: Operation currently not available (36)
onPropertiesChanged( org.bluez.Device1 {'Connected': True} [] )
onPropertiesChanged( org.bluez.Device1 {'ServicesResolved': True} [] )
onPropertiesChanged( org.bluez.Device1 {'ServicesResolved': False, 'Connected': False} [] )
Note that the property changes happen after the call to ConnectProfile fails. I've seen suggestions that I should be opening an RFCOMM socket from inside the property-changed callback, taking advantage of the moment when the connection is open. But server-side (I'm using the excellent bluez-rfcomm-example on github) dbus/bluez takes care of creating the socket: you just get passed a file descriptor. I'm expecting ConnectProfile to work similarly, but can't find any examples.
How should I modify my new_style() function so that it gives me a working socket?
Thanks,
--Eric
#!/usr/bin/env python3
# for new_style()
from pydbus import SystemBus
from gi.repository import GLib
# for old_style()
import bluetooth
PROFILE = 'b079b640-35fe-11e5-a432-0002a5d5c51b'
ADDR = 'AA:BB:CC:DD:EE:FF'
# Works fine. But you're supposed to use dbus these days
def old_style():
service_matches = bluetooth.find_service(uuid=PROFILE, address=ADDR)
if len(service_matches):
first_match = service_matches[0]
port = first_match['port']
host = first_match['host']
sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
sock.connect((host, port))
while True:
data = input()
if not data:
break
sock.send(data)
sock.close()
# Does not work. First an exception fires:
# g-io-error-quark: GDBus.Error:org.bluez.Error.NotAvailable: Operation currently not available (36)
# then onPropertiesChanged lists stuff -- after the failure, not during the connection attempt.
def new_style():
nucky = SystemBus().get('org.bluez', '/org/bluez/hci0/dev_' + ADDR.replace(':', '_'))
# Callback: (s, a{sv}, as)
nucky.onPropertiesChanged = lambda p1, p2, p3: print('onPropertiesChanged(', p1, p2, p3, ')')
def try_connect():
print('connecting...')
try:
nucky.ConnectProfile(PROFILE)
except Exception as ex:
print('ex from ConnectProfile():', ex)
GLib.timeout_add( 250, try_connect )
GLib.MainLoop().run()
if False:
old_style()
else:
new_style()
(Added later)
Let me clarify my question. On a Linux box I'm running a bluez-rfcomm-example server that I modified to use a custom Service UUID. It probably creates a service record, but on the client (Android) side these three lines of Java are enough to get a connected socket to it (assuming the server has bluetooth mac AA:BB:CC:DD:EE:FF and the two are paired):
BluetoothDevice remote = BluetoothAdapter.getDefaultAdapter().getRemoteDevice( "AA:BB:CC:DD:EE:FF" );
BluetoothSocket socket = remote.createRfcommSocketToServiceRecord( MY_SERVICE_UUID );
socket.connect();
Is there a way to do this on Linux using dbus/bluez that is remotely close to this simple? I'm assuming Device1/ConnectProfile(UUID) is what I want -- that it's the same thing as createRfcommSocketToServiceRecord() -- but that assumption might be totally wrong! Should this even be possible from Linux using blues/dbus? Or should I stick with the older methods?
Thanks, and sorry for the vague initial question.
--Eric
There is a good (if slightly old now) blog comparing pybluez and using Python 3 sockets: https://blog.kevindoran.co/bluetooth-programming-with-python-3/
If you want to do it with the BlueZ D-Bus API then the key documentations is: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/profile-api.txt
And the BlueZ example is at: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/test-profile
Creating this with pydbus has some issues as documented at: https://github.com/LEW21/pydbus/issues/54