BLE_scan: scans after first one don't return correct info

ESP32Toad
Posts: 5
Joined: Sun Sep 20, 2020 4:30 am

BLE_scan: scans after first one don't return correct info

Postby ESP32Toad » Wed Sep 30, 2020 12:48 am

Quick summary: BLE scans for advertising packets return something wrong after the first scan (first scan returns correct packets)
-------
running Neil Kolbans Examples>ESP32 BLE Arduino>BLE_Scan.ino example on a 1.0.4 ESP32 IDF, Arduino IDE 1.8.14 hourly 2020/09/23

Using it to passively scan for advertising packets from Govee H5074 thermometer+humidity sensors
https://www.amazon.com/Govee-Thermomete ... 473&sr=8-2

These send out a message every second, and every other or so message contains actual sensor data (temp, humidity) The other ones contain other manufacturer data.

For the sensor data containing packets I know that
esp_ble_gap_cb_param_t➟scan_rst.scan_rsp_len=11 and
esp_ble_gap_cb_param_t➟scan_rst.adv_data_len=29 total length = 40

And for the other packets
scan_rsp_len=27 and adv_data_len=29 total length = 56 (no sensor data)


When I run the code below, which is quite short, the first scan returns proper data as expected.
Here, each Govee_H5074_XXXX sensor is identified in its name by XXXX=last 4 digits of its device address
You can see that we regularly get an advertising packet from various devices with sensor data (and in between length 56 packets)

BUT:
after the first scan terminates and pBLEScan➟start() is called subsequently, the stack consistently returns
scan_rsp_len=0 and adv_data_len=29 total length=29
packets which is wrong.

Now, I don't know whether the bug exists in Neils C++ wrapper class or in the underlying esp_ble_**** calls.
It appears his BLEScan::start() basically does this:
https://github.com/nkolban/esp32-snippe ... LEScan.cpp
esp_ble_gap_set_scan_params(&m_scan_params);
esp_ble_gap_start_scanning(duration);

Is that correct, is it enough ? If so, is the failure to deliver any advertisements in subsequent scans with scan_rsp_len>0 in the handleGAPevent callback (ESP_GAP_SEARCH_INQ_RES_EVT) the fault of the esp_ble stack ?

Starting scan...
{"name":"Govee_H5074_C0A6","celsius":24.3,"fahrenheit":75.8,"humidity":57.8,"battery":100}
Govee_H5074_C0A6 length[56] advertisement...no sensor data!
{"name":"Govee_H5074_C0A6","celsius":24.3,"fahrenheit":75.7,"humidity":57.8,"battery":100}
Govee_H5074_C0A6 length[56] advertisement...no sensor data!
{"name":"Govee_H5074_C0A6","celsius":24.3,"fahrenheit":75.8,"humidity":57.6,"battery":100}
Govee_H5074_C0A6 length[56] advertisement...no sensor data!

Starting scan...
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
Govee_H5074_C0A6 length[29] advertisement...no sensor data!

Starting scan...
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
Govee_H5074_C0A6 length[29] advertisement...no sensor data!
...and so on and so on

Code: Select all

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
BLEScan* pBLEScan;

long getLongFromByteArray(byte* bytes, int position) {
  long result = bytes[position + 1] * 256 + bytes[position];
  return result;
}

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      String deviceName( advertisedDevice.getName().c_str() );
      // devicename is something like Govee_H5074_C0A6
      // H5074= type of govee device
      // C0A6 = last four digits of this device address
      if ( deviceName.startsWith( "Govee_H5074_" ) )  {
        unsigned long pll = advertisedDevice.getPayloadLength();
        uint8_t* payload  = advertisedDevice.getPayload();

        if( pll!=40 )
          Serial.printf( "%s length[%d] advertisement...no sensor data!\n", advertisedDevice.getName().c_str(), pll );
          
        // we see length 29, 40, 56 packets for Govees (adv_data_len=29 always, scan_rsp_len=0,11,27 resp.
        // only the length 40 packets actually contain sensor data in the ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE (0xFF)
        // Sensor data for govee = 88:EC:00:19:09:5C:15:64:02
        //                                  ^^^^^ temperature
        //                                        ^^^^^ humidity
        //                                              ^^ battery level 
        if ( pll == 40 )  {
          double celsius = ((double)getLongFromByteArray(payload, 34 )) / 100.0;
          double fahrenheit = (celsius * 9.0 / 5.0) + 32.0;
          double relativeHumidity = ((double)getLongFromByteArray(payload, 36)) / 100.0;
          int battery = payload[38];
          Serial.printf( "{\"name\":\"%s\",\"celsius\":%.1lf,\"fahrenheit\":%.1lf,\"humidity\":%.1lf,\"battery\":%d}\n",
                   deviceName.c_str(),  celsius,  fahrenheit, relativeHumidity, battery );
        }
      }
    }
};

void setup() {
  Serial.begin(115200);
  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(), true /* wantDuplicates ? yes */);
  pBLEScan->setActiveScan(false); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // less or equal setInterval value
}

void loop()  {
  int scanTime = 10; //In seconds
  Serial.printf( "\nStarting scan...\n" );
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
  pBLEScan->clearResults();
  delay( 10000 );
}

Who is online

Users browsing this forum: No registered users and 78 guests