-
Notifications
You must be signed in to change notification settings - Fork 715
Setting the appearance characteristic of the device #88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Howdy, More than that, the Arduino-ESP32 library opts to build against the latest ESP-IDF and that means that the breakages in ESP-IDF have flowed through to breakages in Arduino-ESP32. That said ... that isn't the issue you are discussing. Help me to help you ... assume that I am juggling so many parallel stories that I can't keep context straight in my head. Please try and make each issue as self contained as possible or, at a minimum, point to other issues that I should pre-read before reading the current one. Can you clarify whether or not your ESP32 BLE app is a BLE Server or a BLE Client. I am going to assume it is a BLE Server that advertises its presence. By setting the appearance, can I assume that you mean exposing this characteristic? If yes, then my immediate guess is that you can create a BLE Server that contains a service that contains a characteristic with 16bit UUID 0x2A01 as documented and described above. What you would do is create and expose a new characteristic. Read the specification of that characteristic and see if it makes sense. If after reading that and the BLE C++ documentation we make available it is still a puzzle ... then I really want to hear back. If something is confusing, then I want to try and resolve that confusion in the documentation so that both you and future readers/users can understand. If something isn't clear, then I consider that my problem to fix. |
I understand you have a lot to deal with, so I appreciate your help even more! I have read the specs and considered creating the characteristic (yes, it is a BLE Server, sorry for not being more specific). I just thought that if I create it from pService, which in my case is cycling speed/cadence sensor, then it appears under that service and the Generic Access characterstic of Appearance would remain unaffected. I have just tested it and it is indeed the case - new Appearance shows up under the cycling service and the Generic Access Appearance remains Uknown. And I do not know how I can create it from the Generic Access service (0x1800), as it does seem to be exposed in the code. If it is accessible, I do not know how to do that. In the nRF SDK the characteristic is set at the creation of the device, together with its name and connection parameters. In your BLEDevice.cpp it seems only the name can be assigned. |
Can you paste link to nRF code you reference to? |
I have downloaded the nRF SDK, but the code is online here: searching for 'appearance' should get you to the relevant part of the code. |
@JabberwockPL Ohhh!! I think I see what you are saying. Let me play it back to you and see if this sound right ... We have a service type with UUID 0x1800 called "Generic Access" .. see: This service is a prescribed service and can have a variety of characteristic values including 0x2A01 (Appearance). How do I use the BLE C++ libraries in order to expose characteristic 0x2A01 as belonging to service 0x1800? Does that sound about right? I don't have an immediate answer for that and will have to study to assist. |
Well, actually if I do not create the characteristic at all, nRF already shows that the Generic Access service has that characteristic, it only shows in the log „'[0] Unknown' received” and the characterstic is visible under the service as '[0] Unknown'. But of course I would like to set to according to my needs. |
Yes, but you can't add any characteristic to generic access 0x1800 and generic attributes 0x1801 service. You need to create service as you can see at https://devzone.nordicsemi.com/tutorials/8/
and i dont think you can add name to those services, but i will investigate it further. |
But I do not want to add my own chatacteristic, it seems Appearance is created anyway at the device creation (as nRF Connect shows). I just want to set it, just like you allow setting the name of the device (characteristic 0x2A00) with BLEDevice init(). I cannot figure out from your code how exactly you set the name (I.e. 0x2A00) at the device creation, but I guess the method (and time and place) should be the same for the appearance. |
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEDevice.cpp#L191 Mail me and we can talk in Polish, [email protected]. |
Ooooh ... I had made a mental note to go research how "appearance" was going to be set system wide but it looks like you may have found the answer (you are AWESOME). Are we saying that setting the device name when we create a BLEDevice() is what causes the value of 0x1800 -> 0x2a01 to be set? |
Ohh ... wait again ... as soon as I re-read, it appears we have two characteristics ... |
Yes, and both are mandatory, which means both are created somwhere in here: https://github.com/espressif/esp-idf/blob/a4fe12cb6d195a580a57690ceed45e1e06dc58e0/components/bt/bluedroid/stack/gap/gap_ble.c#L371 |
But i guess answer to the question is, you cant change appearance name in server. Its up to client to match service UUID and display desired name. |
Name... or an icon. So I think add icon is a good candidate, as it has two bytes, exactly as the apperance UUID. |
Or I could skip the guessing and check GATT_UUID_GAP_ICON: ... and it is a match: 0x2A01 |
Well, my guessing is not about how its handled, its about how good is this answer to you. |
Well, as I understand, the function is not exposed in the Arduino library, so for now I cannot do anything about it. However, I am not sure how useful it would be anyway - I mean, it would be extremely silly if the app developers have detected the sensors based on their icons and not on the services they provided? So while I cannot exclude that, it might be that my emulated sensor differs in other ways from commercial sensors. My next candidate is manufacturer's name, as most examples seem to have that set as well. That I can access creating the relevant service, so it should be no problem. |
Almost found it, just need to investigate if it can be set in arduino. |
OK, it is possible to do it with arduino ide. You need to those 2 includes:
PS: now its time to find function to set manufacturer's name |
About manufacturer's name im not sure, but this is what i found. I found also esp32-snippets/cpp_utils/BLEAdvertising.cpp Lines 30 to 31 in 92958bc
|
I have already set the manufacturer's name, it is a characteristic in a separate service (Device Info). I will try to use the code you have provided. |
I could not get your code to work, so I googled a bit and found this: I have copied the code verbatim and set p_name (just to test the name change), but it does not work, it throws 'unknown reference to' for the procedure. I have dug some more and found that the advertising data also contains the appearance icon, which I thought might be even more import for detection. So between this: you just need to put this: And it worked! nRF Connect even before the connection sees my device as a cycling sensor! However, strangely enough, it still asks for the characteristic 0x2A01 and it comes up with nothing. Oh, and the cycling apps still do not work... Back to investigations, I guess. |
I have posed a question against the underlying ESP-IDF APIs ... see: |
Oh my, it seemed like a simple question at first! I hope for their answer... |
That's a good thought ... how separate should a "BLE Server" advertisement be from the actual properties that the advertised server truly exposes. Should setting an attribute in the advertisement force the server to have the advertised property? Should setting a property in the server force the advertisement to be consistent with the properties offered? I can't say I disagree with either of those. |
Its up to you. In my opinion it should be done in ble stack, but as for now you can add some code like: PS Im little busy this days, thats why it took me so long to find it and test it. |
@chegewara |
@JabberwockPL Like i said, it was tested with esp-idf, i have to prepare Arduino ide first but i have no time. But it should work ith arduino too If you can provide service, i think its 0x1816, and characteristics you are trying to run then i can test it with BLE library. |
This results in:
But no worries, it was most likely not the main source of the problem (but rather non-standard implementation of sensor handling by the apps, as I have written here. |
Try with this, should have working on arduino:
|
It compiles, but ESP32 goes into reboot loop:
Commenting out GAP_BleAttrDBUpdate(GATT_UUID_GAP_ICON, &attr); elimates the loop so it must be the cause. |
Update: pAdvertising->setAppearance(1157); However, after reading the specs again, I have realized that some apps might expect the service UUID to be exposed in advertising data themselves. For that purpose I have used: pAdvertising->setServiceUUID(BLEUUID((uint16_t)0x1816)); but this returns the error: |
Good to hear. @nkolban i have a question about BLEAdvertising class creator. There is 2 variables with exact same structure, m_advData and m_advDataScanResponse, and both are set as config adv data. What is purpose to have it both? |
@JabberwockPL if you follow the routines then you can see that setServiceUUID() sets up m_advDataScanResponse.p_service_uuid, but this error is from this line: which is just after
I dont know if somewhere else in your code m_advData.p_service_uuid is updated, but if not then from constructor it is nullptr. My advice is to try add those lines or alter it:
|
No, that was not the problem. setServiceUUID is supposed to setup the value, so it does not need to be set up earlier. The actual problem is described here: https://www.esp32.com/viewtopic.php?f=13&t=2253 All it took was to put the UUID in the long form: pAdvertising->setServiceUUID("00001816-0000-1000-8000-00805f9b34fb"); now I can happily declare that almost all apps are detecting the sensor correctly! Again, thank you very, very much, I could not have done it without the help... |
@chegewara In BLE there are always two advertising packets. One that is always broadcast and one that is returned to a client when it receives a broadcast advertisement and then says I want the additional advertisement packet. I'm probably getting the technical words wrong here ... but I believe this is called a scan response. At a high level ... imagine that the BLE Server is broadcasting adverts .... when a client receives an advert ... that may be all it needs ... however it is the clients choice to immediately turn around and ask the BLE Server give me the scan response advert. In ESP-IDF, we define two adverts. One which contains the always advertised packet ... and a second advert that is returned by the server only when the client asks for the scan response advert. Notice that one structure is set scan_response = false and the other set scan_response = true. |
We may have a relationship between this issue and #115 |
Maybe this can explain something:
|
@JabberwockPL ive found the problem why it is working this way
but doesnt work that way
This is the clue:
@nkolban When we change this line it will works:
Why? I dont know. Just works. BTW pAdvertising->setAppearance(1157); doesnt work for me |
The sad thing about this issue is that I created a post back in June warning others not to use a uuid_len of anything other than 16 ... and failed to heed my own advice: https://www.esp32.com/viewtopic.php?f=13&t=2253 Taking an action to resolve properly. |
Code changed ... commit pending. |
Code changed. Please let us know if we are good now. |
So I should now to try code it with: pAdvertising->setServiceUUID(0x1816); I wil do it, but it might take a bit, as it requires partial dismantling my bike installation (and I am having a blask using it :) ). But I do plan to have some other code changes, so I will get around to it. |
The new API is:
|
Ok, I will try that. |
Closing for just now. Re-open as needed. |
This can now be set using esp_ble_gap_config_local_icon() on both Arduino and the IDF. |
The code for the cadence/speed sensor is almost done, however, its application is hit-and-miss. One particular app that has worked before now refuses to do so, disconnecting with cryptic messages... Some apps do not recognize the sensor at all. On the other hand, some other apps do and they show the correct inputs. nRF Connect is always solid, showing exactly what I need (but the apps themselves are bad).
I have even downloaded the nRF SDK, as they have an example code for cadence/speed. The code does not look fundamentally different from mine (well, mostly yours :) ), but there is one notable difference: they set the appearance of the device to Speed and Cadence Sensor.
Naturally, I wanted to do the same, but it seems the characteristic is not exposed at all in the library - the device name is set with .init and that is about it. Is there any way I can set it?
The text was updated successfully, but these errors were encountered: