用于蓝牙的 GLib client/server

GLib for bluetooth client/server

我正在尝试学习如何使用 C 语言中的蓝牙和 GLib(通过 D-Bus 连接)连接服务器和客户端。 我已经使用此代码成功注册了我的服务及其自己的 UUID:

注册函数:

int register_profile(GDBusProxy *proxy,
    gchar *service_path,
    gchar *service_name,
    gint service_channel,
    gchar *service_uuid)
{
    GVariant *profile;
    GVariantBuilder profile_builder;
    GError *error = NULL;

    g_variant_builder_init(&profile_builder, G_VARIANT_TYPE("(osa{sv})"));

    if (!g_variant_is_object_path(service_path))
    {
        return ERR_CUSTOM_PATH_INVALID;
    }

    g_variant_builder_add(&profile_builder, "o", service_path);
    g_variant_builder_add(&profile_builder, "s", SERIAL_PORT_PROFILE_UUID);

    g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("a{sv}"));
    g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
    g_variant_builder_add(&profile_builder, "s", "Channel");
    g_variant_builder_add(&profile_builder, "v", g_variant_new_uint16(service_channel));
    g_variant_builder_close(&profile_builder);

    g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
    g_variant_builder_add(&profile_builder, "s", "Service");
    g_variant_builder_add(&profile_builder, "v", g_variant_new_string(service_uuid));
    g_variant_builder_close(&profile_builder);

    g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
    g_variant_builder_add(&profile_builder, "s", "Name");
    g_variant_builder_add(&profile_builder, "v", g_variant_new_string(service_name));
    g_variant_builder_close(&profile_builder);

    g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
    g_variant_builder_add(&profile_builder, "s", "Role");
    g_variant_builder_add(&profile_builder, "v", g_variant_new_string("server"));
    g_variant_builder_close(&profile_builder);

    g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
    g_variant_builder_add(&profile_builder, "s", "RequireAuthentication");
    g_variant_builder_add(&profile_builder, "v", g_variant_new_boolean(FALSE));
    g_variant_builder_close(&profile_builder);

    g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
    g_variant_builder_add(&profile_builder, "s", "RequireAuthorization");
    g_variant_builder_add(&profile_builder, "v", g_variant_new_boolean(FALSE));
    g_variant_builder_close(&profile_builder);

    g_variant_builder_open(&profile_builder, G_VARIANT_TYPE("{sv}"));
    g_variant_builder_add(&profile_builder, "s", "AutoConnect");
    g_variant_builder_add(&profile_builder, "v", g_variant_new_boolean(TRUE));
    g_variant_builder_close(&profile_builder);

    g_variant_builder_close(&profile_builder);
    profile = g_variant_builder_end(&profile_builder);

    GVariant *ret = g_dbus_proxy_call_sync(
        proxy, "RegisterProfile", profile, G_DBUS_CALL_FLAGS_NONE,-1, NULL, &error);

    g_assert_no_error(error);

    if (ret != NULL && error == NULL)
    {
        return RESULT_OK;
    }
    return -1;
}

接收连接事件的代码:

static void signal_device_changed(GDBusConnection *conn,
    const gchar *sender,
    const gchar *path,
    const gchar *interface,
    const gchar *signal,
    GVariant *params,
    void *userdata)
{

    g_print("Signal Device changed");
}

我用这个初始化代码:

int register_service(char *service_path,
    char *service_name,
    int service_channel,
    char *service_uuid)
{
    GDBusProxy *proxy;
    GDBusConnection *conn, *pconn;
    GError *error = NULL;

    conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
    g_assert_no_error(error);

    proxy = g_dbus_proxy_new_sync(conn,
        G_DBUS_PROXY_FLAGS_NONE,
        NULL,
        "org.bluez",
        "/org/bluez",
        "org.bluez.ProfileManager1",
        NULL,
        &error);
    g_assert_no_error(error);
    error = NULL;

    int result = register_profile(proxy, service_path, service_name, service_channel, service_uuid);
    if (result != RESULT_OK)
    {
        return result;
    }

    pconn = g_dbus_proxy_get_connection(proxy);
    guint sub_id = g_dbus_connection_signal_subscribe(pconn,
        "org.bluez",
        "org.freedesktop.DBus.Properties",
        "PropertiesChanged",
        NULL,
        "org.bluez.Device1",
        G_DBUS_SIGNAL_FLAGS_NONE,
        signal_device_changed,
        NULL,
        NULL);

    g_print("Registration successful with subscription id [%d]. Press [ENTER] to exit.", sub_id);
    char c;
    result = scanf("%c", &c);

    g_dbus_connection_signal_unsubscribe(pconn, sub_id);
    g_object_unref(pconn);
    g_object_unref(proxy);
    g_object_unref(conn);

    return RESULT_OK;
}

我使用 python 客户端应用程序(我用 python 服务器测试过,它在我用来测试的设备上运行)连接到上述服务器:

我尝试使用 conn 而不是代理连接,结果相同。
我是不是忘记了什么?

我使用的信息来自:

根据@ukBaz 的建议,我需要进入主循环。我修改了服务注册中的代码如下:

// Beginning is same
serverUserData *userData = malloc(sizeof(serverUserData));
userData->loop = g_main_loop_new(NULL, FALSE);

guint sub_id = g_dbus_connection_signal_subscribe(pconn,
    "org.bluez",
    "org.freedesktop.DBus.Properties",
    "PropertiesChanged",
    NULL,
    "org.bluez.Device1",
    G_DBUS_SIGNAL_FLAGS_NONE,
    signal_device_changed,
    userData,
    NULL);

    if (sub_id > 0)
    {
        g_print("Registration successful with subscription id [%d].\n", sub_id);
    }

    g_main_loop_run(userData->loop);

    g_dbus_connection_signal_unsubscribe(pconn, sub_id);
    if (pconn != NULL)
        g_object_unref(pconn);
    if (proxy != NULL)
        g_object_unref(proxy);
    if (conn != NULL)
        g_object_unref(conn);

当设备断开连接时,我退出了主循环。

接下来我需要弄清楚如何创建 RFCOMM 套接字连接并监听它。但如果我遇到问题,我会在另一个问题中做。