weliem / bluez_inc

A C library for Bluez (BLE) that hides all DBus communication. It doesn't get easier than this. This library can also be used in C++.
MIT License
84 stars 19 forks source link

Problems with notification #16

Closed krimp closed 10 months ago

krimp commented 10 months ago

I am trying to use this library to implement a Central for the Nordic Uart GATT on a RPi4B 64bit, Bullseye, Bluez 5.70. I am using the Central-example as the starting point and the following uuid:

#define NUS_CHARACTERISTIC_TX_UUID  "6e400002-b5a3-f393-e0a9-e50e24dcca9e"
#define NUS_CHARACTERISTIC_RX_UUID  "6e400003-b5a3-f393-e0a9-e50e24dcca9e"
#define NORDIC_UART_SERVICE         "6e400001-b5a3-f393-e0a9-e50e24dcca9e"

The Central is very simple: The RX has a notification only, and the TX a write:

2023-10-29 13:13:28:562 DEBUG [Device] Characteristic{uuid='6e400003-b5a3-f393-e0a9-e50e24dcca9e', flags='[notify]', properties=16, service_uuid='6e400001-b5a3-f393-e0a9-e50e24dcca9e, mtu=247'}
2023-10-29 13:13:28:562 DEBUG [Device] Descriptor{uuid='00002902-0000-1000-8000-00805f9b34fb', flags='[]', properties=0, char_uuid='6e400003-b5a3-f393-e0a9-e50e24dcca9e'}
2023-10-29 13:13:28:563 DEBUG [Device] Characteristic{uuid='6e400002-b5a3-f393-e0a9-e50e24dcca9e', flags='[write-without-response, write]', properties=12, service_uuid='6e400001-b5a3-f393-e0a9-e50e24dcca9e, mtu=247'}

The adapter code in main (restricted to this RPi only):

        binc_adapter_set_discovery_cb(default_adapter, &on_scan_result);
        binc_adapter_set_discovery_state_cb(default_adapter, &on_discovery_state_changed);
        binc_adapter_set_discovery_filter(default_adapter, -100, service_uuids, "RPi BLE Central");
        g_ptr_array_free(service_uuids, TRUE);
        binc_adapter_start_discovery(default_adapter);
void on_services_resolved(Device *device) {
    log_debug(TAG, "'%s' services resolved", binc_device_get_name(device));

    binc_device_read_char(   device, NORDIC_UART_SERVICE, NUS_CHARACTERISTIC_TX_UUID);
    binc_device_read_char(   device, NORDIC_UART_SERVICE, NUS_CHARACTERISTIC_RX_UUID);
    binc_device_start_notify(device, NORDIC_UART_SERVICE, NUS_CHARACTERISTIC_RX_UUID);   
}
void on_notify(Characteristic *characteristic, const GByteArray *byteArray) {
    const char *uuid = binc_characteristic_get_uuid(characteristic);

    if (g_str_equal(uuid, NUS_CHARACTERISTIC_RX_UUID)) {

        Parser *parser         = parser_create(byteArray, LITTLE_ENDIAN);
        GString *parsed_string = parser_get_string(parser);
        log_debug(TAG, "rxStr: %s", parsed_string->str);

The data sent from the Peripheral is 88 bytes binary. However, it seems like the data does not reach the notification callback. The log_debug in characteristc.c does indeed print out a 176 bytes long hex string (2x88 bytes), but it seems like it is not accessible in the callback. I have located the problem to be in the binc_internal_signal_characteristic_changed(...) in characteristc.c, handling the CHARACTERISTIC_PROPERTY_VALUE


    g_assert(g_str_equal(g_variant_get_type_string(parameters), "(sa{sv}as)"));
    g_variant_get(parameters, "(&sa{sv}as)", &iface, &properties, &unknown);
    while (g_variant_iter_loop(properties, "{&sv}", &property_name, &property_value)) {
        if (g_str_equal(property_name, CHARACTERISTIC_PROPERTY_NOTIFYING)) {
            characteristic->notifying = g_variant_get_boolean(property_value);
            log_debug(TAG, "notifying %s <%s>", characteristic->notifying ? "true" : "false", characteristic->uuid);

            if (characteristic->notify_state_callback != NULL) {
                characteristic->notify_state_callback(characteristic, NULL);
            }

            if (characteristic->notifying == FALSE) {
                if (characteristic->characteristic_prop_changed != 0) {
                    g_dbus_connection_signal_unsubscribe(characteristic->connection,
                                                         characteristic->characteristic_prop_changed);
                    characteristic->characteristic_prop_changed = 0;
                }
            }
        } else if (g_str_equal(property_name, CHARACTERISTIC_PROPERTY_VALUE)) {
            GByteArray *byteArray = g_variant_get_byte_array(property_value);
            GString *result = g_byte_array_as_hex(byteArray);
            log_debug(TAG, "len: <%i> of notification <%s> on <%s> ", strlen(result->str)/2, result->str, characteristic->uuid);
            g_string_free(result, TRUE);

            if (characteristic->on_notify_callback != NULL) {
                characteristic->on_notify_callback(characteristic, byteArray);
            }
            g_byte_array_free(byteArray, FALSE);
        }
    }

The log debug in characteristc.c, handling the CHARACTERISTIC_PROPERTY_VALUE gives this output:

2023-10-29 13:13:33:905 DEBUG [Characteristic] len: <88> of notification <b694040ad1d3000000f89f191c000000758b5a7b8b010000eaff0000000005000300000000000000fdff0000000000000500000000000000d0ff000000001700fcff0000000000000e26ea206381020019fc140000000000> on <6e400003-b5a3-f393-e0a9-e50e24dcca9e> 

The log debug in the notification callback:

2023-10-29 13:13:33:905 DEBUG [Main] rxStr: ��

I have a feeling my issues is related to that my Peripheral transmits binary data, which might is a problem for the glib gvariant... library?

Another thing is that the 176 bytes in log_info in chracteristic.c are always the same, which might indicate another problem?

GLib-version used:

GNU C Library (Debian GLIBC 2.31-13+rpt2+rpi1+deb11u7) stable release version 2.31.
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 10.2.1 20210110.
libc ABIs: UNIQUE ABSOLUTE
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
krimp commented 10 months ago

Ahhh. Solved it: Had to NOT convert the byteArray in the notification callback, due to binary data. Had to access the received data by

byteArr->data

and

byteArr->len
weliem commented 10 months ago

Ok, good that you got it to work!