【发布时间】:2021-12-18 22:27:27
【问题描述】:
我有一个 python3 脚本,它使用旧式蓝牙成功打开了到服务器的 RFCOMM 套接字。我正在尝试使用 dbus 完成同样的事情,这就是我正在阅读的方式,这些天你应该在 Linux 上使用蓝牙。 (这是对用 C 编写的 Linux 应用程序进行重大更改的概念验证。)
当我运行下面的脚本时,我看到了这个:
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} [] )
请注意,属性更改发生在对 ConnectProfile 的调用失败之后。我已经看到建议我应该从属性更改回调中打开一个 RFCOMM 套接字,利用连接打开的那一刻。但是服务器端(我在 github 上使用了出色的 bluez-rfcomm-example)dbus/bluez 负责创建套接字:您只需传递一个文件描述符。我希望 ConnectProfile 能够以类似方式工作,但找不到任何示例。
我应该如何修改我的 new_style() 函数以便它给我一个工作套接字?
谢谢,
--埃里克
#!/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()
(稍后添加)
让我澄清一下我的问题。在 Linux 机器上,我正在运行我修改为使用自定义服务 UUID 的 bluez-rfcomm-example 服务器。它可能会创建一个服务记录,但在客户端(Android)端,这三行 Java 足以获得一个连接的套接字(假设服务器有蓝牙 mac AA:BB:CC:DD:EE:FF 和两个成对):
BluetoothDevice remote = BluetoothAdapter.getDefaultAdapter().getRemoteDevice( "AA:BB:CC:DD:EE:FF" );
BluetoothSocket socket = remote.createRfcommSocketToServiceRecord( MY_SERVICE_UUID );
socket.connect();
有没有办法在 Linux 上使用 dbus/bluez 远程接近这个简单?我假设 Device1/ConnectProfile(UUID) 是我想要的——它与 createRfcommSocketToServiceRecord() 相同——但这种假设可能完全错误!这甚至可以从使用 blues/dbus 的 Linux 上实现吗?还是我应该坚持使用旧方法?
谢谢,对于最初含糊不清的问题,我们深表歉意。
--埃里克
【问题讨论】:
标签: python linux dbus bluez rfcomm