使用 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
如果社区能就我的上述主题向我指出正确的方向,我会很高兴。
我有兴趣在 ubuntu 14.04 中使用 bluetooth_client_connect_service()
函数使用 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);
我希望此代码在接收到双击信号时连接到选定的检测到的设备,但目前双击它时没有任何反应。
非常感谢专家的指导。
提前致谢
g_signal_connect(G_OBJECT(selector),"notify::selected-device-activated",
G_CALLBACK(connect_button_clicked),client);
如果存在 属性 "selected-device-activated" 并且您想知道 属性 值何时更改,则将使用此信号签名。但在这种情况下 "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% 确定"proxy" 字段名,我自己没用过这个 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*
.
如果社区能就我的上述主题向我指出正确的方向,我会很高兴。
我有兴趣在 ubuntu 14.04 中使用 bluetooth_client_connect_service()
函数使用 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);
我希望此代码在接收到双击信号时连接到选定的检测到的设备,但目前双击它时没有任何反应。
非常感谢专家的指导。
提前致谢
g_signal_connect(G_OBJECT(selector),"notify::selected-device-activated",
G_CALLBACK(connect_button_clicked),client);
如果存在 属性 "selected-device-activated" 并且您想知道 属性 值何时更改,则将使用此信号签名。但在这种情况下 "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% 确定"proxy" 字段名,我自己没用过这个 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*
.