Проблема при запуске обработчика уведомлений gattlib с отправкой по dbus с использованием libdbus - PullRequest
0 голосов
/ 26 сентября 2019

Я использую библиотеку gattlib C, чтобы общаться с устройством Bluetooth и установить обработчик уведомлений для UUID, который работает нормально, но когда я также вызываю команду отправки DBus из обработчика (используя libdbus), это не работает -ничего не проходит (я проверяю, что не проходит, читая интерфейс другого процесса).

Я пробовал и функцию получения, и функцию отправки, и они работают изолированно без моего кода, например: я могуотправлять сообщения и видеть их получение, используя два процесса, если я использую только пример кода здесь: http://www.matthew.ath.cx/misc/dbus

Ниже мой код;

#define DBUS_API_SUBJECT_TO_CHANGE
#include <assert.h>
#include <glib.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <systemd/sd-daemon.h>
#include <dbus/dbus.h>

#include "gattlib.h"

// Heart Rate UUID
const uuid_t g_heart_rate_uuid = CREATE_UUID16(0x2A37);

static GMainLoop *m_main_loop;
FILE *fp;

void sendsignal(char* sigvalue)
{
   DBusMessage* msg;
   DBusMessageIter args;
   DBusConnection* conn;
   DBusError err;
   int ret;
   dbus_uint32_t serial = 0;

   printf("Sending signal with value %s\n", sigvalue);

   // initialise the error value
   dbus_error_init(&err);

   // connect to the DBUS system bus, and check for errors
   conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
   if (dbus_error_is_set(&err)) { 
      fprintf(stderr, "Connection Error (%s)\n", err.message); 
      dbus_error_free(&err); 
   }
   if (NULL == conn) { 
      exit(1); 
   }

   // register our name on the bus, and check for errors
   ret = dbus_bus_request_name(conn, "test.signal.source", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
   if (dbus_error_is_set(&err)) { 
      fprintf(stderr, "Name Error (%s)\n", err.message); 
      dbus_error_free(&err); 
   }
   if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { 
      exit(1);
   }

   // create a signal & check for errors 
   msg = dbus_message_new_signal("/test/signal/Object", // object name of the signal
                                 "test.signal.Type", // interface name of the signal
                                 "Test"); // name of the signal
   if (NULL == msg) 
   { 
      fprintf(stderr, "Message Null\n"); 
      exit(1); 
   }

   // append arguments onto signal
   dbus_message_iter_init_append(msg, &args);
   if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &sigvalue)) {
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   }

   // send the message and flush the connection
   if (!dbus_connection_send(conn, msg, &serial)) {
      fprintf(stderr, "Out Of Memory!\n"); 
      exit(1);
   }


   //dbus_connection_flush(conn);


   printf("Signal Sent\n");

   // free the message and close the connection
   dbus_message_unref(msg);
   dbus_connection_close(conn);
}

void notification_handler(
    const uuid_t* uuid,
    const uint8_t* data,
    size_t data_length,
    void* user_data){

    int rrInterval_one, rrInterval_two;
    char str[10];

    for (int i=0; i<9; i++){
        str[i] = '\0';
    }

    fp = fopen("/home/research/Desktop/bluetooth/gattlib/build-dir/heart_rate_and_rr.txt", "w");

    if (fp == NULL)
    {
            printf("Error opening file!\n");
            exit(1);
    }

    if (data_length == 2){

        printf("HR: %d", data[1]);
        fprintf (fp, "HR: %d", data[1]);
        sprintf(str, "%d", data[1]);

        sendsignal(str);

        sd_notify(0,"WATCHDOG=1");
    }
    else if (data_length == 4)
    {

        printf("HR: %d", data[1]);
        fprintf (fp, "HR: %d", data[1]);
        sprintf(str, "%d", data[1]);

        rrInterval_one = (data[3]* 0x100) + (data[2]);
        fprintf (fp, " RR-Interval: %d", rrInterval_one);
        printf (" RR-Interval: %d \n", rrInterval_one);

        sendsignal(str);

        sd_notify(0,"WATCHDOG=1");


    }
    else if (data_length == 6)
    {

        printf("HR: %d", data[1]);
        fprintf (fp, "HR: %d", data[1]);
        sprintf(str, "%d", data[1]);


        rrInterval_one =(data[3]* 0x100) + (data[2]);
        rrInterval_two =(data[5]* 0x100) + (data[4]);
        fprintf (fp, " RR-Interval: %d %d", rrInterval_one, rrInterval_two);
        printf (" RR-Interval: %d", rrInterval_one);
        printf (" %d\n", rrInterval_two);

        sendsignal(str);

        sd_notify(0,"WATCHDOG=1");
    }
    fclose(fp);

}


static void on_user_abort(int arg) {
    g_main_loop_quit(m_main_loop);
}

static void usage(char *argv[]) {
    printf("%s <device_address>\n", argv[0]);
}

int main(int argc, char *argv[]) {

    int ret;
    gatt_connection_t* connection;

    if (argc != 2) {
        usage(argv);
        return 1;
    }

    connection = gattlib_connect(NULL, argv[1], GATTLIB_CONNECTION_OPTIONS_LEGACY_DEFAULT);
    if (connection == NULL) {
        fprintf(stderr, "Fail to connect to the bluetooth device.\n");
        return 1;
    }

    gattlib_register_notification(connection, notification_handler, NULL);

    ret = gattlib_notification_start(connection, &g_heart_rate_uuid);
    if (ret) {
        fprintf(stderr, "Fail to start notification\n.");
        goto DISCONNECT;
    }

    // Catch CTRL-C
    signal(SIGINT, on_user_abort);

    // Start-up notification to the service manager
    sd_notify(0, "READY=1");

    fprintf(stderr, "Connected to Bluetooth Device\n");

    m_main_loop = g_main_loop_new(NULL, 0);
    g_main_loop_run(m_main_loop);

    // In case we quit the main loop, clean the connection
    gattlib_notification_stop(connection, &g_heart_rate_uuid);
    g_main_loop_unref(m_main_loop);

DISCONNECT:
    gattlib_disconnect(connection);
    puts("Done");
    return ret;
}

Это не дает мне никакой ошибкисообщения, но на второй итерации обработчика код выходит из кода ниже, если я не закомментирую проверку для DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER и когда я это сделаю, код выполняется, но все же я ничего не вижу со стороны получения.

if (dbus_error_is_set(&err)) { 
      fprintf(stderr, "Name Error (%s)\n", err.message); 
      dbus_error_free(&err); 
   }
   if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { 
      exit(1);
}

Я действительно подозреваю, что проблема в главном цикле событий, потому что даже когда я перемещаю DBUS, отправьте функциюна (или только на той его части, которая создает соединение с шиной) внутри Main () - я все еще не вижу имя шины, однако, используя d-футы, когда я проверяю - я знаю, что ей присваивается уникальное имя (например,: 1.113), который тоже не виден с d-футами (я пытаюсь использовать SESSION Bus, если кто-то задается вопросом).

...