esp32-snippets icon indicating copy to clipboard operation
esp32-snippets copied to clipboard

How send a write request?

Open smartinick opened this issue 7 years ago • 24 comments

Hi there!

i'm trying to connect esp32 to a ble server - i'm able to find the devices, uuid, services, descriptors,... (btw - using esp32_ble_arduino)

now i need to send a write-request to a handle, but i have no idea how...?

the handle is a BLERemoteDescriptor which is found from a BLERemoteCharacteristic by using the getdescriptor. using the writevalue method for writing 2 bytes via a char-array (and according to the sniffer it sends those 2 bytes out as desired.

when using the ble sniffer i can watch an android app connect to the ble server and it sends a write-request (OpCode 0x12 in BLE AT Protocoll). when sniffing on the esp32 it sends the exact same packet except for the opcode which is 0x52 aka write-command.

it does not matter if i set the 3rd parameter from writevalue (response) to true or false, opcode is always 0x52.

searching the sources did not help either, bleremotedescriptor only has read/write value methods but as far as i see there's no writecommand or writerequst methods.

So that's where i'm stuck beeing happy about any usefull hint...

Thanks for your time & Brgds, Martin.

smartinick avatar Jan 26 '18 19:01 smartinick

Howdy, It should be that given a BLEClient object, you can locate the BLERemoteService and from there locate the BLERemoteCharacteristic which will then take you to the BLERemoteDescriptor. With a reference to a BLERemoteDescriptor object, we should find that we have a method on that called writeValue(). When we invoke writeValue(), that should set the value of the descriptor on the remote BLE server..

Unfortunately, I have never looked at the wire level bits and bytes of BLE (ive so far never had to). The ESP-IDF provides APIs for working with BLE and the cpp_utils BLE classes provide C++ encapsulations of the ESP-IDF BLE APIs.

The actual API that performs the API call looks like:

https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLERemoteDescriptor.cpp#L145

nkolban avatar Feb 05 '18 01:02 nkolban

Hi Neil!

i've used your ble_client example and modified it a bit, in the end i'm doing following:

  • Device search, look for a device where adverstisedDevice.getServiceUUID matches
  • use advertisedDevice.getAddress in conjunction with a bleclient to connect.
  • get the bleremoteservice via client->getservice
  • get (totally it's 3 of them) bleremotecharacteristics via bleremoteservice->getcharacteristic
  • dump the properties for the remotecharacteristic (canread/write/... and the handle.
  • then i get the bleremotedescriptor via bleremotecharacteristic->getdescriptor
  • and finally i use the writevalue on the bleremotedescriptor. (and registerfornotification as well).

Now when looking at the blesniffer trace the esp32 sends a packet with the desired payload to the desired handle (aka the same handle/payload that the android-app sends to the bleserver/device).

Except for the small difference mentioned above (BLE-AT OpCode 0x12 vs 0x51).

i can post screenshots or wireshark dump-files if that helps.

but i guess not ;)

i've already read through the bleremotedescriptor/charateristics,... files for your ble library. and also through the esp-idf-arduino sources.

and i'm still clueless as even in espidf sources i can't find a hint how to get the desired opcode sent out.

(by the way, i can write values to the device, reset the esp and read the same value back from the device. so i'd guess the basic communication part is working).

From your feedback i believe i've gone the correct path though not reached the target.... does my feedback give you any hints for anything to test...?

my only idea now is to put this information/questions either in esp32 forum or post a issue with the esp-idf repository - any other ideas?

Thanks &Brgds, Martin. (And sorry for the delay, just have very sporadic time-resources for programming lately).

smartinick avatar Feb 09 '18 20:02 smartinick

I have kind a same problem. Im working with Komoot navigation. Everything else works ok, but it sends only 20 bytes (document speaks of 22 bytes) and when street name is longer i have to ask for more. I just dont know how to write and ask more.

https://github.com/komoot/BLEConnect

JaspaJami avatar May 04 '18 16:05 JaspaJami

Could you paste that part of code is sending request?

chegewara avatar May 04 '18 16:05 chegewara

Well i have try to modify this one: https://github.com/SensorsIot/Bluetooth-BLE-on-Arduino-IDE/blob/master/Polar_Receiver/Polar_Receiver.ino

Now if i try to add example that notification enable / disable part to my code ESP32 crash and reboots.

pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true);

JaspaJami avatar May 04 '18 16:05 JaspaJami

Hm. My Problem was that the BLE-Command beeing sent has the wrong opcode and that there's only a writevalue in the api, no writecommand. it was not about different length and such.

but a hint might be that there's a length limit for ble packets so if your payload and header exceeds that, you'll have to send another packet...

smartinick avatar May 04 '18 16:05 smartinick

Now if i try to add example that notification enable / disable part to my code ESP32 crash and reboots.

How logs looks like when it crash? Try to use this tool to see why it crash: https://github.com/me-no-dev/EspExceptionDecoder

chegewara avatar May 04 '18 16:05 chegewara

i guess either the remoteCharacteristic or the Descriptor returned by getDescriptor is null.... how about this code with nullptr handling? void SubscribeNotification(BLERemoteCharacteristic* blechar) { Serial.print("Subscribing to Notification for BLERemoteCharacteristic: "); static BLERemoteDescriptor* brd; brd = blechar->getDescriptor(CCC_UUID); if (brd == nullptr) { Serial.println("Failed to find CCC Descriptor, "); } else { Serial.print("Found CCC Descriptor, sent not_On sequence, "); brd->writeValue((uint8_t*)not_On,2,true); } blechar->registerForNotify(notifyCallback); Serial.println("registered for notifications!"); }

smartinick avatar May 04 '18 17:05 smartinick

@JaspaJami Did you solve the komoot request problem for streets longer fitting in the 1st packet? Can you share that part somewhere...? Having the same - clueless - issue now :D

smartinick avatar Jul 12 '18 20:07 smartinick

Did you try to set MTU?

chegewara avatar Jul 12 '18 20:07 chegewara

No. If you look there, they write that they can only send 20 bytes on android and if the street-name is too long it's truncated.

so you "registerfornotify" and get a buffer sent by the phone that is max 20 bytes and if the street name is longer, you need to read the data.... Just reading the value of the bleremotecharacteristic does not do the trick...

and as i rememered JaspaJami asking about this here.... i'm curious if he solved it.

smartinick avatar Jul 12 '18 21:07 smartinick

Just try to use BLEDevice::setMTU(100) for example (up to 512). By default mtu is equal 23 and because of that notify max length is 20 bytes. Im not saying this will work, because peer device may not work with higher mtu values.

chegewara avatar Jul 12 '18 21:07 chegewara

Thanks for the hint, i did a quick test - setMTU does not exist, so i updated the arduino-lib, now BLEDevice does not compile as esp_bt.h does not exist. so this will take some more time to fix.... i'll come back here with my result!

smartinick avatar Jul 13 '18 06:07 smartinick

So for now give up. setMTU does not exist on my "old" version of the ble library, so i've updates the lib, which won't compile because esp_bt.h does not exist. created the include file as noted in the other open issue, and now i un into the "c++ eceptions not enabled" issue which is waiting since 2018-02-05....

smartinick avatar Jul 13 '18 06:07 smartinick

"c++ eceptions not enabled" are enabled for quit some time, you just need to update your arduino-esp32. Fastest way is to delete old one and download new, but if you are familiar with git then its pretty easy. Also there is no issue with esp_bt.h anymore.

chegewara avatar Jul 13 '18 08:07 chegewara

chegewara - thanks for your hints - i already did a update via GIT last time when it did not work, but now after starting from scratch setMTU works, no Exception-not-enabled errors and Komoot sends Pakets longer than 20 bytes - THANKS for the hint!

(And to my git-update problem.... i also had the esp32-ble lib zip/downloaded some time ago and still in my arduino/libraries folder. After the git-update i had the excepetion-not-enabled problems. Now, i had the issue that i had 2 BLE Libraries - the one included in the arduino-esp32 sdk and my old one... so i guess during my GIT-Update something went wrong (submodules..?) as i didn't have the ble librarie within arduino-esp32.

smartinick avatar Jul 24 '18 19:07 smartinick

Sorry, just a mistaken click :D

smartinick avatar Jul 24 '18 19:07 smartinick

smartinick, I wonder how you did to sniff it! Could you give me a light?

Grazie!!

vcmorini avatar May 14 '19 07:05 vcmorini

smartinick, I wonder how you did to sniff it! Could you give me a light?

Grazie!!

https://www.adafruit.com/product/2269 & wireshark....

smartinick avatar May 14 '19 08:05 smartinick

@smartinick , after your hint I also made a sniff, and.. I also need opcode of 0x12 instead of 0x52. nRF is sending 0x12 (write request) and it is working with the ble device, but when I try exactly the same with esp32, the opcode is (0x52 write command), and it does not work. So I guess that is the problem. Did you have any luck?

esp32 write command with opcode 0x52: https://user-images.githubusercontent.com/44900293/58360132-4a13b100-7e87-11e9-8a14-19da8d97821c.png

about the sniff setup: Adafruit Bluefruit LE Sniffer V1 + Nordic's nRF Sniffer Utility (Windows only) + Wireshark version 1.12.1 (not the best, usually I have a hard time to make it work properly and sniff packets right - it is a very emotional setup)

vcmorini avatar May 24 '19 22:05 vcmorini

To be exact the write_command (0x52) is handled as write_request (0x12) + command_flag (0x40), and that's why the analyzer handles it as write request, and waits for a response. You are right, you can see "missing packets" because there is no response. But again, this is only an issue in the analyzer.

https://www.silabs.com/community/wireless/bluetooth/forum.topic.html/ble_write_withoutre-NnIl

chegewara avatar May 25 '19 01:05 chegewara

https://github.com/dlenski/ttblue/blob/master/tt_bluetooth.md

HANDLE <- data: host sends data to device using the ATT write-no-response command (opcode 0x52) HANDLE <-- data: host sends data to device using the ATT write-request command (opcode 0x12)

chegewara avatar May 25 '19 01:05 chegewara

Thks @chegewara , these articles were of great help!

Just to make it clear for those who might have the same issue: e.g.: in Arduino IDE: pRemoteCharacteristic->writeValue(value, length, true); -> opcode 0x12 pRemoteCharacteristic->writeValue(value, length); -> opcode 0x52

vcmorini avatar May 26 '19 10:05 vcmorini

@vcmorini opcode write to descriptor or characteristics?

EequalmcUP2 avatar Aug 19 '21 13:08 EequalmcUP2