Characteristic Notifies Correctly but Blank When Read

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

cross mob
ToVa_285016
Level 5
Level 5
100 replies posted 50 replies posted 50 questions asked

Hi,

   

I have a system values characteristic that is being read by an android app.  The characteristic delivers the correct values when the PSOC notifies the app, but when the app reads the characteristic, it shows up as whatever values are in the component in PSOC Creator.  Am I writing to the GATT database incorrectly?  Below is my update code.

   


// Sends notificaiton of sysValues change to the app
void NotifySysValuesChange()
{
    // Set up value structure
    struct valsStruct{
        uint16 angleLow;
        uint16 angleHigh;
        uint8 mode;
    } tempStruct;
    
    // Gather system values and update GATT database
    tempStruct.angleLow = dataLocal.angleLow;
    tempStruct.angleHigh = dataLocal.angleHigh;
    tempStruct.mode = dataLocal.mode;
    CYBLE_GATT_HANDLE_VALUE_PAIR_T tempHandle;
    tempHandle.attrHandle = CYBLE_ROTARYACTUATOR_SYSVALS_CHAR_HANDLE;
    tempHandle.value.val = (uint8 *)&tempStruct;
    tempHandle.value.len = sizeof(tempStruct);  
    
    // Update Gatts Server
    CyBle_GattsWriteAttributeValue(&tempHandle, 0, &cyBle_connHandle, CYBLE_GATT_DB_LOCALLY_INITIATED);    
    // Send notificaiton if authentication is complete
    if(deviceConnected){CyBle_GattsNotification(cyBle_connHandle,&tempHandle);}
}
 

   

Once again, the notification delivers correctly, but reading the database does not reflect the update.

   

Please let me know if you have any ideas.  Thanks in advance,

   

Tom

0 Likes
1 Solution
Anonymous
Not applicable

I've setup my own code to use hardcoded values, since the application doesn't change. For your case, I would assume you are more curious than anything for why the value is wrong: My guess would be that the serialization of the C++ object in memory is:

   

<length of structure><data bytes> or <data bytes><length of structure>

   

This would have +1 bytes for the actual data due to the metadata of the structure/container. With larger structures/containers the metadata amount will increase, thus the length of "type" will not give the length of the data in the type, but rather the length of the entire type/object. This SO post explains it in different words: https://stackoverflow.com/questions/4240554/c-c-getting-struct-size

   

Here is a better explanation explaining packing of the data in structures(this is probably what is really going on): https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-o...

   

I would suggest hard-coding it as a macro or constant that correlates with the data structure that you are coding for using. Since the length will change between each structure depending on the contents anyways, this will save you codespace/time. If you are looking for a way to implement a generic function that will grab a length an arbitrary structure type, then I'm not sure what even I would do in that situation. Possibly implement a function that checks the type and returns the size of the data? Or, you could transmit the entire "6" bytes of the structure and have the receiving side cast it to a structure of the associated type for use on that device; this might not work when traveling between different processors/chips.

View solution in original post

0 Likes
6 Replies
ToVa_285016
Level 5
Level 5
100 replies posted 50 replies posted 50 questions asked

I have discovered that the database is not being written to at all.  Can anyone help me understand what I am doing wrong in the writing of the characteristic?  It looks just like the examples...

   

Thank you,
Tom

0 Likes
Anonymous
Not applicable

Make sure you are handling the CyBle_ProcessEvents() call in your main loop;

   

Also try checking the API responses from the notification() and writecharacteristic() function calls; If they retun an error, then that would explain why it isn't working. Double check your pointers/references are correct (pointing to the correct things)

   

The most likely bet is that the function is returning an error code; I would check that to see what is going on.

0 Likes

Hi,

   

You were correct, I am receiving CYBLE_GATT_ERR_INVALID_ATTRIBUTE_LEN.  The sizeof(tempStruct) is returning 6, but the length should be 5 (two uint16s and a uint8).  If I hardcode it to 5, the error goes away, and my app works!  

   

Can you explain why this might be giving me a wrong number, and what a more appropriate way to retrieve the size might be?

   

Thank you,

   

Tom

0 Likes
Anonymous
Not applicable

I've setup my own code to use hardcoded values, since the application doesn't change. For your case, I would assume you are more curious than anything for why the value is wrong: My guess would be that the serialization of the C++ object in memory is:

   

<length of structure><data bytes> or <data bytes><length of structure>

   

This would have +1 bytes for the actual data due to the metadata of the structure/container. With larger structures/containers the metadata amount will increase, thus the length of "type" will not give the length of the data in the type, but rather the length of the entire type/object. This SO post explains it in different words: https://stackoverflow.com/questions/4240554/c-c-getting-struct-size

   

Here is a better explanation explaining packing of the data in structures(this is probably what is really going on): https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-o...

   

I would suggest hard-coding it as a macro or constant that correlates with the data structure that you are coding for using. Since the length will change between each structure depending on the contents anyways, this will save you codespace/time. If you are looking for a way to implement a generic function that will grab a length an arbitrary structure type, then I'm not sure what even I would do in that situation. Possibly implement a function that checks the type and returns the size of the data? Or, you could transmit the entire "6" bytes of the structure and have the receiving side cast it to a structure of the associated type for use on that device; this might not work when traveling between different processors/chips.

0 Likes
ToVa_285016
Level 5
Level 5
100 replies posted 50 replies posted 50 questions asked

Hi,

   

Thank you for the explanation.  I think I will just be putting in a set of macro sizes for my different structures.  Something that will definately help me in future projects.

   

Regards,
Tom

0 Likes
Anonymous
Not applicable

Glad I could help out. Good luck on the project,

   

Pratt

0 Likes