I am using PSoC Creator 4.2 to write a BLE application for a CYBLE-416045-02 and the basics are all working very well.
Of the 3 custom services I have, one is a readable/writable 32-character UTFS8 string. The initial value set in the component is a null string.
As the app starts up, it looks to the EEPROM to read the name that has been given to the system previously and if none has been set, it creates a default name of 'No Given Name' which is 13 character long. I use the Cy_BLE_GATTS_WriteAttributeValueLocal() function to set the name.
When this is read by the client, it is a 32-character value that is null-padded after the actual string.
When I write to the service with (say) 'Test Lamp' I can see the 'handleValPair' structure has the new value and the 'len' parameter is 9 (which is correct).
I then use the Cy_BLE_GATTS_WriteAttributeValuePeer() function to write the value to the local database (and I also update the EEPROM).
However when I then read the service value, what I get is 'Test LampName'.
When I look at the full string sent to the client, it is the same ASCII character null terminated.
If I reboot the code, it will then correctly read 'Test Lamp' form the EEPROM and sets the value in the local GATTS database accordingly.
What do I have to do to save the name to the local database with the correct length (other than rebooting!)?
The code I use is:
writeReqParameter = (cy_stc_ble_gatts_write_cmd_req_param_t*)eventParam;
if( CY_BLE_LOCATION_SETTING_CHAR_HANDLE ==
memset( &newLocalName, 0, sizeof( tLocalName));
memset( newLocalName.localName, ' ', sizeof( newLocalName.localName));
newLocalName.nameLength = writeReqParameter->handleValPair.value.len & 0xff;
writeReqParameter->handleValPair.value.len & 0xff);
// Save to the EEPROM for the next reboot
// Save to the local GATTS database
writeReqParameter->handleValPair.value.val = newLocalName.localName;
You can see there my attempts to space-pad the name and also repoint the string pointer. (It doesn't mater if I don't do this and leave the 'val' pointer pointing to whatever it originally was.)
I guess you are using Emulated EEPROM which is implemented in Flash. Flash writes happen in row wise. When you initiate a Flash write request the entire row of flash gets erased and the new values will be written. That is the reason you are getting the exact value of name when you reset the device.
The GATT database (characteristics) is stored in RAM. So when you are writing to GATT database we recommend you to erase completely and write new value just like how Flashwrite happens.
@MichaelF_56 - can you please stop marking responses to my questions as 'helpful'. I think you have done this to every single response I have received in all of my questions.
In this case I have not yet tried the suggested answer, but on the face of it, it seems as though it is exposing a logical flaw. The struct that holds the pointer to the new value (string or whatever) also contains the length of the value. It sounds like the length for a string is not being saved as the value is being written to the database.
If that is the case then what is the point of passing in the length of the value (string) and why is there no documentation to say that a string in the GATT database MUST always be written with the full length?