Stollpy
Stollpy

Reputation: 45

Unable to read GATT notifications after Bluetooth connection on Raspberry Pi (btmon shows notifications)

I'm working on a C++ project where I'm trying to receive GATT notifications from a Bluetooth glucometer on a Raspberry Pi. I'm at the pair & connect prerequisite, in the btmon logs I get GATT notifications, but in my C++ program, I'm unable to read GATT notifications (for example, Glucose Measurement notifications).

Here's what I've done so far:

I set up a Bluetooth LE connection with the device using hci and l2cap. I've configured the HCI filters to listen for HCI and GATT events. btmon shows that I do receive notifications from the device, including GATT notifications, but in my program I am unable to capture them. I mainly receive Advertising Reports and HCI events, but not ACL packets containing GATT notifications. Here's an example of a log I receive via btmon that shows a GATT notification:

@ RAW Open: glucometre (privileged) version 2.22     {0x0002} [hci0] 117.802009
> ACL Data RX: Handle 64 flags 0x02 dlen 24              #225 [hci0] 117.837355
      ATT: Handle Value Notification (0x1b) len 19
        Handle: 0x0008 Type: Glucose Measurement (0x2a18)
          Data: 1b1d00e8070817012b2a10ff71b0f80000
> HCI Event: Number of Completed Packets (0x13) plen 5   #226 [hci0] 117.837757
        Num handles: 1
        Handle: 64 Address: XX:XX:XX:XX:XX:XX (Texas Instruments)
        Count: 2

Here are the logs of my C++ program (which do not seem to contain GATT notifications):

Lecture de l'événement HCI.
Notification reçue via HCI type : 
Notification reçue via HCI (données brutes) : 02 01 00 01 09 1d 29 65 e3 65 13 02 01 1a 02 0a 07 0c ff 4c 00 10 07 33 1f 45 be 8f 93 78 b9 ec 7e 2f 
Lecture de l'événement HCI.
Notification reçue via HCI type : 
Notification reçue via HCI (données brutes) : 02 01 03 01 af 66 38 c5 b3 c5 08 07 ff 4c 00 12 02 00 03 a6 00 10 07 
Lecture de l'événement HCI.
Notification reçue via HCI type : 
Notification reçue via HCI (données brutes) : 02 01 00 01 fd b1 04 be 91 50 12 02 01 1a 02 0a 0c 0b ff 4c 00 10 06 06 1d 5f 3d e4 58 b9 b9 ec 7e 
Lecture de l'événement HCI.
Notification reçue via HCI type : 
Notification reçue via HCI (données brutes) : 02 01 00 01 ba 6c 91 05 9f 71 1f 02 01 02 03 03 9f fe 17 16 9f fe 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c6 00 00 50 
Lecture de l'événement HCI.
Notification reçue via HCI type : 
Notification reçue via HCI (données brutes) : 02 01 02 01 28 0a 6d 78 d3 78 1b 1a ff 4c 00 02 15 50 76 5c b7 d9 ea 4e 21 99 a4 fa 87 96 13 a4 92 16 05 be b0 ce af 00 00 00 

And here's my C++ object for listening to HCI notifications :

class HCIListener {
private:
    int device_handle;
    int device_id;
    struct hci_filter original_filter;

public:
    HCIListener() : device_handle(-1), device_id(-1) {}

    bool openDevice() {
        device_id = hci_get_route(NULL);
        if (device_id < 0) {
            std::cerr << "Impossible de trouver un adaptateur Bluetooth." << std::endl;
            return false;
        } else {
            std::cout << "Adaptateur Bluetooth trouvé. Device id: " << device_id << std::endl;
        }

        device_handle = hci_open_dev(device_id);
        if (device_handle < 0) {
            std::cerr << "Impossible d'ouvrir le périphérique HCI." << std::endl;
            return false;
        } else {
            std::cout << "Périphérique HCI ouvert." << std::endl;
        }

        socklen_t original_filter_len = sizeof(original_filter);
        if (getsockopt(device_handle, SOL_HCI, HCI_FILTER, &original_filter, &original_filter_len) < 0) {
            std::cerr << "Erreur lors de la sauvegarde du filtre HCI." << std::endl;
            return false;
        } else {
            std::cout << "Sauvegarde du filtre HCI." << std::endl;
        }

        struct hci_filter new_filter;
        hci_filter_clear(&new_filter);

        hci_filter_set_ptype(HCI_EVENT_PKT, &new_filter);
        hci_filter_set_event(EVT_LE_META_EVENT, &new_filter);

        hci_filter_set_ptype(HCI_ACLDATA_PKT, &new_filter);

        if (setsockopt(device_handle, SOL_HCI, HCI_FILTER, &new_filter, sizeof(new_filter)) < 0) {
            std::cerr << "Erreur lors de la configuration du filtre HCI." << std::endl;
            return false;
        } else {
            std::cout << "Configuration du filtre HCI." << std::endl;
        }

        return true;
    }

    void closeDevice() {
        if (device_handle >= 0) {
            setsockopt(device_handle, SOL_HCI, HCI_FILTER, &original_filter, sizeof(original_filter));
            close(device_handle);
        }
    }

    void listenForNotifications() {
        uint8_t buffer[HCI_MAX_EVENT_SIZE];
        while (true) {
            int len = read(device_handle, buffer, sizeof(buffer));
            if (len < 0) {
                std::cerr << "Erreur lors de la lecture de l'événement HCI." << std::endl;
                break;
            } else {
                std::cout << "Lecture de l'événement HCI." << std::endl;
            }

            evt_le_meta_event* meta_event = (evt_le_meta_event*)(buffer + (1 + HCI_EVENT_HDR_SIZE));
            std::cout << "Notification reçue via HCI type : " << meta_event->subevent <<std::endl;

            if (len > static_cast<int>(HCI_EVENT_HDR_SIZE + sizeof(evt_le_meta_event))) {
                uint8_t* data = (buffer + HCI_EVENT_HDR_SIZE + sizeof(evt_le_meta_event));
                std::cout << "Notification reçue via HCI (données brutes) : ";
                for (int i = 0; i < len; i++) {
                    printf("%02x ", data[i]);
                }
                std::cout << std::endl;

                if (buffer[0] == 0x1B) { 
                    uint16_t handle = buffer[1] | (buffer[2] << 8);
                    if (handle == 0x2a18) { 
                        std::cout << "Notification reçue pour Glucose Measurement : ";
                        for (int i = 0; i < len; i++) {
                            printf("%02x ", buffer[i]);
                        }
                        std::cout << std::endl;
                    }
                }
            }
        }
    }
};

My question:

Thank you for your help!

Environment :

Upvotes: 0

Views: 41

Answers (0)

Related Questions