使用 bluetooth_client_connect_service() 连接到蓝牙设备 - gnome-bluetooth 3.8.2.1

Posted

技术标签:

【中文标题】使用 bluetooth_client_connect_service() 连接到蓝牙设备 - gnome-bluetooth 3.8.2.1【英文标题】:Connecting to Bluetooth Device using bluetooth_client_connect_service() - gnome-bluetooth 3.8.2.1 【发布时间】:2015-09-04 23:01:44 【问题描述】:

如果我能就我的上述主题为社区指明正确的方向,我会很高兴。

我有兴趣使用 bluetooth_client_connect_service() 函数在 ubuntu 14.04 中使用 gnome-bluetooth api 连接到蓝牙设备。

我尝试过搜索,但没有找到关于如何使用它的好结果,所以我决定阅读gnome-bluetooth的源代码,但由于评论不足,我无法理解。

以下是我到目前为止所做的事情,但是当我尝试运行我的应用程序时没有收到任何错误,但是当我双击设备时它什么也不做。

#define AGENT_PATH "/org/bluez/agent/wizard"
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <signal.h>
#include <math.h>
#include <glib.h>
//#include <dbus/dbus.h>
#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <bluetooth-chooser.h>
#include <bluetooth-client.h>
#include <bluetooth-utils.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

#define CONNECT_TIMEOUT 3.0
#define AGENT_PATH "/org/bluez/agent/wizard"

typedef struct 
    char *path;
    GTimer *timer;
 ConnectData;

BluetoothClient *client;
GtkWidget *selector;
GtkWidget *vboxMainLayout;

GValue value =  0, ;

int find_conn(int s, int dev_id, long arg)

    struct hci_conn_list_req *cl;
    struct hci_conn_info *ci;
    int i;

    if (!(cl = malloc(10 * sizeof(*ci) + sizeof(*cl)))) 
        perror("Can't allocate memory");
        exit(1);
    
    cl->dev_id = dev_id;
    cl->conn_num = 10;
    ci = cl->conn_info;

    if (ioctl(s, HCIGETCONNLIST, (void *) cl)) 
        perror("Can't get connection list");
        exit(1);
    

    for (i = 0; i < cl->conn_num; i++, ci++)
        if (!bacmp((bdaddr_t *) arg, &ci->bdaddr)) 
            free(cl);
            return 1;
        

    free(cl);
    return 0;


void cmd_rssi(const char *bt_address)

    struct hci_conn_info_req *cr;
    bdaddr_t bdaddr;
    int8_t rssi;
    int dd, dev_id;

    str2ba(bt_address, &bdaddr);

        dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr);
        if (dev_id < 0) 
            g_print("\tNot connected.\n");
            return;
        

    dd = hci_open_dev(dev_id);
    if (dd < 0) 
        perror("HCI device open failed");
        exit(1);
    

    cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info));
    if (!cr) 
        perror("Can't allocate memory");
        exit(1);
    

    bacpy(&cr->bdaddr, &bdaddr);
    cr->type = ACL_LINK;
    if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) 
        perror("Get connection info failed");
        exit(1);
    

    if (hci_read_rssi(dd, htobs(cr->conn_info->handle), &rssi, 1000) < 0) 
        perror("Read RSSI failed");
        exit(1);
    

    g_print("\tRSSI return value: %d\n", rssi);

    free(cr);

    hci_close_dev(dd);


void connect_callback (GObject *source_object, GAsyncResult *res, gpointer user_data)

    ConnectData *data = (ConnectData *) user_data;
    gboolean success;

    success = bluetooth_client_connect_service_finish (client, res, NULL);

    if (success == FALSE && g_timer_elapsed (data->timer, NULL) < CONNECT_TIMEOUT) 
        bluetooth_client_connect_service (client, data->path, TRUE, NULL, connect_callback, data);
        return;
    

    if (success == FALSE)
        g_print ("\tFailed to connect to device %s", data->path);
    else
        g_print("\n\tConnection successfully.. ha.. I'm tired\n");

    g_timer_destroy (data->timer);
    g_free (data->path);
    g_free (data);


void create_callback (BluetoothClient *_client, const char *path, const GError *error, gpointer user_data)

    ConnectData *data;
    //compiler throws "implicit declaration" warning here
    //bluetooth_client_set_trusted(client, path, TRUE);

    data = g_new0 (ConnectData, 1);
    data->path = g_strdup (path);
    data->timer = g_timer_new ();

    bluetooth_client_connect_service (client, path, TRUE, NULL, connect_callback, data);


void get_device_info(BluetoothChooser *self)


        const gchar* result;

        g_print ("Info dumped:\n");
        if (bluetooth_chooser_get_selected_device_info (self, "name", &value)) 
            g_print ("\tName: '%s'\n", g_value_get_string (&value));
            g_value_unset (&value);
        
        if (bluetooth_chooser_get_selected_device_info (self, "address", &value)) 
            g_print ("\tAddress: '%s'\n", g_value_get_string (&value));
            g_value_unset (&value);
        
        if (bluetooth_chooser_get_selected_device_info (self, "paired", &value)) 
            result = g_value_get_boolean (&value)? "Paired":"Unpaired";
            g_print ("\tPaired: '%s'\n", result);
            g_value_unset (&value);
        
        guint type = bluetooth_chooser_get_selected_device_type (self);
        const gchar *device_type = bluetooth_type_to_string(type);
        if(type)
        
            g_print("\tType: '%s'\n", device_type);
        
        if (bluetooth_chooser_get_selected_device_info (self, "connected", &value)) 
                result = g_value_get_boolean (&value)? "Connected":"Not Connected";
                g_print ("\tConnected: '%s'\n", result);
                g_value_unset (&value);
        


/* My problem lies here.. how to connect to the detected device 
 * no error message is displayed when a device is double-clicked
 */
void connect_button_clicked(GtkWidget *widget, gpointer user_data)

    const char *path = AGENT_PATH;
    ConnectData *data = (ConnectData *) user_data;
    GValue value =  0, ;

    bluetooth_chooser_get_selected_device_info (widget, "address", &value);
    bluetooth_client_connect_service (client, path, TRUE, NULL, connect_callback, data);

    //function to get the rssi value of the remote device
    cmd_rssi(g_value_get_string (&value));


void create_interface(GtkApplication *app, gpointer user_data)

    GtkWidget *frmTopWindow;
    frmTopWindow = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(frmTopWindow), "Test");
    gtk_window_set_position(GTK_WINDOW(frmTopWindow),GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(frmTopWindow),200,400);

    selector = bluetooth_chooser_new();
    g_object_set(selector,
                  "show-searching", TRUE,
                  "show-device-type", FALSE,
                  "show-pairing" , TRUE,
                  "show-device-category", FALSE,
                     NULL);
        client = bluetooth_client_new();
        vboxMainLayout = gtk_box_new(GTK_ORIENTATION_VERTICAL, 3);
        g_object_set(vboxMainLayout,
                "width-request", 190,
                "height-request", 300, NULL);

        gtk_container_add(GTK_CONTAINER(frmTopWindow),selector);

        /*Events and Signals*/
        /*------------------*/

        // When user double-clicks on a detected device, try and connect to that device
        // and display it's RSSI
        g_signal_connect(G_OBJECT(selector),"notify::selected-device-activated",G_CALLBACK(connect_button_clicked),client);

        //When user clicks on a detected device, display information about that device in the
        // standard output
        g_signal_connect(G_OBJECT(selector),"notify::device-selected",G_CALLBACK(get_device_info),vboxMainLayout);

        gtk_widget_show_all(frmTopWindow);


int main(int argc, char** argv)

    GtkApplication *app;
    int status;
    app = gtk_application_new ("rucst.project.test", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (app, "activate", G_CALLBACK (create_interface), NULL);
    status = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);
    return status;

在我的实现代码中,我有一个g_signal_connect 函数调用它,如下所示:

g_signal_connect(G_OBJECT(selector),"notify::selected-device-activated",G_CALLBACK(connect_button_clicked),client);

我希望这段代码在接收到双击信号时连接到选定的检测到的设备,但是当我双击它时没有任何反应。

如果能得到专家的指导,我将非常感激。

提前谢谢你

【问题讨论】:

"I get errors" 真的没用,尤其是当您不提供我们可以运行以查看错误的示例时... 另外,请说明这段代码是如何被调用的:最后的g_signal_connect() 似乎无关——也许是复制粘贴错误? 感谢您的回复。我目前不在我的系统后面,我会尽快更正错误并更新。 【参考方案1】:
g_signal_connect(G_OBJECT(selector),"notify::selected-device-activated",
                 G_CALLBACK(connect_button_clicked),client);

如果存在“选定设备激活”属性并且您想知道属性值何时更改,则将使用此信号签名。但在这种情况下,“selected-device-activated”是一个实际的信号,所以你应该这样做:

g_signal_connect(G_OBJECT(selector),"selected-device-activated",
                 G_CALLBACK(callback), client);

单击版本恰好可以工作,因为您找到了一个可以满足您要求的属性,因此连接到“notify::device-selected”可以正常工作(我仍然会连接到“selected-device-changed " 表示一致性)。


在 connect_button_clicked() 之后,您的连接调用使用看似不相关的路径作为设备对象路径......这样的事情可能会起作用(尽管我不是 100% 确定“代理”字段名称,我自己没用过这个API):

GValue value =  0, ;
if (bluetooth_chooser_get_selected_device_info (BLUETOOTH_CHOOSER (widget),
                                                "proxy", &value)) 
    GDBusProxy *proxy = g_value_get_object (&value);
    g_print ("Connecting to %s\n", g_dbus_proxy_get_object_path(proxy));
    bluetooth_client_connect_service (client, g_dbus_proxy_get_object_path(proxy),
                                      TRUE, NULL, connect_callback, data);

还要注意,您给回调的用户数据指针是错误的:例如connect_button_clicked() 需要ConnectData*,但得到BluetoothClient*

【讨论】:

感谢您的宝贵时间。我按照您的建议更改了g_signal_connect()。现在,应用程序可以调用connect_button_clicked 回调函数,即使已配对,它也无法连接到检测到的设备。你能帮我解决这个问题吗? “它无法连接”再次说明细节......不过我会在帖子中添加一些建议。 再次感谢您。将您的代码插入我的connect_button_clicked 函数使其工作,尽管我收到GLib-GObject-CRITICAL **: g_value_get_string: assertion 'G_VALUE_HOLDS_STRING (value)' failed 错误。但我会尝试解决该错误。我非常感谢您的时间和帮助。 :) 不客气。请注意,它确实是 g_value_get_object(),因为值是 GObject 而不是字符串。

以上是关于使用 bluetooth_client_connect_service() 连接到蓝牙设备 - gnome-bluetooth 3.8.2.1的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)