espressif / esp-nimble

A fork of NimBLE stack, for use with ESP32 and ESP-IDF
Apache License 2.0
76 stars 49 forks source link

HCI packet count mismatch (0, 1) #47

Open markingle opened 2 years ago

markingle commented 2 years ago

Environment

Development Kit: HiLetGo ESP32 Dev Board Module or chip used: ESP32-WROOM-32D IDF version: Build System: Compiler version: xtensa-esp32-elf-gcc (crosstool-NG esp-2020r1) 8.2.0 Operating System: Mac OSX Big Sur Using an IDE?: Arduino Power Supply: USB

Problem Description

I am working to develop an WatchOS BLE application to control a water pump. By design when the Apple watch goes into sleep mode the Watch BLE app disconnects from the server application running on the ESP32. Eventually the connection state gets stuck on "device connected" and the HCI error message is displayed in the serial output...See below

Starting BLE work! Characteristic defined! Now you can read it in your phone! device connected Device is connecting device connected device connected device connected device connected device connected start advertising device connected Device is connecting device connected device connected device connected device connected start advertising device connected Device is connecting device connected device connected device connected device connected device connected start advertising device connected lld_pdu_get_tx_flush_nb HCI packet count mismatch (0, 1)

Expected Behavior

To maintain a stable connection state based on current connection with Watch app.

Wireshark Capture Link

https://drive.google.com/file/d/1muiVhvKGq0Gc-K3awjBWnBMphY0jAlCt/view?usp=sharing

Arduino Code Snippet


void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");

  pinMode(WIFI_CLIENT_CONNECTED, OUTPUT);
  digitalWrite(WIFI_CLIENT_CONNECTED, LOW);

  BLEDevice::init("Long name works now");

  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                        CHARACTERISTIC_UUID,
                                  /***** Enum Type NIMBLE_PROPERTY now *****      
                                        BLECharacteristic::PROPERTY_READ   |
                                        BLECharacteristic::PROPERTY_WRITE  
                                        );
                                  *****************************************/
                                        NIMBLE_PROPERTY::READ |
                                        NIMBLE_PROPERTY::WRITE 
                                       );

  pCharacteristic->setValue("Hello World says Neil");
  pService->start();
  // BLEAdvertising *pAdvertising = pServer->getAdvertising();  // this still is working for backward compatibility
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMaxPreferred(0x12);

  BLEDevice::startAdvertising();
  Serial.println("Characteristic defined! Now you can read it in your phone!");
}

void loop() {
  if (deviceConnected) {
        Serial.println("device connected");
        //value++;
        digitalWrite(WIFI_CLIENT_CONNECTED, HIGH);
        delay(1000); // bluetooth stack will go into congestion, if too many packets are sent, in 6 hours test i was able to go as low as 3ms
        //pCharacteristicB->setValue((uint8_t*)&onState, 4);
        //pCharacteristicB->notify(); 
        //pCharacteristicA->setValue((uint8_t*)&pumpEnabled, 4);
        //pCharacteristicA->notify();
        BLEDevice::getAdvertising()->stop();
    }
    // disconnecting
    if (!deviceConnected && oldDeviceConnected) {
        delay(500); // give the bluetooth stack the chance to get things ready
        digitalWrite(WIFI_CLIENT_CONNECTED, LOW);
        BLEDevice::getAdvertising()->start();
        Serial.println("start advertising");
        oldDeviceConnected = deviceConnected;
    }
    // connecting
    if (deviceConnected && !oldDeviceConnected) {
        // do stuff here on connecting
        Serial.println(" Device is connecting");
        oldDeviceConnected = deviceConnected;  
    }
   }