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

Support for Master mode, Pin and SSP #3219

Merged
merged 44 commits into from Oct 1, 2019
Merged

Support for Master mode, Pin and SSP #3219

merged 44 commits into from Oct 1, 2019

Conversation

IonicEV
Copy link
Contributor

@IonicEV IonicEV commented Sep 17, 2019

I witnessed a lot of folks struggling with master mode on ESP32 (initiating connection to other slave devices). Some examples were available(example_spp_initiator_demo.c), but they lacked support for IO, congestions and other aspects covered nicely in original BluetoothSerial class. I took a step forward and combined code provided in example_spp_initiator_demo.c and BluetoothSerial class to enable Master mode, Pin and SSP for legacy BT in BluetoothSerial class. Hopefully, you would find it useful.

@IonicEV
Copy link
Contributor Author

IonicEV commented Sep 17, 2019

Looks like build #2408.4 errored out due to inability to access main repo, please advise.

fatal: unable to access 'https://github.com/espressif/arduino-esp32.git/': Failed to connect to github.com port 443: Connection timed out

@IonicEV
Copy link
Contributor Author

IonicEV commented Sep 17, 2019

All checks are passed, what is the next step, please forgive me - it is first time for me on github.

@luc-github
Copy link
Contributor

Just wait - review will be done with some feedback ^_^

@me-no-dev
Copy link
Member

Very nice :) this is really useful!
But, some of the techniques, excessive logging, too many static variables, constants, not using proper API to wait for events. It all makes the code a bit hard to read and not so efficient to execute. How about I give you a hand and touch up a bit your additions?

@IonicEV
Copy link
Contributor Author

IonicEV commented Sep 17, 2019

Sure, let me push the latest iteration that uses resolved address as preference on connect() and get rid of redundant _remote_address, and more of technique in example. all done on my side. I see [Event Group API] is used for signaling in existing code.

@IonicEV
Copy link
Contributor Author

IonicEV commented Sep 17, 2019

Pushed pin logic re-work

@IonicEV
Copy link
Contributor Author

IonicEV commented Sep 17, 2019

I made some effort to address some of the issues you noted. I was not sure you have time to work on it, as you could be quite busy. Hopefully, you need to spend less time refactoring the code.

@IonicEV
Copy link
Contributor Author

IonicEV commented Sep 18, 2019

At this point my only concerns are with delegation to user to set timeouts to keep it from any unexpected crash due to concurrency. I timed the ops and have pretty good idea how to set timeouts in connect() and disconnect() operations appropriately, so the result code would reflect the true state, not just async API call return value.

Victor Tchistiak added 2 commits September 18, 2019 11:04
…currency and more authoritative status returned back to caller. Automatic disconnect in connect() methods
@wolph
Copy link
Contributor

wolph commented Nov 3, 2019

I think I found the issue and I don't see at all how it ever could have worked correctly for you, but maybe something else had initialized the variables different for you @IonicEV :)

static bool waitForConnect(int timeout) {
    TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
    return (xEventGroupWaitBits(_spp_event_group, SPP_CONNECTED, pdFALSE, pdTRUE, xTicksToWait) != 0);
}

That code is pretty wrong, it's returning whether any of the bits is non-zero. It should be like this instead:

static bool waitForConnect(int timeout) {
    TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
    return (xEventGroupWaitBits(_spp_event_group, SPP_CONNECTED, pdFALSE, pdTRUE, xTicksToWait) & SPP_CONNECTED) != 0;
}

@IonicEV
Copy link
Contributor Author

IonicEV commented Nov 3, 2019

That code is pretty wrong, it's returning whether any of the bits is non-zero. It should be like this instead:

static bool waitForConnect(int timeout) {
    TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
    return (xEventGroupWaitBits(_spp_event_group, SPP_CONNECTED, pdFALSE, pdTRUE, xTicksToWait) & SPP_CONNECTED) != 0;
}

You can try it at will - just rebuild your sketch with local updated code in waitForConnect(). I do not think it makes any difference though as only SPP_CONNECTED bit is analyzed, so no other bits are relevant. It does not even need !=0 (was added for better compliance). The ESP32 BT core library triggers event on successful connection. The code in BluetoothSerial.* is just an enabler to expose this functionality.
It means you have to look into following for answers:
esp_bt.h
esp_bt_main.h
esp_gap_bt_api.h
esp_bt_device.h
esp_spp_api.h

@wolph
Copy link
Contributor

wolph commented Nov 3, 2019

I did, and it does make a difference which is why I said it was broken :)

When printing the output for xEventGroupWaitBits I received 13 (0b1101) which includes all bits except the SPP_CONNECTED = 0x02.

@IonicEV
Copy link
Contributor Author

IonicEV commented Nov 3, 2019

Submit the fix. If you need any assistance with it let me know. Also, look at other calls to xEventGroupWaitBits, as those need to be protected as well.

@IonicEV
Copy link
Contributor Author

IonicEV commented Nov 3, 2019

I just checked my sources and I have:

static bool waitForConnect(int timeout) {
    TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
    return (xEventGroupWaitBits(_spp_event_group, SPP_CONNECTED, pdFALSE, pdTRUE, xTicksToWait) & SPP_CONNECTED);
}

bool BluetoothSerial::disconnect() {
    if (_spp_client) {
        flush();
        log_i("disconnecting");
        if (esp_spp_disconnect(_spp_client) == ESP_OK) {
            TickType_t xTicksToWait = READY_TIMEOUT / portTICK_PERIOD_MS;
            return (xEventGroupWaitBits(_spp_event_group, SPP_DISCONNECTED, pdFALSE, pdTRUE, xTicksToWait) & SPP_DISCONNECTED);
        }
    }
    return false;
}

bool BluetoothSerial::isReady(bool checkMaster, int timeout) {
    if (checkMaster && !_isMaster) {
        log_e("Master mode is not active. Call begin(localName, true) to enable Master mode");
        return false;
    }
    if (!btStarted()) {
        log_e("BT is not initialized. Call begin() first");
        return false;
    }
    TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
    return (xEventGroupWaitBits(_spp_event_group, SPP_RUNNING, pdFALSE, pdTRUE, xTicksToWait) & SPP_RUNNING);
}

Not sure at what point it deviated from repo. Possibly, last minute changes before merge to add != 0 to make the whole expression a "true" bool as it was done on different laptop.

@wolph
Copy link
Contributor

wolph commented Nov 3, 2019 via email

@mprowe
Copy link

mprowe commented Nov 5, 2019

Thank you very much. Looking forward to trying it out here.
By the way, and I'm showing my ignorance now, how do I get your fix into my system?
Does it become version 1.0.5 and I upgrade via the Arduino library manager?
~Martin

@wolph
Copy link
Contributor

wolph commented Nov 5, 2019

Look for the BluetoothSerial.cpp file on your system and replace that with this file: https://github.com/espressif/arduino-esp32/blob/f0e2e2a62fe98ec9657f3935c41c88a0fd0e7acd/libraries/BluetoothSerial/src/BluetoothSerial.cpp

@mprowe
Copy link

mprowe commented Nov 5, 2019

Thank you Rick,

It works a treat. With your new BluetoothSerial.cpp, it connects and more importantly, does not connect (and correctly reporting this fact) when it shouldn't.
Thanks once again. I can now move on to with my project to read my Motorhome OBD info.

I still have questions regarding this library. I this the correct forum to ask? Or is it reserved for you experts?

Many regards, ~Martin

@ahmedwahdan
Copy link

Hello,
It doesn't work for me while try making the ESP connect with my andriod bluetooth.

@jsodeman
Copy link

jsodeman commented Jan 8, 2020

@wolph I replaced my local BluetoothSerial.cpp file with the one you linked on Nov 5th. My code went from falsely showing that it connected every time to giving me a "Stack smashing protect failure!". This thread covers a long time span so I'm not clear if I need to roll the ESP32 library back also, or do something else to get it working.

Edit: I'm on 1.11.1 currently

@wolph
Copy link
Contributor

wolph commented Jan 9, 2020

@jsodeman: while my patch fixes that bug, that doesn't mean it properly works. I've personally given up and I'm using a HC-05 now. Alternatively the bluestacks implementation works better as well.

@jsodeman
Copy link

jsodeman commented Jan 9, 2020

Thanks, I was wondering if using a HC-05 was a better direction as well. Or alternately if I was going to have to dig into the lower levels in IDF.

Since you've got more experience with this, maybe you can point me in the right direction. What I'm trying to achieve is to manually pair the esp32 with a phone once, and then have the esp32 be able to check to see if it can connect to the phone later via bluetooth or ble without having to run an app on the phone. I don't really care about any exchange of data, just a test connection - somewhat like unlocking a device by having your phone with you.

My hope was that with classic bluetooth I could just call .connect() with the MAC address of the previously paired phone, which is what led me to this post. My impression was that BLE wasn't an option.

@wolph
Copy link
Contributor

wolph commented Jan 9, 2020

I think BLE is perfect for that application actually. The esphomelib library has an example doing just that: https://esphome.io/components/esp32_ble_tracker.html

@jsodeman
Copy link

jsodeman commented Jan 9, 2020

Thanks for the link. The problem I'd run into with BLE is that phones randomize their mac address and don't otherwise seem to broadcast anything detectable without running something like a beacon simulator app. Generally it seems like working with a phone really requires the phone to be the initiating device or for it to be running an app. So for now I think BLE with a beacon app running in the phone background is the easiest. I was able to wifi sniff a phone but the interval is inconsistent.

@chegewara
Copy link
Contributor

@jsodeman If you initially connect with smartphone and create bond connection then esp32 should recognize that smartphone anytime, because smartphones are using resolvable address.

@jsodeman
Copy link

jsodeman commented Jan 9, 2020

@chegewara with BT classic? I think I ran into problems trying that which is what led me to trying Master mode and this post. But honestly I've tried so many different things in the last week I've lost track of why I rules things out. I need to start taking notes on my attempts :-P

@chegewara
Copy link
Contributor

No, im saying about BLE now.
I am completely lame about classic bluetooth, so i cant help with that.

@jsodeman
Copy link

jsodeman commented Jan 9, 2020

No worries. I'll give that a shot with BLE. For some reason last time I tried it I couldn't get the phone to connect and bond with the ESP32 running the server example.

@j0r9e74
Copy link

j0r9e74 commented Apr 18, 2020

Hello,
I need to make a BT connection (classic BT) from an ESP32 to an arduino nano with HC-06 bluetooth.
Using info from @wolph info from Nov 5, 2019 post:
https://github.com/espressif/arduino-esp32/blob/f0e2e2a62fe98ec9657f3935c41c88a0fd0e7acd/libraries/BluetoothSerial/src/BluetoothSerial.cpp
"The device started in master mode, make sure remote BT device is on!
Failed to connect. Make sure remote device is available and in range, then restart app."

Tryed @IonicEV master 1.0.4 but there is no connection, even if there is a success in the log:

"The device started in master mode, make sure remote BT device is on!
Connected Succesfully!"

Tried both connection by name and by address, I have double checked the used infos.
Can you confirm that a classical BT connection from ESP32 to HC-06 is possible and if so then can you point me to the proper files??
I can update also the code used if needed

Please, I really need it for a school project
Thank you

@atanisoft
Copy link
Collaborator

@j0r9e74 open a new issue

@j0r9e74
Copy link

j0r9e74 commented Apr 19, 2020

Hello,
Can anybody give me an answer:
It is possible to connect using standard bluetooth from ESP32 to HC-06 (with arduino nano)?
The usecase is to send/receive some strings.
I tried the different modified BluetoothSerial sources and got only two types of results:

  • always saying "Connected succesfully!", no matter what name or address I used; tryed also to communicate in this state but without success
  • "Failed to connect" forever
    It is not a matter of HC-06 connection because I can use a phone to connect at it and send/receive strings.
    @wolph and @IonicEV can you help me please??
    @mprowe I have noticed that you have have some success. Can you provide me the details?

I really a solution until the end of net week. Please help me guys.
Regards,
Jorge

@jsodeman
Copy link

@j0r9e74 I think they're willing to help but want you to open a new issue on that as your question isn't related to this topic directly.

@j0r9e74
Copy link

j0r9e74 commented Apr 19, 2020

@jsodeman my question belong to this topic. if they wants to help and a new issue is required they can request this. thank you

@jsodeman
Copy link

jsodeman commented Apr 19, 2020 via email

@j0r9e74
Copy link

j0r9e74 commented Apr 19, 2020

#3916 issue opened
@atanisoft and @jsodeman

@lysiong
Copy link

lysiong commented May 26, 2020

As I mentioned earlier I did not find in documentation suggestion those functions (esp_bt_gap_set_pin & esp_bt_gap_pin_reply) are working for incoming connections (your use case), only outgoing connections were mentioned and those are working for outgoing connections. For incoming connections to use those functions, as you mentioned, it needs some kind of library module compiled with specific options or containing the code to utilize esp_bt_gap_set_pin function for incoming connections. This does not preclude people from using pins for outgoing connections that is supported currently by the firmware.

@IonicEV , at the moment, ESP32 not possible to connect OBDII bluetooth dongle such as OBDLink LX that always generate random pin at the moment?

@ketan
Copy link

ketan commented Dec 16, 2020

Does the setPin work as expected? I'm trying to pair an ESP32 with my phone, and it pairs without asking for any pin.

The example has the setPin method commented out.

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

Successfully merging this pull request may close these issues.

None yet