AnneRanch
Posts: 209
Joined: Fri Oct 19, 2018 1:48 pm
Location: Hot Houston TX

Programming bluetooth using C++

Mon May 13, 2019 6:32 pm

http://people.csail.mit.edu/albert/blu ... 768482065
Edited - link did not show up
https://lifehacker.com/everything-you-n ... 1768482065

I am using the 1st link "scan" sample referenced above and it sort of works.
I ended up using the 2nd link to "activate" bluetooth on 3 BRPi

I am using ssh to communicate with RPi, have no access to GUI for now.

It is my understanding that "bluetoothctlt " is a "Linux package" designed to be used as standalone CLI application.
That is NOT my goal, I need a C++ code to interact with bluetooth without using "bluetoothctlt "

Unfortunately the code presented in the first reference link DOES NOT help me to initially activate the RPi bluetooth.
The ID "scan" works only after I do bluetoothctlt .
I can do that using "system calls" but prefer C++ .
Is that possible?

Thanks in advance


EDITED
I like to attempt to clarify the above post.
I need to have "headless operation" .
I am familiar with "bluez stack " of hci_x functions, what I am missing is how to initialize / start "bluetooth service" on RPi from running C++ program.
The enclosed C code will always fail because the RPI OS bluetooth service is not active , not untill CLI "bluetoothctlt" is used.
In essence - I either have to make "system" calls to bluetoothctl or find hci-_x function which does that.

Code: Select all

	// get the device ID
	if ((id = hci_get_route(NULL)) < 0) {
#ifdef DEBUG
		cout << " get the device ID  failed exit " << endl; //
#endif
		return -1;
	}



User avatar
topguy
Posts: 7225
Joined: Tue Oct 09, 2012 11:46 am
Location: Trondheim, Norway

Re: Programming bluetooth using C++

Tue May 14, 2019 12:17 pm

Why not make "starting the bluetooth service" a part of the system boot ?
Is there a "bluetooth" service you can start or enable with systemd ?

User avatar
Douglas6
Posts: 5038
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: Programming bluetooth using C++

Tue May 14, 2019 1:33 pm

There's a ton of example C code in the BlueZ github (https://git.kernel.org/pub/scm/bluetoot ... .git/tree/) in the tools/ directory. I would start there. Most of it uses D-Bus interfaces to interact with BlueZ, so get familiar with that.

That Lifehacker article you referenced is quite inaccurate.

AnneRanch
Posts: 209
Joined: Fri Oct 19, 2018 1:48 pm
Location: Hot Houston TX

Re: Programming bluetooth using C++

Tue May 14, 2019 3:09 pm

Thanks
that is what I was looking for - something which has comments in code.
I am still searching for how to start C++ to "interact" with RPi hardware.
I believe I need to learn how to distinguish between OS "build-in" bluetooth and using the bluez library.
I need to go back to RPi configure, I have not been there for months, to check if bluetooth needs to be configured there.
Thanks for your post, appreciate it.

deepo
Posts: 854
Joined: Sun Dec 30, 2018 8:36 pm
Location: Denmark

Re: Programming bluetooth using C++

Wed May 29, 2019 8:48 pm

I have also tried to get Bluetooth communication code working from C++ - with varied success.
My goal is to intercept Bluetooth Low Energy (BLE) Advertisement messages, similar to Bluetooth beacon signals.
I have managed that using the Bluez Bluetooth stack.

My goal was to receive temperature measurements from Minew BLE tags that transmit measurements as BLE Advertisement messages.

That seems to work fine for me.

My next step was then to communicate with the BLE tag to program it, but I have not been able to do that yet.

Many sources on the interwebs says to look at the Bluez DBus API, as that is supposedly the better way to use the Bluez stack, but I have not found a way through yet.

Let me know if you want some of my sample code.

/Mogens

deepo
Posts: 854
Joined: Sun Dec 30, 2018 8:36 pm
Location: Denmark

Re: Programming bluetooth using C++

Wed May 29, 2019 8:50 pm

Oh by the way.
I have never had to start the Bluetooth stack in any way, when working with Bluez on rPi 3B+.
My code (similar to your example) just connected and worked out of the box.

/Mogens

AnneRanch
Posts: 209
Joined: Fri Oct 19, 2018 1:48 pm
Location: Hot Houston TX

Re: Programming bluetooth using C++

Thu May 30, 2019 12:21 am

Thanks for the reply.
I am sure some will not appreciate this, but I am firm believer that "blueZ" is one of the worst NON documented stuff on the net.
It seems to be closed to an average programmer as far as finding out things.
Since it is now part of the Linux kernel even basic Linux documentation is very scarce.


I think there are several "levels" in accessing bluetooth technology...

Basic - low level HCI functions.
There is an ancient "scan" (C) wrapper which supposedly identify ALL nearby devices - its function "hci_inquiry" identify ONLY ONE such device.

Then you have "tools" - commands pretty much useless to seriously use in C++ code.

Yes, the "HCI" is pretty much obsolete , no big loss " and replaced with "D_Bus" .
I have not found SINGLE documentation in "blueZ" package ( source code ) about D_Bus usage.

I am not sure what BLE technology offers as fas as wireless communication.
If the name "low energy " really means something above "low energy" I'll pass for now.

I am presently looking into using "system()" to access "bluetoothctl" TOOL.
I can get simple response - such as system("bluetoothctl help"):

I am experimenting with "popen" to get interactive response - so far not much luck.
But there are other Linux "commands" I’ll try later.

I may be interested in you code later. Right now I need to prove that using "bluetoothctl" is worth the effort.
Later.






.

User avatar
Douglas6
Posts: 5038
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: Programming bluetooth using C++

Thu May 30, 2019 1:04 am

AnneRanch wrote:
Thu May 30, 2019 12:21 am
I have not found SINGLE documentation in "blueZ" package ( source code ) about D_Bus usage.
Did you look into the BlueZ github directory as I recommended? Based on your response, I'm guessing no. Again, I can't help if you ignore my advice.

If you are looking at using bluetoothctl from a C program, try 'expect'. Or not, your choice.

deepo
Posts: 854
Joined: Sun Dec 30, 2018 8:36 pm
Location: Denmark

Re: Programming bluetooth using C++

Thu May 30, 2019 7:33 am

AnneRanch, I understand your frustration. I'm there myself.

My latest Bluetooth "project" was installing SBFspot this week on a rPi Zero W to transfer data via Bluetooth from my solar cells on the roof to pvoutput.org.
https://github.com/SBFspot/SBFspot

I haven't looked into the code yet, but it works flawlessly.

I wrote about my latest attempt with BlueZ here:
viewtopic.php?f=33&t=239640&p=1463422#p1463422

Douglas6: I'll have to look into the BlueZ github directory, thanks.

/Mogens

AnneRanch
Posts: 209
Joined: Fri Oct 19, 2018 1:48 pm
Location: Hot Houston TX

Re: Programming bluetooth using C++

Thu May 30, 2019 2:29 pm

Mogens
Yes, I thought that the concept "open source" includes "open documentation".
In an essence this has been "just learning experience" and so far with very limited success.

What is really interesting NONE of these "resources" have simple - "this is how to connect bluetooth devices IN SOFTWARE ".
Perhaps these "source packages" could use some kind of "table of contents". Wishful thinking on my part.


I am really not thrilled to switch to yet another "concept" - I hate to call it "protocol" - D_Bus.
If "hci" published by same group did not do the job, what makes anybody think that "D_Bus" will be the holly grail?

( just read a note saying "bluez should not be used in C++ programming"!)

The whole idea of using "'bluetothctl" was - if it works in plain "command" mode - why not put it in C++.
The concept of starting another process is pretty clear, no magic, but to make "exec" work in interactive mode seems impossible.

PS
As far as RPI Zero goes - after finding out that its "processor" architecture is NOT currently part of tools I am using I had to scrap it for my project.
Long , boring story.

Mogens
Just an unhappy update.
This DBus seems to be "under development" and as far as my OS is concerned "version 1.0".
Already found "missing header " and checked "developers " site - 87 pending errors!
Funny - I cannot just test delete the reference to missing header - file is "read only".

I'll try to find current , hopefully working release not under OS "supervision" , and build it from source .

I am really not to thrilled the way Linux "supports" software development.
Everything is either obsolete or "under construction".
Not really sure what is the answer.
Of course I will get flamed for saying this.

deepo
Posts: 854
Joined: Sun Dec 30, 2018 8:36 pm
Location: Denmark

Re: Programming bluetooth using C++

Fri May 31, 2019 8:25 am

AnneRanch: You should be able to fix the missing file problem by editing the file that includes the missing file as robot:
sudo nano filename.ext

But your build might still be broken after that.

I think I updated BlueZ to 5.5 but I don’t have my notes here. I’ll respond when I get back home monday.
Are you trying out BlueZ?

/Mogens

AnneRanch
Posts: 209
Joined: Fri Oct 19, 2018 1:48 pm
Location: Hot Houston TX

Re: Programming bluetooth using C++

Fri May 31, 2019 12:28 pm

I have been using bluez 5.50 source compiled for Raspberry Pi 3 B . I did try to crosscompile it ( on X86) but kept running into issues.
I ended up building it on RPi and just copy the library to X86.
It looks as most of the "DBus" stuff" is unusable.
I am not sure I want to find out why or just start with fresh DBus source only.
But I need to find one with "configure" , I am not that comfortable to tackle autotools from scratch.

deepo
Posts: 854
Joined: Sun Dec 30, 2018 8:36 pm
Location: Denmark

Re: Programming bluetooth using C++

Thu Jun 13, 2019 7:27 pm

I stumbled upon TinyB from Intel:
TinyB exposes the BLE GATT API for C++, Java and other languages, using BlueZ over DBus.
https://github.com/intel-iot-devkit/tinyb

I was able to discover Bluetooth devices, listing their services etc.

But it does not seem to allow me to receive BLE advertisements, so I'm still on the hunt for something that can do that over DBus.

/Mogens

rogermorrell1
Posts: 3
Joined: Thu Nov 01, 2018 8:34 am

Re: Programming bluetooth using C++

Fri Mar 06, 2020 9:35 pm

Did you every get any further. I have a Android all that connects to a GATT service that supported by product from Silicon labs on another environment but am looking to use the Pi . I have tried to build the nettlep/gobbledegook from git hub but there is some issue with the glib-2.0 version on the standard (and latest?) Raspbian

Roger

deepo
Posts: 854
Joined: Sun Dec 30, 2018 8:36 pm
Location: Denmark

Re: Programming bluetooth using C++

Fri Mar 06, 2020 10:00 pm

No, I didn't dig any deeper.

/Mogens

rackflot
Posts: 1
Joined: Wed Apr 08, 2020 3:30 pm

Re: Programming bluetooth using C++

Wed Apr 08, 2020 3:33 pm

deepo wrote:
Wed May 29, 2019 8:48 pm
I have also tried to get Bluetooth communication code working from C++ - with varied success.
My goal is to intercept Bluetooth Low Energy (BLE) Advertisement messages, similar to Bluetooth beacon signals.
I have managed that using the Bluez Bluetooth stack.

My goal was to receive temperature measurements from Minew BLE tags that transmit measurements as BLE Advertisement messages.

That seems to work fine for me.

My next step was then to communicate with the BLE tag to program it, but I have not been able to do that yet.

Many sources on the interwebs says to look at the Bluez DBus API, as that is supposedly the better way to use the Bluez stack, but I have not found a way through yet.

Let me know if you want some of my sample code.

/Mogens
I would be interested. I have it working with blescan.py and it is ok. would like to recreate it in C or C++. I too would like to get the temp from the tag as I have a water proof beacon that I will be using to monitor pool temperature.

deepo
Posts: 854
Joined: Sun Dec 30, 2018 8:36 pm
Location: Denmark

Re: Programming bluetooth using C++

Thu Apr 09, 2020 3:56 pm

rackflot wrote:
Wed Apr 08, 2020 3:33 pm
deepo wrote:
Wed May 29, 2019 8:48 pm
I have also tried to get Bluetooth communication code working from C++ - with varied success.
My goal is to intercept Bluetooth Low Energy (BLE) Advertisement messages, similar to Bluetooth beacon signals.
I have managed that using the Bluez Bluetooth stack.

My goal was to receive temperature measurements from Minew BLE tags that transmit measurements as BLE Advertisement messages.

That seems to work fine for me.

My next step was then to communicate with the BLE tag to program it, but I have not been able to do that yet.

Many sources on the interwebs says to look at the Bluez DBus API, as that is supposedly the better way to use the Bluez stack, but I have not found a way through yet.

Let me know if you want some of my sample code.

/Mogens
I would be interested. I have it working with blescan.py and it is ok. would like to recreate it in C or C++. I too would like to get the temp from the tag as I have a water proof beacon that I will be using to monitor pool temperature.
This how far I got looking at code from various places:

Code: Select all

// From https://stackoverflow.com/questions/38334255/basic-ble-client-with-d-bus-bluez

#include <iostream>
#include <chrono>
#include <thread>
#include <cstdint>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

#include <glib.h>
#include <gio/gio.h>

#include <list>
#include <algorithm>

// sudo apt-get update
// sudo apt-get install bluez libbluetooth-dev libglib2.0-dev

// Compile with
// g++ -std=c++11 $(pkg-config --cflags glib-2.0 gobject-2.0 gio-2.0) ./bluez_dbus.cpp $(pkg-config --libs glib-2.0 gobject-2.0 gio-2.0 bluez) -o bluez_dbus

// Run with:
// sudo ./bluez_dbus

const u_char LE_ADV_REPORT = 0x02;

// https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/
const u_char EIR_FLAGS =                  0x01; /* flags */
const u_char EIR_UUID16_SOME =            0x02; /* 16-bit UUID, more available */
const u_char EIR_UUID16_ALL =             0x03; /* 16-bit UUID, all listed */
const u_char EIR_UUID32_SOME =            0x04; /* 32-bit UUID, more available */
const u_char EIR_UUID32_ALL =             0x05; /* 32-bit UUID, all listed */
const u_char EIR_UUID128_SOME =           0x06; /* 128-bit UUID, more available */
const u_char EIR_UUID128_ALL =            0x07; /* 128-bit UUID, all listed */
const u_char EIR_NAME_SHORT =             0x08; /* shortened local name */
const u_char EIR_NAME_COMPLETE =          0x09; /* complete local name */
const u_char EIR_TX_POWER =               0x0A; /* transmit power level */
const u_char EIR_DEVICE_ID =              0x10; /* device ID */
const u_char EIR_SERVICE_DATA =           0x16; /* service data */
const u_char EIR_MANUFACTURE_SPECIFIC =   0xFF;

void processData(uint8_t *data, size_t data_len, le_advertising_info *info)
{
    //printf("process_data: %d octets\n", (int)data_len);
    if (data[0] == EIR_NAME_SHORT || data[0] == EIR_NAME_COMPLETE)
    {
        size_t name_len = data_len - 1;
        char *name = (char *)malloc(name_len + 1);
        memset(name, 0, name_len + 1);
        memcpy(name, &data[1], name_len);

        char addr[18];
        ba2str(&info->bdaddr, addr);

        printf("addr=%s name=%s\n", addr, name);

        free(name);
    }
    else if (data[0] == EIR_FLAGS)
    {
        printf("-> Flag type: len=%d\n", (int)data_len);
        int i;
        for (i=1; i<data_len; i++)
        {
            printf("\tFlag data: 0x%02X\n", data[i]); // 0x06 -> 0000 0110
        }
        /*
         bit 0 LE Limited Discoverable Mode
         bit 1 LE General Discoverable Mode
         bit 2 BR/EDR Supported
         bit 3 Simultaneous LE and BR/EDR to Same Device Capable (controller)
         bit 4 Simultaneous LE and BR/EDR to Same Device Capable (Host)
        */
    }
    else if (data[0] == EIR_UUID16_ALL)
    {
        printf("-> UUID 16 All type: len=%d\n", (int)data_len);

        int i;
        printf("\tUUIDs: ");
        for (i=1; i<data_len; i += 2)
        {
            printf("0x%02X%02X ", data[i], data[i+1]);
        }
        printf("\n");
    }
    else if (data[0] == EIR_MANUFACTURE_SPECIFIC)
    {
        printf("-> Manufacture specific type: len=%d\n", (int)data_len);

        // https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers/
        // TODO int company_id = data[current_index + 2] 

        // https://www.silabs.com/community/wireless/bluetooth/knowledge-base.entry.html/2017/11/14/bluetooth_advertisin-zCHh
        // int company_id = data[2] + 256 * data[1];
        // printf("Company ID: 0x%04X\n", company_id);

        int i;
        printf("\tData: ");
        for (i=1; i<data_len; i++)
        {
            printf("0x%02X ", data[i]);
        }
        printf("\n");
    }
    else if (data[0] == EIR_UUID128_SOME)
    {
        printf("-> UUID 128 type: len=%d\n", (int)data_len);
        printf("\t");
        int i;
        for (i=data_len-1; i>0; i--)
        {
            printf("%02x", data[i]);
        }
        printf("\n");
    }
    else if (data[0] == EIR_SERVICE_DATA)
    {
        printf("-> Service Data type: len=%d\n", (int)data_len);
        // Minew S1 data is 16 bytes
        if (data_len == 16)
        {
            // UUID = 0xFFE1 (little endian)
			// Not listed here: https://www.bluetooth.com/specifications/gatt/services/
            if (data[1] == 0xE1 && data[2] == 0xFF)
            {
                // Frame type 0xA1, Product Model 0x01
                if (data[3] == 0xA1 && data[4] == 0x01)
                {
                    uint8_t batteryPct = data[5];
                    printf("\tBattery percentage: %d\n", batteryPct);
                    float temperature = (float)data[6] + ((float)data[7] / 100.0);
                    printf("\tTemperature: %.2f C\n", temperature);
                    float humidity = (float)data[8] + ((float)data[9] / 100.0);
                    printf("\tHumidity: %.2f %%\n", humidity);
                }
            }
        }
    }
    else
    {
        printf("-> Unhandled AD type: 0x%02X\n", data[0]);
    }
}

// based on hcitool lescan
bool receiveAdv(int dd, std::chrono::seconds timeout, std::list<std::string> &devices)
{
    u_char buff[HCI_MAX_EVENT_SIZE];
    u_char *ptr;
    hci_filter filter;

    hci_filter_clear(&filter);
    hci_filter_set_ptype(HCI_EVENT_PKT, &filter);
    hci_filter_set_event(EVT_LE_META_EVENT, &filter);

    if (setsockopt(dd, SOL_HCI, HCI_FILTER, &filter, sizeof(filter)) < 0)
    {
        std::cerr << "Could not set socket options" << std::endl;
        return false;
    }

    using namespace std::chrono;
    time_point<steady_clock> start = steady_clock::now();
    while (steady_clock::now() - start < timeout)
    {
        if (read(dd, buff, sizeof(buff)) < 0)
        {
            std::this_thread::sleep_for(milliseconds(20));
            continue;
        }

        ptr = buff + (1 + HCI_EVENT_HDR_SIZE);
        evt_le_meta_event *meta = reinterpret_cast<evt_le_meta_event *>(ptr);

        if (meta->subevent != LE_ADV_REPORT)
            continue;

        le_advertising_info *info = reinterpret_cast<le_advertising_info *>(meta->data + 1);
        char addr[18];
        ba2str(&info->bdaddr, addr);
        int rssi = info->data[info->length]; //intentional, isn't out of bounds

        // Add new devices to list
        std::list<std::string>::iterator it = devices.begin();
        bool found = false;
        while (it != devices.end())
        {
            if (*it == std::string(addr))
                found = true;
            it++;
        }
        if (!found)
        {
            std::cout << "Detected device: " << addr << " " << rssi << std::endl;
            devices.push_back(std::string(addr));
        }

        if (info->length != 0)
        {
            int current_index = 0;
            int data_error = 0;
            while (!data_error && current_index < info->length)
            {
                size_t data_len = info->data[current_index];
                if (data_len + 1 > info->length)
                {
                    printf("EIR data length is longer than EIR packet length. %d + 1 > %d", (int)data_len, info->length);
                    data_error = 1;
                }
                else
                {
                    std::string btaddr(addr);
                    if (btaddr == "AC:23:3F:A0:02:B6" || btaddr == "AC:23:3F:A0:01:C4" || btaddr == "AC:23:3F:A0:3B:73" || btaddr == "AC:23:3F:A0:01:F8")
                    {
                        processData(info->data + current_index + 1, data_len, info);
                    }
                    current_index += data_len + 1;
                }
            }
        }
    }

    return true;
}

bool scan(unsigned timeout, std::list<std::string> &devices)
{
    int devId = hci_get_route(nullptr);
    int dd = hci_open_dev(devId);
    if (devId < 0 || dd < 0) {
        std::cerr << "Could not open device" << std::endl;
        return false;
    }

    uint8_t localAddr = LE_PUBLIC_ADDRESS; //LE_PUBLIC_ADDRESS to use public on local device, LE_RANDOM_ADDRESS to use random
    uint8_t scanType = 0x01; //0x01 = active, 0x00 = passive
    uint8_t filterPolicy = 0x00; //0x00 = don't use whitelist, 0x01 = use whitelist
    uint16_t interval = htobs(0x0010); //no idea, default for all except 'g' or 'l' filters that use htobs(0x0012)
    uint16_t window = htobs(0x0010); //no idea, default for all except 'g' or 'l' filters that use htobs(0x0012)
    uint8_t filterDup = 0x00; // 0x01 = filter duplicates, 0x00 = receive duplicates
    int hciTimeout = 10000; // this is timeout for communication with the local adapter, not scanning

    if (hci_le_set_scan_parameters(dd, scanType, interval, window, localAddr, filterPolicy, hciTimeout) < 0) {
        std::cerr << "Set scan parameters failed" << std::endl;
        hci_close_dev(dd);
        return false;
    }

    uint8_t scanEnable = 0x01;
    if (hci_le_set_scan_enable(dd, scanEnable, filterDup, hciTimeout) < 0) {
        std::cerr << "Enable scan failed" << std::endl;
        hci_close_dev(dd);
        return false;
    }

    if (receiveAdv(dd, std::chrono::seconds(timeout), devices) < 0) {
        std::cerr << "Could not receive advertising events" << std::endl;
        hci_close_dev(dd);
        return false;
    }

    uint8_t scanDisable = 0x00;
    if (hci_le_set_scan_enable(dd, scanDisable, filterDup, hciTimeout) < 0) {
        std::cerr << "Disable scan failed" << std::endl;
        hci_close_dev(dd);
        return false;
    }

    hci_close_dev(dd);
    return true;
}

// https://stackoverflow.com/questions/2896600/how-to-replace-all-occurrences-of-a-character-in-string
std::string ReplaceAll(std::string str, const std::string& from, const std::string& to)
{
    size_t start_pos = 0;
    while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
    }
    return str;
}

GDBusProxy *connect(const char *addr)
{
    GError *err = nullptr;

    std::string ble_addr(addr);
    ble_addr = ReplaceAll(ble_addr, ":", "_");

    std::string objPath = ReplaceAll(std::string("/org/bluez/hci0/dev_[DEV_ADDR]"), std::string("[DEV_ADDR]"), ble_addr);
    std::cout << "Connect path: " << objPath << std::endl;

//    char objPath[sizeof("/org/bluez/hci0/dev_AC_23_3F_A0_02_B6")] = "/org/bluez/hci0/dev_AC_23_3F_A0_02_B6";
    GDBusProxy *devProxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, "org.bluez", objPath.c_str(), "org.bluez.Device1", nullptr, &err);
    if (!devProxy) {
        std::cerr << "Device " << addr << " not available: " << err->message << " (" << err->code << ")" << std::endl;
        g_clear_error(&err);
        return nullptr;
    }
    if (g_dbus_proxy_call_sync(devProxy, "Connect", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &err)) {
        if (!g_dbus_proxy_call_sync(devProxy, "Pair", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &err)) {
            std::cerr << "Failed to pair: " << err->message << " (" << err->code << ")" << std::endl;
            g_clear_error(&err);
            return nullptr;
        }
    }
    else {
        std::cerr << "Failed to connect: " << err->message << " (" << err->code << ")" << std::endl;
        g_clear_error(&err);
        devProxy = nullptr;
    }
    return devProxy;
}

bool disconnect(GDBusProxy *devProxy)
{
    if (devProxy != nullptr)
    {
        GError *err = nullptr;
        if (!g_dbus_proxy_call_sync(devProxy, "Disconnect", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &err)) {
            std::cerr << "Failed to disconnect - " << err->message << "(" << err->code << ")" << std::endl;
            g_clear_error(&err);
            return false;
        }
    }
    return true;
}

GVariant *read(const char *addr)
{
//    const char *objPath("/org/bluez/hci0/dev_AC_23_3F_A0_02_B6/service0013/char0014");
	std::string ble_addr(addr);
	ble_addr = ReplaceAll(ble_addr, ":", "_");

	std::string objPath = ReplaceAll(std::string("/org/bluez/hci0/dev_[DEV_ADDR]/service0013/char0014"), std::string("[DEV_ADDR]"), ble_addr);
	std::cout << "Read path: " << objPath << std::endl;

    GVariantBuilder *b = g_variant_builder_new(G_VARIANT_TYPE("({sv})"));
    g_variant_builder_add(b, "{sv}", "offset", g_variant_new_uint16(0));
    GVariant *args = g_variant_builder_end(b);

    GError *err = nullptr;
    GDBusProxy *charProxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, "org.bluez", objPath.c_str(), "org.bluez.GattCharacteristic1", nullptr, &err);
    GVariant *ret = g_dbus_proxy_call_sync(charProxy, "ReadValue", args, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &err);
    if (ret == FALSE) {
        std::cerr << "Failed to read - " << err->message << "(" << err->code << ")" << std::endl;
        g_clear_error(&err);
        return nullptr;
    }

    return ret;
}

int main()
{
    std::list<std::string> devices;
    scan(10, devices);

    std::list<std::string>::iterator it = devices.begin();
    while (it != devices.end())
    {
        std::cout << "--------------- " << *it << " ---------------" << std::endl;

        GDBusProxy *proxy = connect((*it).c_str());
        if (proxy) {
            GVariant *ret = read((*it).c_str());
        }
        disconnect(proxy);

        it++;
    }

//    GDBusProxy *proxy = connect("AC:23:3F:A0:3B:73");
//    if (proxy) {
//        GVariant *ret = read("AC:23:3F:A0:3B:73");
//    }
//    disconnect(proxy);

    return 0;
}
The code doesn't do much, unless you have a Minew BLE tag. So you'll have to add decoding of your specific BLE tag.
I just tested compiling and running it on Buster, so I hope you can get it to work.

I also took inspiration from http://tvaira.free.fr/flower-power/ble-scan.c

/Mogens

david_mawer
Posts: 1
Joined: Sat Jul 18, 2020 3:55 pm

Re: Programming bluetooth using C++

Sat Jul 18, 2020 3:59 pm

Hi there,

So - I had a similar problem - looking for anything that makes sense writing c++ code to handle Bluetooth.

In the end - got something working that allowed me to get signals from an external Bluetooth device to my Raspberry PI.

I've uploaded my code to a public GIT Repository here : - https://bitbucket.org/david_mawer/bluet ... rc/master/

Hoping that it can help you.

lurk101
Posts: 964
Joined: Mon Jan 27, 2020 2:35 pm
Location: Cumming, GA (US)

Re: Programming bluetooth using C++

Sun Jul 19, 2020 12:54 am

Douglas6 wrote:
Thu May 30, 2019 1:04 am
AnneRanch wrote:
Thu May 30, 2019 12:21 am
I have not found SINGLE documentation in "blueZ" package ( source code ) about D_Bus usage.
Did you look into the BlueZ github directory as I recommended?
Oh indeed we have, but examples is not documentation. The BlueZ Bluetooth, and now LE, stack is a mishmash of various ad hoc protocols more or less integrated, and surprisingly poorly documented. The typical response to information requests is 'go read the code'.

Return to “C/C++”