我正在尝试构建一个Qt应用程序,用于在Linux设备上配对/连接蓝牙设备。我正在使用BlueZ API(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc)over D-Bus,如BlueZ官方网站(http://www.bluez.org/page/8/)中所述。
一般程序如下所述:
https://www.kynetics.com/docs/2018/pairing_agents_bluez/
目前,我可以使用api来配对/连接设备,没有问题。
但我不知道如何使用配对代理。
我正试着按照这里指出的方向走:
How can i set the bluetooth pin number in linux C/C++
QDBusAbstractAdaptor object does not export implemented dbus interface
我在网上搜索了很多代码:
https://github.com/sdemario/qt-bluez-demos
https://github.com/KDE/bluez-qt
https://android.googlesource.com/platform/external/bluetooth/bluez/+/froyo-release/test/agent.c
https://github.com/pauloborges/bluez/blob/master/client/agent.c
https://www.linumiz.com/bluetooth-connectdevice-without-scanning/
但是,我还是不明白这是怎么回事。在Python中也有很多脚本,但是我正在使用C++。
我的(伪)代码如下:

agentManager = new QDBusInterface("org.bluez","/org/bluez","org.bluez.AgentManager1",QDBusConnection::systemBus(),this);
agent = new QDBusInterface("org.bluez","/org/bluez/agent","org.bluez.Agent1",QDBusConnection::systemBus(),this);


QDBusReply<void> reply;

reply = agentManager->call("RegisterAgent", QVariant::fromValue(QDBusObjectPath(path)), capability);
if (!reply.isValid()) {
    qDebug() << reply.error().message() << reply.error().name();
}

reply = agentManager->call("RequestDefaultAgent", QVariant::fromValue(QDBusObjectPath(path)));
if (!reply.isValid()) {
    qDebug() << reply.error().message() << reply.error().name();
}

QDBusReply<QString> reply_str = agent->call("RequestPinCode", QVariant::fromValue(QDBusObjectPath(path)));
if (reply_str.isValid()) {
    pincode = reply_str.value();
} else {
    qDebug() << reply_str.error().message() << reply.error().name();
}


“RegisterAgent”和“RequestDefaultAgent”调用给出有效的答复,而“RequestPinCode”则给出错误:
接口上“签名”“O”的“RequestPinCode”与签名“O”不存在
“org.freedesktop.DBus.Error.UnknownObject”
为什么?我做错什么了?
谢谢
编辑
我在D-Bus上实现了一个全新的服务,它实现了org.bluez.Agent1接口(至少是它的一部分)。现在,代码如下所示:
MyObject* myObject = new MyObject();
MyAdaptor* myAdaptor = new MyQDusAdaptor(myObject);

if (QDBusConnection::systemBus().registerService("org.test")) {
    qDebug() << "registerService was Succesfull!";
} else {
    qDebug() << "registerService was not Succesfull!";
}

if(QDBusConnection::systemBus().registerObject("/pairing/agent",myObject)){
    qDebug() << "registerObject was Succesfull!";
} else {
    qDebug() << "registerObject was not Succesfull!";
}

agentManager->RegisterAgent(QDBusObjectPath("/pairing/agent"),"NoInputNoOutput");
agentManager->RequestDefaultAgent(QDBusObjectPath("/pairing/agent"));



我的目标在哪里

class MyObject : public QObject
{
    Q_OBJECT

public:
    MyObject();

public Q_SLOTS:
    QString RequestPinCode(const QDBusObjectPath &in0);
};


MyObject::MyObject() {

}
QString MyObject::RequestPinCode(const QDBusObjectPath& in0)
{
    qDebug() << "MyObject" << in0.path();


    QString str = "2974";
    return str;
}



适配器是

class MyQDusAdaptor: public QDBusAbstractAdaptor
{

    Q_OBJECT
    Q_CLASSINFO("D-Bus Interface", "org.bluez.Agent1")
    Q_CLASSINFO("D-Bus Introspection", ""
                                                                         "  <interface name=\"org.bluez.Agent1\">\n"
                                                                         "    <method name=\"RequestPinCode\">\n"
                                                                         "      <arg direction=\"in\" type=\"o\"/>\n"
                                                                         "      <arg direction=\"out\" type=\"s\"/>\n"
                                                                         "    </method>\n"
                                                                         "  </interface>\n"
                                                                         "")

public:
        MyQDusAdaptor(QObject *parent);
        virtual ~MyQDusAdaptor();

public: // PROPERTIES
public Q_SLOTS: // METHODS
        QString RequestPinCode(const QDBusObjectPath &in0);
};


MyQDusAdaptor::MyQDusAdaptor(QObject* parent) : QDBusAbstractAdaptor(parent) {

    setAutoRelaySignals(true);
}

MyQDusAdaptor::~MyQDusAdaptor() {

}

QString MyQDusAdaptor::RequestPinCode(const QDBusObjectPath& in0)
{
    qDebug() << "MyQDusAdaptor" << in0.path();

    QString out0;
         QMetaObject::invokeMethod(parent(), "RequestPinCode", Q_RETURN_ARG(QString, out0), Q_ARG(QDBusObjectPath, in0));
         return out0;
}


当我尝试配对智能手机时,应用程序冻结约30秒,我收到以下错误消息:
“没有收到回复。可能的原因包括:远程应用程序未发送答复、消息总线安全策略阻止了答复、答复超时或网络连接已断开。“”org.freedesktop.DBus.Error.NoReply”
只有在那之后智能手机才会要求插入一个密码。
我认为这必须异步完成。有什么建议吗?

最佳答案

好的,现在可以了。方法在QDBusAbstractAdaptor object does not export implemented dbus interface
实现的细节在这个问题的最后一次编辑中。最后一件事是使用callWithCallback异步地在设备1接口上实现“Pair”方法:

void cBluetoothDevice::Pair() {

    QList<QVariant> args;
    args.clear();

    device->callWithCallback("Pair",args, this, SLOT(PairSlot(QDBusMessage)));
}


其中设备是QDBusInterface*

关于c++ - 如何使用Qt在D-Bus上创建/实例化配对代理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57872510/

10-11 19:40