NimBLE-Arduino icon indicating copy to clipboard operation
NimBLE-Arduino copied to clipboard

NIMBLE Client read/update characteristic

Open FrancescoBaroneItaly opened this issue 3 years ago • 6 comments
trafficstars

Hello everyone,

I'm tring to implement a BLE client application that will connect to a specific Address and try to read and then update a characteristic value. ( I use authentication ) These are my steps: -> connect to peer address OK -> discover service OK -> discover characteristic OK -> check if characteristic is readable and writable OK -> read value -> FAIL it return an empty value -> write value -> FAIL it return rc=0 but the data does not change in server

The server code would be ok because I tried to update with another BLE Client ( iphone and android ) and it works

NimBLEClient *pClient = NimBLEDevice::createClient(); pClient->setClientCallbacks(new ClientCallbacks());

if (pClient->connect( NimBLEAddress("1c:9d:c2:fe:0d:76"), true )){

pClient->secureConnection(); NimBLERemoteService *pService = pClient->getService("6d78d760-581e-11ec-bf63-0242ac130002"); if (pService != nullptr){

if (pSecureCharacteristic != nullptr){
   
   Serial.print("-read->");Serial.println(atoi(pSecureCharacteristic->readValue().c_str()));
                    
   if(pSecureCharacteristic->canWrite()) {

           Serial.println("Update ... ");
           if(pSecureCharacteristic->writeValue('a')) {

                Serial.println("ok");
                }
      }
   }
}

}


these are output log lines:

NimBLERemoteCharacteristic *pSecureCharacteristic = pService->getCharacteristic("2000D NimBLERemoteService: ">> getCharacteristic: uuid: 0x2000" D NimBLERemoteService: ">> retrieveCharacteristics() for service: 6d78d760-581e-11ec-bf63-0242ac130002" D NimBLERemoteService: "Characteristic Discovered >> status: 0 handle: 24" D NimBLERemoteCharacteristic: ">> NimBLERemoteCharacteristic()" D NimBLERemoteCharacteristic: "<< NimBLERemoteCharacteristic(): 0x2000" D NimBLERemoteService: "Characteristic Discovered >> status: 14 handle: -1" D NimBLERemoteService: "<< Characteristic Discovered" D NimBLERemoteService: "<< retrieveCharacteristics()" -read->D NimBLERemoteCharacteristic: ">> readValue(): uuid: 0x2000, handle: 24 0x18" I NimBLERemoteCharacteristic: "Read complete; status=261 conn_handle=0" D NimBLEClient: "Got Client event " D NimBLEClientCallbacks: "onAuthenticationComplete: default" I NimBLERemoteCharacteristic: "Read complete; status=261 conn_handle=0" **E NimBLERemoteCharacteristic: "<< readValue rc=261" 0 Update ... D NimBLERemoteCharacteristic: ">> writeValue(), length: 1" ok D NimBLECli**ent: ">> disconnect()" D NimBLEClient: "<< disconnect()" delete client D NimBLEClient: ">> disconnect()" I NimBLEClient: "Already disconnecting, timer started" D NimBLEClient: "Got Client event " Client Disconnected");

thank you for help

FrancescoBaroneItaly avatar Jun 24 '22 07:06 FrancescoBaroneItaly

It looks to me like the pairing has failed. What is the peer device you're connecting to, do you have access to it's code?

h2zero avatar Jun 25 '22 02:06 h2zero

Hi and thanks for response... below the server code I used that is running on another ESP32....

// ESP32 80Mhz DEV 1.9 APP 190kb SPFSS PSRAM=false #include <NimBLEDevice.h>

#include <esp_wifi.h> #include <esp_bt.h> #include "driver/rtc_io.h" #include <driver/adc.h>

#include <WiFi.h>

#include <ESP32AnalogRead.h> ESP32AnalogRead adc;

RTC_DATA_ATTR int8_t COUNT=0; RTC_DATA_ATTR int DEEP_SLEEP_TIME=5; RTC_DATA_ATTR float VBATT=0; unsigned long T=0;

NimBLECharacteristic *pSecureCharacteristic; NimBLEAdvertising *pAdvertising;

class MyServerCallbacks: public NimBLEServerCallbacks {

void onWrite (NimBLECharacteristic *pCharacteristic){

Serial.println("WRITE REQUEST");
}

void onConnect(NimBLEServer *pServer) { Serial.println("Server Connect"); pAdvertising->start(); }

uint32_t onPassKeyRequest() { Serial.println("-----> Server Passkey Request");
/** return the passkey to send to the server / /* Change this to be different from NimBLE_Secure_Server if you want to test what happens on key mismatch */ return 123456;
}

bool onConfirmPIN(uint32_t pin){

Serial.println("----> PIN "+String(pin));
return true;
}

};

class MyCharacteristicCallbacks: public NimBLECharacteristicCallbacks {

void onWrite (NimBLECharacteristic *pCharacteristic){

std::string value = pCharacteristic->getValue(); 

int len = pCharacteristic->getDataLength();

char cstr[len+1];
memcpy(cstr, value.data(), len);
cstr[len]='\0';

Serial.println("->> WRITE "+String(cstr));
}

};

#define LED_BUILTIN 22

void setup() {

gpio_deep_sleep_hold_dis();

adc.attach(39); VBATT = adc.readVoltage();//analogRead(36);

adc_power_off();

//WiFi.persistent(false);
WiFi.disconnect(); WiFi.mode(WIFI_OFF);

//disable WDT disableCore0WDT(); disableCore1WDT();

pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); delay(500); digitalWrite(LED_BUILTIN, HIGH); delay(500); digitalWrite(LED_BUILTIN, LOW);

Serial.begin(115200); Serial.println("Starting NimBLE Server"); //Serial.print("BATT=");Serial.println(VBATT);

uint8_t chipid[6];

esp_read_mac(chipid,ESP_MAC_BT); //esp_efuse_read_mac(chipid);

char ble[32]; sprintf(ble,"AAA-%02x%02x%02x%02x%02x%02x",chipid[0], chipid[1], chipid[2], chipid[3], chipid[4], chipid[5]); NimBLEDevice::init(ble); NimBLEDevice::setPower(ESP_PWR_LVL_P9);

Serial.println(ble);

NimBLEDevice::setSecurityAuth(true, true, true); NimBLEDevice::setSecurityPasskey(123456); //NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY); NimBLEDevice::setSecurityIOCap(BLE_HS_IO_KEYBOARD_ONLY); NimBLEServer *pServer = NimBLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks()); NimBLEService *pService = pServer->createService("6d78d760-581e-11ec-bf63-0242ac130002");

pSecureCharacteristic = pService->createCharacteristic("2000", NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_ENC | NIMBLE_PROPERTY::WRITE_AUTHEN );

pSecureCharacteristic->setCallbacks(new MyCharacteristicCallbacks());

char payload[32];

pService->start();

sprintf(payload,"Hello Ble-%02x %d",chipid[5], COUNT); pSecureCharacteristic->setValue(payload);

pAdvertising = NimBLEDevice::getAdvertising(); pAdvertising->addServiceUUID("6d78d760-581e-11ec-bf63-0242ac130002"); pAdvertising->start();

T=millis(); COUNT++;

xTaskCreatePinnedToCore( task, /* Task function. / "task", / String with name of task. / 8 * 1024, / Stack size in bytes. / NULL, / Parameter passed as input of the task / 2, / Priority of the task. / NULL, / Task handle. */ 1); }

boolean low_power=false; unsigned long t0=millis();

void task( void * parameter ) {

for(;;){

vTaskDelay(10);

if(millis()-t0>5000){

  t0=millis();
  Serial.println((pSecureCharacteristic->getValue()).c_str());

  ( strcmp( (pSecureCharacteristic->getValue()).c_str(), "a")==0) ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH);
  }

}

}

void loop() {

vTaskDelete(NULL); }

FrancescoBaroneItaly avatar Jun 27 '22 06:06 FrancescoBaroneItaly

Can you provide a log from the server when this happens?

h2zero avatar Jun 27 '22 23:06 h2zero

Hi, sure, I will attach server connection log:

PS1: for this test the service uuid is 6d78d760-581e-11ec-bf63-0242ac130002 and char uuid 2000 the server bluetooth address is 1c:9d:c2:fe:0d:76

PS2: the workaround that fix the problem is to set at server side the characteristic with these properties:

NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_ENC

if I add NIMBLE_PROPERTY::READ_AUTHEN and NIMBLE_PROPERTY::WRITE_AUTHEN the service is not updated

----- LOG --------------------

D NimBLEServer: ">> handleGapEvent: " [0000000014989] Server Connect D NimBLEAdvertising: ">> Advertising start: customAdvData: 0, customScanResponseData: 0" GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=0 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=0 adv_itvl_max=0 ble_hs_hci_cmd_send: ogf=0x08 ocf=0x0006 len=15 0x06 0x20 0x0f 0x30 0x00 0x60 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x07 0x00 ble_hs_hci_cmd_send: ogf=0x08 ocf=0x000a len=1 0x0a 0x20 0x01 0x01 D NimBLEAdvertising: "<< Advertising start" D NimBLEServerCallbacks: "onConnect(): Default" ble_hs_hci_cmd_send: ogf=0x08 ocf=0x0016 len=2 0x16 0x20 0x02 0x00 0x00 ble_hs_hci_evt_acl_process(): conn_handle=0 pb=2 len=7 data=0x03 0x00 0x04 0x00 0x02 0xff 0x00 host tx hci data; handle=0 length=7 ble_hs_hci_acl_tx(): 0x00 0x00 0x07 0x00 0x03 0x00 0x04 0x00 0x03 0xff 0x00 D NimBLEServer: ">> handleGapEvent: " I NimBLEServer: "mtu update event; conn_handle=0 mtu=255" D NimBLEServerCallbacks: "onMTUChange(): Default" looking up our sec; peer_addr_type=0 peer_addr=0xce 0x6f 0x9d 0x25 0xbf 0x58 ediv=0x00 rand=0x0 ble_hs_hci_cmd_send: ogf=0x08 ocf=0x001a len=18 0x1a 0x20 0x12 0x00 0x00 0x04 0x53 0xad 0xbf 0xfe 0x2b 0x95 0xe3 0xc3 0xdd 0xe6 0x02 0x3f 0x1c 0x93 0x17 D NimBLEServer: ">> handleGapEvent: " D NimBLEServerCallbacks: "onAuthenticationComplete: default" ble_hs_hci_evt_acl_process(): conn_handle=0 pb=2 len=27 data=0x17 0x00 0x04 0x00 0x06 0x01 0x00 0xff 0xff 0x00 0x28 0x02 0x00 0x13 0xac 0x42 0x02 0x63 0xbf 0xec 0x11 0x1e 0x58 0x60 0xd7 0x78 0x6d host tx hci data; handle=0 length=9 ble_hs_hci_acl_tx(): 0x00 0x00 0x09 0x00 0x05 0x00 0x04 0x00 0x07 0x0a 0x00 0x19 0x00 ble_hs_hci_evt_acl_process(): conn_handle=0 pb=2 len=27 data=0x17 0x00 0x04 0x00 0x06 0x1a 0x00 0xff 0xff 0x00 0x28 0x02 0x00 0x13 0xac 0x42 0x02 0x63 0xbf 0xec 0x11 0x1e 0x58 0x60 0xd7 0x78 0x6d host tx hci data; handle=0 length=9 ble_hs_hci_acl_tx(): 0x00 0x00 0x09 0x00 0x05 0x00 0x04 0x00 0x01 0x06 0x1a 0x00 0x0a ble_hs_hci_evt_acl_process(): conn_handle=0 pb=2 len=11 data=0x07 0x00 0x04 0x00 0x08 0x0a 0x00 0x19 0x00 0x03 0x28 host tx hci data; handle=0 length=41 ble_hs_hci_acl_tx(): 0x00 0x00 0x29 0x00 0x25 0x00 0x04 0x00 0x09 0x07 0x0b 0x00 0x02 0x0c 0x00 0x19 0x2a 0x0e 0x00 0x02 0x0f 0x00 0x01 0x10 0x11 0x00 0x02 0x12 0x00 0x00 0x10 0x14 0x00 0x0a 0x15 0x00 0x01 0x20 0x17 0x00 0x0a 0x18 0x00 0x00 0x20 ble_hs_hci_evt_acl_process(): conn_handle=0 pb=2 len=11 data=0x07 0x00 0x04 0x00 0x08 0x18 0x00 0x19 0x00 0x03 0x28 host tx hci data; handle=0 length=9 ble_hs_hci_acl_tx(): 0x00 0x00 0x09 0x00 0x05 0x00 0x04 0x00 0x01 0x08 0x18 0x00 0x0a ble_hs_hci_evt_acl_process(): conn_handle=0 pb=2 len=7 data=0x03 0x00 0x04 0x00 0x0a 0x18 0x00 host tx hci data; handle=0 length=9 ble_hs_hci_acl_tx(): 0x00 0x00 0x09 0x00 0x05 0x00 0x04 0x00 0x01 0x0a 0x18 0x00 0x05 looking up our sec; peer_addr_type=0 peer_addr=0xce 0x6f 0x9d 0x25 0xbf 0x58 ediv=0x00 rand=0x0 ble_hs_hci_cmd_send: ogf=0x08 ocf=0x001a len=18 0x1a 0x20 0x12 0x00 0x00 0x04 0x53 0xad 0xbf 0xfe 0x2b 0x95 0xe3 0xc3 0xdd 0xe6 0x02 0x3f 0x1c 0x93 0x17 D NimBLEServer: ">> handleGapEvent: " D NimBLEServerCallbacks: "onAuthenticationComplete: default" ble_hs_hci_evt_acl_process(): conn_handle=0 pb=2 len=7 data=0x03 0x00 0x04 0x00 0x0a 0x18 0x00 host tx hci data; handle=0 length=9 ble_hs_hci_acl_tx(): 0x00 0x00 0x09 0x00 0x05 0x00 0x04 0x00 0x01 0x0a 0x18 0x00 0x05 ble_hs_hci_evt_acl_process(): conn_handle=0 pb=2 len=8 data=0x04 0x00 0x04 0x00 0x12 0x18 0x00 0x61 host tx hci data; handle=0 length=9 ble_hs_hci_acl_tx(): 0x00 0x00 0x09 0x00 0x05 0x00 0x04 0x00 0x01 0x12 0x18 0x00 0x05 looking up our sec; peer_addr_type=0 peer_addr=0xce 0x6f 0x9d 0x25 0xbf 0x58 ediv=0x00 rand=0x0 ble_hs_hci_cmd_send: ogf=0x08 ocf=0x001a len=18 0x1a 0x20 0x12 0x00 0x00 0x04 0x53 0xad 0xbf 0xfe 0x2b 0x95 0xe3 0xc3 0xdd 0xe6 0x02 0x3f 0x1c 0x93 0x17 D NimBLEServer: ">> handleGapEvent: " D NimBLEServerCallbacks: "onAuthenticationComplete: default" ble_hs_hci_evt_acl_process(): conn_handle=0 pb=2 len=8 data=0x04 0x00 0x04 0x00 0x12 0x18 0x00 0x61 host tx hci data; handle=0 length=9 ble_hs_hci_acl_tx(): 0x00 0x00 0x09 0x00 0x05 0x00 0x04 0x00 0x01 0x12 0x18 0x00 0x05 D NimBLEServer: ">> handleGapEvent: " D NimBLEServerCallbacks: "onDisconnect(): Default" D NimBLEServerCallbacks: "onDisconnect(): Default" D NimBLEAdvertising: ">> Advertising start: customAdvData: 0, customScanResponseData: 0" W NimBLEAdvertising: "Advertising already active"

FrancescoBaroneItaly avatar Jun 28 '22 07:06 FrancescoBaroneItaly

Hi @all, just an update, feel free to add your comments and I could consider issue as closed without any code-fix required. After several tests, I decided to build a second prototype using different ESP32 module. ( same chip ESP32-DOWQ06, different date of production). The client-code on second prototype work as designed and I was able to update remote characteristic. Seems that the problem was the ESP32 chip despite I tried using esptool to clear flash, NVS, flash a minimal code and so on .... any comments would help to definitely bury prototype number 1 :-)

FrancescoBaroneItaly avatar Jul 04 '22 06:07 FrancescoBaroneItaly

Thanks for the update, I was not able to reproduce this, but I know there have been a few bad chips in the past that users had trouble with.

h2zero avatar Jul 04 '22 13:07 h2zero