Read response with only the data of a string

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

I'm trying to create a characteristic that contains a string with a max length that will only return the parts of the data that are not 0.

So far, I couldn't figure out how to do it but I do think it should be possible because the first name in the weight scale example does it.

In my client the zeros that are send are filtered and ignored, but I have a problem with the tests with the Profile Tuning Suite.

Is it possible to do this in a custom service with a custom characteristic?

0 Likes
1 Solution
Anonymous
Not applicable

I found a way to only send the data in a longer string on a read request on the server. The actualLen value of the characteristic must be changed so that the framework only uses the data in the actualLen of the array. The CyBle_GattsWriteAttributeValue function does not use the actual length value in the CYBLE_GATT_HANDLE_VALUE_PAIR_T parameter, that is told in the documentation.

The macro CYBLE_GATT_DB_ATTR_SET_ATTR_GEN_LEN(handle, value) can be used to achieve the shorter response. This macro should be used after the CyBle_GattsWriteAttributeValue function is used to write the data in the database.This value won't change when the value in the database is changed, so after each write, this macro is advised.

View solution in original post

11 Replies
Anonymous
Not applicable

Declare your string characteristic with the size/length in the profile. Then, when you write data to it, merely append the data with hex 00 to signify the end of the string. Using a string will by default cut off the data after the null character (0x00) when using in the program/C-code. Anything that is done in a standard characteristic is possible to do in a custom characteristic.

(You might need to implement some handling code to remove/ignore 0's if the behavior you want is different from what I'm thinking above)

0 Likes
Anonymous
Not applicable

I added an image that shows the difference when the exact same operations are done on the two services. As you can see, the raw data that the example service returns does not have the zeroes added on, but the data type has a length of 30. The zeroes are handled in the client application, but I can't pass the UDS/SR/CW/BV-01-C test for the User Data Service in the Profile Tuning Suite. It probably won't be a problem in practice, but it could be a problem for communicating with other clients that implement the User Data Service.

Difference services.png

0 Likes
Anonymous
Not applicable

Ahhh, I see what you mean now (the images were helpful for clarity )

When the remote device connects to your bluetooth device and does a gatt read, there is the event CYBLE_EVT_GATTC_READ_BY_TYPE_RSP that you can handle. It will allow you to modify the data/values being returned. That is where you would catch the read request, remove the appended zeroes/nulls and continue sending the rest of the data. That event will be generated on a read-by-type using characteristic UUID or handle I believe.

The event would be handled under your BLE callback handler code for the event, and it should be as simple as changing the length of the data response to match the length of the valid data you want returned.

0 Likes
Anonymous
Not applicable

The CYBLE_EVT_GATTC_READ_BY_TYPE_RSP event is never called on my server. I added it to the AppCallBack function switch case with a print but it never showed any life. Is the event not an event for the client, because of the CYBLE_EVT_GATTC name?

This results in the image are the exact same calls from the client to the server, and the only difference is the User Data Service implementation on the GATT Server.

0 Likes
Anonymous
Not applicable

Ah, my mistake. Yes you are correct; The GATTC indicates client. Hmm, I was thinking it was a pretty obvious event, but now I'll have to look deeper.

0 Likes
Anonymous
Not applicable

This might be the one I was thinking of: CYBLE_EVT_GATTS_READ_CHAR_VAL_ACCESS_REQ; You will need to set the CYBLE_GATT_DB_ATTR_CHAR_VAL_RD_EVENT  property to true to have the event occur. It says you can modify the response to be an error, but playing with it in debug to see if you can modify the returned data is what I would try, as no other events seem to be useful for this scenario

0 Likes
Anonymous
Not applicable

According to this thread, it seems like the event doesn't exist that I was looking for. Potentially, modifying the write request event on the server to change the data length to append/cutoff after the data reaches a zero might be what is happening? I believe the UDS source code is available in the PSoC creator. The custom services don't implement code the same way as the standard services. But, the same features and functionalities are generally possible from what I've seen.

0 Likes
Anonymous
Not applicable

The standard UDS uses the CyBle_UdsRegisterAttrCallback(UdsCallBack); function to use the UDS callback which has different events. The read event in that callback is the CYBLE_EVT_UDSS_READ_CHAR event, which has a eventParam with type CYBLE_UDS_CHAR_VALUE_T, which has the CYBLE_GATT_VALUE_T * value field that can be edited to change the response.

I'm now trying to change custom service to use that callback by copying the generated files from the example and pasting it in my source and header folders.

I also added  #define CYBLE_UDS and #define CYBLE_UDS_SERVER to the BLE_gatt.h file to make it activate the callback handler.

In BLE_uds.c the handles are not generated so I changed them to the defines from BLE_custom.h.

I added the CyBle_UdsRegisterAttrCallback(UdsCallBack); call to my udsInit and it seems to work so far.

Tomorrow I will look further at it to see if I can fully implement it without to much trouble every time code is generated and will update here.

I do think that it is strange that these type of "hacks" are needed to make it work, and think that there should be a way to do it with the normal callback function.

0 Likes
Anonymous
Not applicable

I thought about it and I don't think that this way will work for my project, because I added characteristics to the UDS and to add those to the UDS callbac, I would have to make many changes to the generated code, which would result in too much problems I fear. It is just not an easy way to use the Cypress BLE stack and would make the code much more difficult to understand and change.

0 Likes
Anonymous
Not applicable

I agree, it would be difficult to maintain

(I also agree that having these "hacks" removed into normal functional operations would be nice)

You could try have the UDS service itself in the BLE profile and modifying/adding attributes to it to get similar behavior, but that is a hit or miss for usefulness

0 Likes
Anonymous
Not applicable

I found a way to only send the data in a longer string on a read request on the server. The actualLen value of the characteristic must be changed so that the framework only uses the data in the actualLen of the array. The CyBle_GattsWriteAttributeValue function does not use the actual length value in the CYBLE_GATT_HANDLE_VALUE_PAIR_T parameter, that is told in the documentation.

The macro CYBLE_GATT_DB_ATTR_SET_ATTR_GEN_LEN(handle, value) can be used to achieve the shorter response. This macro should be used after the CyBle_GattsWriteAttributeValue function is used to write the data in the database.This value won't change when the value in the database is changed, so after each write, this macro is advised.