nkolban / esp32-snippets

Sample ESP32 snippets and code fragments
https://leanpub.com/kolban-ESP32
Apache License 2.0
2.37k stars 710 forks source link

Obtaining RSSI value from server while connected #1113

Open DaCeeej opened 2 years ago

DaCeeej commented 2 years ago

Hello all,

Currently, I have 4 Firebeetle esp32 boards. 1 of which is the BLE server that is notifying 3 BLE clients. I have the clients being notified successfully, but now I need to find a way for the clients to continually get the RSSI value while staying connected to the server. I have found ways of getting the RSSI value once while connecting to the BLE server.

The following works on the initial connection to the server:

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {

  void onResult(BLEAdvertisedDevice advertisedDevice) {
    Serial.print("BLE Advertised Device found: ");
    Serial.println(advertisedDevice.toString().c_str());

    // We have found a device, let us now see if it contains the service we are looking for.
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
      rssi = advertisedDevice.getRSSI();
      Serial.print("RSSI: ");Serial.println(rssi);
      BLEDevice::getScan()->stop();
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;

    } // Found our server
  } // onResult
}; // MyAdvertisedDeviceCallbacks

I've found issues #808 and #893 to be similar to the issue that I'm having, but haven't been able to implement any solutions based on these discussions and this is where I'm looking for advice. Similar to issue #808, I tried to use the following in the void loop() section:

int rssi = pClient->getRssi(); 
Serial.println(rssi);

However, I keep getting the error of pClient not being declared in the scope. How does this get declared in the scope? I have it "declared" in the following, but I guess that's not global?

bool connectToServer() {
    Serial.print("Forming a connection to ");
    Serial.println(myDevice->getAddress().toString().c_str());
    BLEClient*  pClient  = BLEDevice::createClient();
    ....

I've also attempted to make a custom gap handler similar to what's discussed in issue #893.

static void my_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t* param) {
  Serial.print("RSSI status");Serial.println(param->read_rssi_cmpl.status);
  Serial.print("RSSI ");Serial.println(param->read_rssi_cmpl.rssi);
  Serial.print("Address ");Serial.println(BLEAddress(param->read_rssi_cmpl.remote_addr).toString().c_str());
}

All this does is display the RSSI values for random BLE devices that I don't care about, then it connects to my esp32 BLE server, and then that's it. Why doesn't this get the RSSI value for the BLE server that it's connecting to? If there's a way to get the BLE server's RSSI value, then how could I get it to update the RSSI value after connecting to the server?

If I'm unable to figure this out then my brute force solution could be to constantly start and stop BLE scanning in order to update the RSSI value (similar to a modified BLE_scan example utilizing advertisedDevice.getRSSI()). I would then read the characteristic value each time a client connected to the server instead of being notified by the server. I'd prefer to not do this since I have everything else working with the notifications and I feel like there must be a way of obtaining the RSSI value that I'm not experienced enough to figure out on my own. If you all think that this is the best solution then I'll just try moving forward with this.

Thanks!

DaCeeej commented 2 years ago

I've now defined pClient as global and I can run the program. I'm just getting a RSSI of 0. I think I should be able to troubleshoot this from here, but maybe not.

aveleta commented 2 years ago

I have the same problem I keep getting an RSSI of 0 but i only have one device connected

DaCeeej commented 2 years ago

So the RSSI value is a 0 if the client isn't connected or if the esp_err_t value is anything other than ESP_OK.

From BLEClient.cpp:

int BLEClient::getRssi() {
    log_v(">> getRssi()");
    if (!isConnected()) {
        log_v("<< getRssi(): Not connected");
        return 0;
    }
    // We make the API call to read the RSSI value which is an asynchronous operation.  We expect to receive
    // an ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT to indicate completion.
    //
    m_semaphoreRssiCmplEvt.take("getRssi");
    esp_err_t rc = ::esp_ble_gap_read_rssi(*getPeerAddress().getNative());
    if (rc != ESP_OK) {
        log_e("<< getRssi: esp_ble_gap_read_rssi: rc=%d %s", rc, GeneralUtils::errorToString(rc));
        return 0;
    }
    int rssiValue = m_semaphoreRssiCmplEvt.wait("getRssi");
    log_v("<< getRssi(): %d", rssiValue);
    return rssiValue;
} // getRssi

I modified the 1st "return 0" to be "return 1". Then all of my RSSI values became 1 instead of 0. Therefore, isConnected is false.

While writing this out, I realized my problem and the RSSI values are reading correctly now. I had defined "BLEClient pClient = BLEDevice::createClient();" globally, but I never removed the definition from my "bool connectToServer()" function (function is probably the wrong word to use, still learning the terminology). In other words, I defined "BLEClient pClient = BLEDevice::createClient();" in 2 places, one local and one global. I removed the local definition it's working now. Hopefully some part of this is helpful for you @aveleta.

aveleta commented 2 years ago

I cant believe it was that easy!!!!! I've been trying to figure this out all week thank you so much for the help!!!@DaCeeej

mar-ver commented 2 years ago

Hi! do you maybe have the full code for this? would love to implement it but i'am struggling to get it working :)

DaCeeej commented 2 years ago

I've just made a repository that I'll link here. The code I've uploaded is working for me, but I haven't really cleaned it up and I do get some random errors at times that happen more frequently when I'm reading RSSI values more often. Hopefully, this is somewhat useful for you @vermar-js.

It's been a little while since I've looked at any of this. Based on my previous posts, I'm guessing that line 73 and lines 99-138 of EMF_Client3mod.ino would be the most useful for you.

davidangelo64 commented 1 year ago

Have you ever tried doing this with two servers? If you have achieved it please help me. I'm currently using arduino ide, but any help is useful, thanks in advance.