Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BLE support missing #55

Closed
monacoprinsen opened this issue Feb 25, 2022 · 32 comments
Closed

BLE support missing #55

monacoprinsen opened this issue Feb 25, 2022 · 32 comments

Comments

@monacoprinsen
Copy link

monacoprinsen commented Feb 25, 2022

I am trying to use the esp32 Wifi+Bluetooth module. Although the wifi functionality is working I did not find any way of getting the Bluetooth to work using Rust.

It would be great to have this option as well since many IoT projects require Bluetooth support.

@jessebraham
Copy link
Member

We discussed this briefly today in the community meeting.

Unfortunately, none of our current maintainers seems to have much or any experience with Bluetooth. Given the complexity of the protocol this makes defining traits incredibly difficult, if not impossible. We really need somebody with expertise to do this properly, so that's our first blocking point.

One potential option is to try and find examples of Bluetooth stacks written in Rust for other platforms. I'm not really sure what is out there, or if there has been any serious work done for this at all. However, if we were able to find some implementation(s) we would at least have some inspiration as to how our API might look.

If there are any further updates on this topic I will share them here, but it's unfortunately looking like one or more community members will need to tackle this on their own, otherwise there will likely be quite the wait.

@lherman-cs
Copy link

How about continuing Rubble's work,https://github.com/jonas-schievink/rubble? The project seems to be outdated, it only supports Bluetooth 4.2 and NRF MCUs only, but it's designed to be hardware-independent.

At the very least, I think we can learn from their project structure and flow.

@ivmarkov
Copy link
Collaborator

Rubble is not seeing a lot of development lately so I'm skeptical that it can be used in any shape or form.

There are actually some sample wrappers of the ESP-IDF BT stacks implemented by community members in the meantime. We are only waiting for them to find some time to publish those.

@Witcher01 Witcher01 mentioned this issue Nov 18, 2022
@wassup-
Copy link

wassup- commented Mar 4, 2023

I think it would be handy to list some of these sample wrappers.
The only one that I could find is https://github.com/pyaillet/esp-idf-ble.

@persello
Copy link
Contributor

persello commented Mar 4, 2023

If it's useful to you, I created a bluedroid wrapper: https://github.com/persello/bluedroid.

@ivmarkov ivmarkov changed the title Bluetooth support missing BLE support missing Sep 21, 2023
@ivmarkov
Copy link
Collaborator

I have updated the title of the bug to indicate that this issue is now about BLE.

Classic BT (esp32 only, of course) is in the meantime supported, under the experimental flag, in mainline, and will be released soon. Not all protocols are implemented, but they can be - incrementally, when the need arises. and the overall framework how to implement those is in the meantime in place.

As for BLE - at least the Bluedroid APIs can also be easily mapped as they should follow the same approach as the Classic BT. And will share the same underlying driver (BtDriver). There is even a commented out code that is midway into implementing BLE on top of Bluedroid.

@thedevleon
Copy link

thedevleon commented Sep 29, 2023

As for BLE - at least the Bluedroid APIs can also be easily mapped as they should follow the same approach as the Classic BT. And will share the same underlying driver (BtDriver). There is even a commented out code that is midway into implementing BLE on top of Bluedroid.

Hi ivmarkov, just found this thread after searching for BLE support on the esp32-c3 in Rust. Can you elaborate a bit on what needs to be done and how I could get a first example running? You mentioned some commented out code, I guess you mean this? https://github.com/esp-rs/esp-idf-svc/blob/master/src/bt/ble/gatt/server.rs#L265

I have also tried to compile bluedroid with the latest cargo packages and esp-idf v5.1 in the meantime (https://github.com/thedevleon/bluedroid/tree/upgrade), but it fails with a lot of errors regarding pthreads (same error messages as here: esp-rs/esp-idf-hal#289).

@FrigoEU
Copy link

FrigoEU commented Oct 12, 2023

I'd also be very interested to know how to get started with BLE using this library, or what still needs doing.

I've managed to get a simple BLE GATT server working using the following library https://github.com/pyaillet/esp-idf-ble, but I'd much rather use this "official" well maintained libary. Thanks for all the work on it!

@thedevleon
Copy link

I'd also be very interested to know how to get started with BLE using this library, or what still needs doing.

I've managed to get a simple BLE GATT server working using the following library https://github.com/pyaillet/esp-idf-ble, but I'd much rather use this "official" well maintained libary. Thanks for all the work on it!

In the meantime, I have found this library, which works very well and covers all my needs: https://lib.rs/crates/esp32-nimble

@FrigoEU
Copy link

FrigoEU commented Oct 12, 2023

I'd also be very interested to know how to get started with BLE using this library, or what still needs doing.
I've managed to get a simple BLE GATT server working using the following library https://github.com/pyaillet/esp-idf-ble, but I'd much rather use this "official" well maintained libary. Thanks for all the work on it!

In the meantime, I have found this library, which works very well and covers all my needs: https://lib.rs/crates/esp32-nimble

I've actually also tried to use this library, but failed to get it working since the rest of my project is using the standard library. As far as I understand the esp32-nimble crate works only in an no-std environment?

@ivmarkov
Copy link
Collaborator

I've actually also tried to use this library, but failed to get it working since the rest of my project is using the standard library. As far as I understand the esp32-nimble crate works only in an no-std environment?

No, completely the opposite. esp32-nimble seems to require ESP IDF and it does depend on esp-idf-svc and friends.

@FrigoEU
Copy link

FrigoEU commented Oct 12, 2023

I've actually also tried to use this library, but failed to get it working since the rest of my project is using the standard library. As far as I understand the esp32-nimble crate works only in an no-std environment?

No, completely the opposite. esp32-nimble seems to require ESP IDF and it does depend on esp-idf-svc and friends.

That's what I thought when I first found it! But when I looked through the examples (eg: https://github.com/taks/esp32-nimble/blob/develop/examples/ble_server.rs) it says #![no_std] and that made me terribly confused. I also just tried the code in my project verbatim (apart from the no_std annotation mentioned above) and couldn't get it working, so I chalked it up to the std <> no_std divide. I'm probably making a big reasoning error somewhere, but can't figure out where!

@ivmarkov
Copy link
Collaborator

ivmarkov commented Oct 12, 2023

I'd also be very interested to know how to get started with BLE using this library, or what still needs doing.

I've managed to get a simple BLE GATT server working using the following library https://github.com/pyaillet/esp-idf-ble, but I'd much rather use this "official" well maintained libary. Thanks for all the work on it!

@FrigoEU @thedevleon There are not yet "official" bindings for BLE, yet what is there is pretty close: you need to uncomment this line and then work on the ble module by making it compile and then fix all possible bugs.

The ble module is based on BlueDroid though, not on NimBLE. We might have NimBLE implementation in future as well, but I have no time for that, so somebody has to pick it up. Perhaps by taking the esp32-nimble project, adjusting it to work on top of esp-idf-svc's BtDriver, removing as many allocations as possible (we don't usually need those), and making the API similar (or identical) to the one via which BlueDroid BLE is exposed. As in getting rid of all the Lazy / OnceCell stuff by following the singleton pattern used for BtDriver and for the ClassicBT servers (Gap, A2dp, Avrc and so on).

If you are just starting with embedded, this is not an easy task. In the meantime, just use esp32-nimble.

@jasta is anyway working on BLE traits, and I think he has a working implementation on top of NimBLE for the esp32.
@taks might be interested in contributing his lib into esp-idf-svc as well.

@ivmarkov
Copy link
Collaborator

ivmarkov commented Oct 12, 2023

I've actually also tried to use this library, but failed to get it working since the rest of my project is using the standard library. As far as I understand the esp32-nimble crate works only in an no-std environment?

No, completely the opposite. esp32-nimble seems to require ESP IDF and it does depend on esp-idf-svc and friends.

That's what I thought when I first found it! But when I looked through the examples (eg: https://github.com/taks/esp32-nimble/blob/develop/examples/ble_server.rs) it says #![no_std] and that made me terribly confused. I also just tried the code in my project verbatim (apart from the no_std annotation mentioned above) and couldn't get it working, so I chalked it up to the std <> no_std divide. I'm probably making a big reasoning error somewhere, but can't figure out where!

That's because most of the esp-rs folks are constantly branding the ESP IDF (esp-idf-*) crates as the "STD" crates, which - to the community - often means "STD"-only, while what it actually means is that these crates CAN be used, and DO support "STD" as well, but don't mandate it. In contrast, the baremetal (esp-hal) crates DO NOT support "std" simply because - unlike the esp-idf-* crates - they do not "implement" the STD threads, sockets etc. Not that the esp-idf-* crates "implement" sockets and threads themselves. Actually ESP IDF itself does, by providing a POSIX API, which Rust STD library upstream can map and use directly (well, almost directly - we had to upstream a few changes to upstream Rust STD library so that it maps ESP IDF cleanly back in time.)

Regardless, esp-idf-* crates can also be compiled and used with no_std as well, and also with or without alloc (though without alloc a lot of functionality is missing). Because in general, no_std is a strict subset of STD, not a negation of it.

And @taks probably did his crate no_std simply because "why not". And he was right. Why not - using no_std makes you think what APIs you really need - and - moreover, when you really need alloc. Especially useful for libraries. That's also why the esp-idf-* crates are no_std-compatible as well. Even if 99.9% of the community (in their "apps", not libraries) uses them with STD, as STD gives them threads, sockets and whatnot which are otherwise difficult.

@FrigoEU
Copy link

FrigoEU commented Oct 12, 2023

That really clarifies a lot. Thank you so much! I'll read this again tomorrow until it's engrained in my brain :).

In the meantime, I'll see why esp32-nimble wasn't working for me.

@ivmarkov
Copy link
Collaborator

That really clarifies a lot. Thank you so much! I'll read this again tomorrow until it's engrained in my brain :).

In the meantime, I'll see why esp32-nimble wasn't working for me.

Just take this example again, paste it in a esp-idf-template-generated project with "STD enabled", remove all #[] annotations, and try to compile. It should work fine then.

@ivmarkov
Copy link
Collaborator

Oh and remove this completely:

#[panic_handler]
#[allow(dead_code)]
fn panic(info: &core::panic::PanicInfo) -> ! {
  ::log::error!("{:?}", info);
  unsafe { esp_idf_sys::abort() }
}

@jasta
Copy link
Contributor

jasta commented Oct 12, 2023

@jasta is anyway working on BLE traits, and I think he has a working implementation on top of NimBLE for the esp32.
@taks might be interested in contributing his lib into esp-idf-svc as well.

I haven't implemented ble-peripheral for esp32 yet (I implemented bluer-ble-peripheral for the host first because it's way easier to test), but based on your feedback and seeing some potentially thorny gotchas I'm going to start looking at that now. I don't anticipate this work will take me more than a few weeks to settle and publish to crates.io.

@LarryMerino
Copy link

That really clarifies a lot. Thank you so much! I'll read this again tomorrow until it's engrained in my brain :).

In the meantime, I'll see why esp32-nimble wasn't working for me.

Here I leave you the basic example using the esp-idf (STD) crate.

It works for esp32-c3 but I have not tested it for esp32. Be careful because they recently updated the crate to version 0.2.1 and it does not work for me with this new version, it works for me with version 0.2.0

I use this library but keep in mind that if you are going to use it with iPhone, there are some things that don't quite go well for me with the bounding issue

taks/esp32-nimble#24

I hope this helps you.

use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
use log::*;

use esp32_nimble::{uuid128, BLEDevice, NimbleProperties};

fn main() {
    // It is necessary to call this function once. Otherwise some patches to the runtime
    // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
    esp_idf_sys::link_patches();
    // Bind the log crate to the ESP Logging facilities
    esp_idf_svc::log::EspLogger::initialize_default();

    info!("Hello, world!");

    let ble_device = BLEDevice::take();

    let server = ble_device.get_server();
    server.on_connect(|server, desc| {
        info!("Client connected");

        server
            .update_conn_params(desc.conn_handle, 24, 48, 0, 60)
            .unwrap();

        ::log::info!("Multi-connect support: start advertising");
        ble_device.get_advertising().start().unwrap();
    });
    let service = server.create_service(uuid128!("fafafafa-fafa-fafa-fafa-fafafafafafa"));

    // A static characteristic.
    let static_characteristic = service.lock().create_characteristic(
        uuid128!("d4e0e0d0-1a2b-11e9-ab14-d663bd873d93"),
        NimbleProperties::READ,
    );
    static_characteristic
        .lock()
        .set_value("Hello, world!".as_bytes());

    // A characteristic that notifies every second.
    let notifying_characteristic = service.lock().create_characteristic(
        uuid128!("a3c87500-8ed3-4bdf-8a39-a01bebede295"),
        NimbleProperties::READ | NimbleProperties::NOTIFY,
    );
    notifying_characteristic.lock().set_value(b"Initial value.");

    // A writable characteristic.
    let writable_characteristic = service.lock().create_characteristic(
        uuid128!("3c9a3f00-8ed3-4bdf-8a39-a01bebede295"),
        NimbleProperties::READ | NimbleProperties::WRITE,
    );
    writable_characteristic
        .lock()
        .on_read(move |_, _| {
            ::log::info!("Read from writable characteristic.");
        })
        .on_write(move |args| {
            ::log::info!("Wrote to writable characteristic: {:?}", args.recv_data);
        });

    let ble_advertising = ble_device.get_advertising();
    ble_advertising
        .name("ESP32-C3")
        .add_service_uuid(uuid128!("68f41eac-ee28-11ec-8ea0-0242ac120002"));

    ble_advertising.start().unwrap();

    let mut counter = 0;
    loop {
        esp_idf_hal::delay::FreeRtos::delay_ms(1000);
        notifying_characteristic
            .lock()
            .set_value(format!("Counter: {counter}").as_bytes())
            .notify();

        counter += 1;
    }
}

@FrigoEU
Copy link

FrigoEU commented Oct 13, 2023

Hey Larry,

Thanks a lot for your time!

In the meantime I also managed to get esp32-nimble working on my project. However, I did have to downgrade to version 1.4. Both 2.0 and 2.1 didn't work well for me. See https://github.com/taks/esp32-nimble/issues/29

@vaknin
Copy link

vaknin commented Jan 30, 2024

What is preventing adding 'esp32-nimble' to 'esp-idf-svc' and closing this issue?

@ivmarkov
Copy link
Collaborator

What is preventing adding 'esp32-nimble' to 'esp-idf-svc' and closing this issue?

@taks Any interest in contributing your library and merging it/adjusting it with what is already available here?

@Vollbrecht
Copy link
Collaborator

What is preventing adding 'esp32-nimble' to 'esp-idf-svc' and closing this issue?

ble alone is a huge thing by itself, and the development is still pretty much underway, so a lot of breaking things. esp-idf-svc is also not finished in that sense, but i think it make sense for ergonomic reasons to have them separated until they settled down a bit.

But i think we can try to promote esp-nimble more inside esp-idf-* eco system so the discoverability is better for interested users.

@taks
Copy link
Contributor

taks commented Jan 31, 2024

@taks Any interest in contributing your library and merging it/adjusting it with what is already available here?

Currently, 'esp32-nimble' has some bad code and I frequently modify it.
(includes breaking changes)
I'm interested in merging into 'esp-idf-svc', but merging requires more modifications.

As @Vollbrecht mentioned, I think it's better to develop them separately until they settled down a bit.

@reformc
Copy link

reformc commented Aug 27, 2024

Is there any gatt client library available? Nimble has some bugs that are still unresolved and cannot be used

@ivmarkov
Copy link
Collaborator

Is there any gatt client library available? Nimble has some bugs that are still unresolved and cannot be used

Gatt "client" library specifically, or gatt server/peripheral, which is in 99% what you need in the MCU?

There are now also Bluedroid bindings in the esp-idf-svc itself, so you can try these. Here's an example. You need to pass the experimental feature to esp-idf-svc for these though.

@reformc
Copy link

reformc commented Aug 28, 2024

Is there any gatt client library available? Nimble has some bugs that are still unresolved and cannot be used

Gatt "client" library specifically, or gatt server/peripheral, which is in 99% what you need in the MCU?

There are now also Bluedroid bindings in the esp-idf-svc itself, so you can try these. Here's an example. You need to pass the experimental feature to esp-idf-svc for these though.

ble controller

@ivmarkov
Copy link
Collaborator

Is there any gatt client library available? Nimble has some bugs that are still unresolved and cannot be used

Gatt "client" library specifically, or gatt server/peripheral, which is in 99% what you need in the MCU?
There are now also Bluedroid bindings in the esp-idf-svc itself, so you can try these. Here's an example. You need to pass the experimental feature to esp-idf-svc for these though.

ble controller

You always need a BLE controller and there is one. But after that, your device has to assume either the role of a gatt server/peripheral or a gatt client. Or both (which is rare).

Oh well. You have the example and the exposed APIs in esp-idf-svc so I guess you can see for yourself whether what is there would suit your needs or not. :)

@ivmarkov
Copy link
Collaborator

Closing since the Bluedroid bindings are available since the last release of esp-idf-svc.

@github-project-automation github-project-automation bot moved this from Todo to Done in esp-rs Aug 28, 2024
@joebnb
Copy link

joebnb commented Dec 13, 2024

image image

why i still not get bt with latest idf svc

@ivmarkov
Copy link
Collaborator

image image
why i still not get bt with latest idf svc

Because you need to enable BT in sdkconfig.defaults?

@joebnb
Copy link

joebnb commented Dec 14, 2024

image image
why i still not get bt with latest idf svc

Because you need to enable BT in sdkconfig.defaults?

it was added, i found it need restart devcontainer and vscode after that bt trait shows up,thanks for advice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

No branches or pull requests