- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Does the BLE stack create or update a value when a non bonded device pairs?
In other words, when a device pairs, how do you know if you should store it, or if it already stored?
Solved! Go to Solution.
- Labels:
-
BLE
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Herb,
Select the 'Strict Pairing' option as 'NO'.
Basically the strict pairing option expects the same security level selected in the peer device as well and if the security level in peer device is different then the pairing process will fail. Here , we do not know the security level of mobile device and hence we should proceed with Strict pairing as NO.
I am attaching a sample project to show the implementation of CyBle_GapGetBondedDevicesList() API. Sending a 'd' char over UART will display the bonded device list on serial terminal.
-Gyan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
The global variable 'cyBle_pendingFlashWrite' contains status of pending write to flash operation. This will be clear after write operation completes. For example a when two devices connects with bonding 'Yes', first they will check if the corresponding bonding data is already present in the Flash. If they are already bonded ,they will not initiate the pairing process again and will encrypt the BLE link with stored keys and will start the BLE communication.
If they are not bonded, they will go through the pairing process and the variable 'cyBle_pendingFlashWrite' will be set. In the main loop you have to always check the status of this flag and call the API CyBle_StoreBondingData().
Note: You should call CyBle_StoreBondingData() in a continuous loop because one call of this API writes one ROW of flash memory and the bonding information might be more then one ROW size.
So in summary , the variable cyBle_pendingFlashWrite will take care for storing the bonding data.
Well, you can also check the bonding devices present in Flash by using the API CyBle_GapGetBondedDevicesList() API before storing the bonding data.
For example , on connection in the event CYBLE_EVT_GAP_DEVICE_CONNECTED you can check if the connected device is already present in the Flash or not by using the above API and based on this check along with cyBle_pendingFlashWrite , you can call CyBle_StoreBondingData() API.
-Gyan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Gyan, thank you for your response, I will delete the post on SFLASH, we thought we were correct.
Let me summarize, and let me know if I am incorrect.
So when a new device, sends the proper pass key in response to this instruction: CyBle_GapAuthReq(cyBle_connHandle.bdHandle,&cyBle_authInfo); // request pairing
The function will set cyBle_pendingFlashWrite and I use that to determine if a device needs to be bonded? Also, I use a while function, testing that flag to determine when the data has been stored using CyBle_StoreBondingData()? Why is there not a flag called NEW_bd_DEVICE? Would have been so much clearer.
Also, when a previously bonded device connects and the code hit this instruction, CyBle_GapAuthReq(cyBle_connHandle.bdHandle,&cyBle_authInfo); it determines that the device is already paired and does not set cyBLE_pendingFlashWrite? That is the part that is not clear?
Otherwise I would just keep storing the same device four times.
Herb
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Herb,
If the device is already paired and BONDED , the cyBLE_pendingFlashWrite will not set. The flag will only set when there is new bonding information needs to be store in the FLASH.
You just have to put the below code snippet in main infinite for(;;) loop and do not need to check anything else. BLE stack will take care of updating the variable cyBLE_pendingFlashWrite whenever there is a new device needs to be bond.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
if(cyBle_pendingFlashWrite!=0)
{
CyBle_StoreBondingData(0);
}
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
You can verify the bonding device number by calling CyBle_GapGetBondedDevicesList() API which I think will clear your queries.
-Gyan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That is great, still not sure why that flag is not called BONDED_DATA_TO _BE_STORED would have been so much clearer?
Also, on the CyBle_GapGetBondedDevicesList() it states to have a structure to hold the data, that is where I am lost, could you show and example of actually implementing this instruction?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok, pairing is not working as planned, please review and advise. What I am trying to do is make is so the person with the phone enters a code and pairs, that is all.
The phone asks for the PIN code, I enter 123456 and is says incorrect pin or password, I tried entering in hex, no joy? It wants me to enter the code on the other device? If I turn off bonding I lose all the functions.
I want this procedure.
A phone connects and if not bonded asks for the pin
The pin is entered and then stored.
On the next connection is goes right through.
Here is my code and BLE security settings:
function in main
if(pairingUpdate == TRUE)
{
// time to store the user pairing data if it is CYBLE_pendingflashwrtie is set
if(cyBle_pendingFlashWrite == TRUE)
{
CyBle_StoreBondingData(0);
pairingUpdate = FALSE;
}
}
function in BLE stack
case CYBLE_EVT_GAP_DEVICE_CONNECTED:
/* This flag is used in application to check connection status */
/* Update attribute handle on GATT Connection*/
newColor = BLUE;
CyBle_GappStopAdvertisement();
deviceConnected = TRUE;
case CYBLE_EVT_GAP_DEVICE_CONNECTED:
/* This flag is used in application to check connection status */
/* Update attribute handle on GATT Connection*/
newColor = BLUE;
CyBle_GappStopAdvertisement();
deviceConnected = TRUE;
// test for the Pairing code not set flag, 00010000 AND with Status, if the PCNS is set (no user code) the result will be zero
if((Status & PCNS) == FALSE)
{
valid_passkey = default_passkey; // if not set use the default
CyBle_GapFixAuthPassKey(1,valid_passkey); //set pass key
CyBle_GapAuthReq(cyBle_connHandle.bdHandle,&cyBle_authInfo); // request pairing
}
else
{
valid_passkey = user_passkey; // if it is store it
CyBle_GapFixAuthPassKey(1,valid_passkey); //set pass key
CyBle_GapAuthReq(cyBle_connHandle.bdHandle,&cyBle_authInfo); // request pairing
pairingUpdate = 1;
}
break;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Herb,
Select the 'Strict Pairing' option as 'NO'.
Basically the strict pairing option expects the same security level selected in the peer device as well and if the security level in peer device is different then the pairing process will fail. Here , we do not know the security level of mobile device and hence we should proceed with Strict pairing as NO.
I am attaching a sample project to show the implementation of CyBle_GapGetBondedDevicesList() API. Sending a 'd' char over UART will display the bonded device list on serial terminal.
-Gyan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Gyan, I cannot thank you enough, I was really stuck on this, and now it works, your example was very clear.
One question, you added in the case CYBLE_EVT_GAP_DEVICE_CONNECTED:, can I assume that this was only for display purposes?
apiResult = CyBle_GattcStartDiscovery(cyBle_connHandle);
printf("Starting Discovery \r\n");
if(apiResult != CYBLE_ERROR_OK)
{
printf("StartDiscovery API Error: %x \r\n", apiResult);
}
break;
Could I ask you to look at one more thing, I need an example of a read only from the client. My writes, used for read, are not reading back for some reason. But I would really like a clear example of setting up a read, it is really no where out there. If you could add one to the project you created, I would appreciate it.
write_request_param = (CYBLE_GATTS_WRITE_REQ_PARAM_T *) eventparam; /* this is where the entire data structure of the BLE packet is stored, value, size length, descriptor, limits, etc */
if(CYBLE_OUTPUT_CONTROL_OUTPUT_CONTROL_VALUE_CHAR_HANDLE == write_request_param->handleValPair.attrHandle)
{
BLE_Output_Control = write_request_param->handleValPair.value.val[0];
OUTPUTCONTROL.attrHandle = CYBLE_OUTPUT_CONTROL_OUTPUT_CONTROL_VALUE_CHAR_HANDLE;
OUTPUTCONTROL.value.val = &BLE_Output_Control;
OUTPUTCONTROL.value.len = OUTPUTCONTROL_CHAR_DATA_LEN;
outputUpdate = TRUE;
CyBle_GattsWriteAttributeValue(&OUTPUTCONTROL,FALSE,&connHandle,FALSE);
}
/* Pairing*/
if(CYBLE_PAIRING_PAIRING_CONTROL_CHAR_HANDLE == write_request_param->handleValPair.attrHandle)
{
Pairing_control = write_request_param->handleValPair.value.val[0];
PAIRING.attrHandle = CYBLE_PAIRING_PAIRING_CONTROL_CHAR_HANDLE;
PAIRING.value.val = &Pairing_control;
PAIRING.value.len = PAIRING_CHAR_DATA_LEN;
//pairingUpdate = 1;
CyBle_GattsWriteAttributeValue(&PAIRING,FALSE,&connHandle,FALSE);
}
/* Pairing Data*/
if(CYBLE_PAIRING_DATA_PAIRING_DATA_VALUE_CHAR_HANDLE == write_request_param->handleValPair.attrHandle)
{
ble_passkey = write_request_param->handleValPair.value.val[0];
PAIRING_DATA.attrHandle = CYBLE_PAIRING_DATA_PAIRING_DATA_VALUE_CHAR_HANDLE;
PAIRING_DATA.value.val = &ble_passkey;
PAIRING_DATA.value.len = PAIRING_DATA_CHAR_DATA_LEN;
//pairingDataUpdate = 1;
CyBle_GattsWriteAttributeValue(&PAIRING_DATA,FALSE,&connHandle,FALSE);
}
/*STATUS*/
if(CYBLE_STATUS_STATUS_VALUE_CHAR_HANDLE == write_request_param->handleValPair.attrHandle)
{
BLE_Status = write_request_param->handleValPair.value.val[0];
BLE_Status = Status;
STATUS.attrHandle = CYBLE_STATUS_STATUS_VALUE_CHAR_HANDLE;
STATUS.value.val = &BLE_Status;
STATUS.value.len = STATUS_CHAR_DATA_LEN;
CyBle_GattsWriteAttributeValue(&STATUS,FALSE,&connHandle,FALSE);
}
/*Error*/
if(CYBLE_ERROR_DATA_ERROR_DATA_VALUE_CHAR_HANDLE == write_request_param->handleValPair.attrHandle)
{
BLE_Error = write_request_param->handleValPair.value.val[0];
BLE_Error = Error;
ERROR_DATA.attrHandle = CYBLE_ERROR_DATA_ERROR_DATA_VALUE_CHAR_HANDLE;
ERROR_DATA.value.val = &Error;
ERROR_DATA.value.len = ERROR_DATA_CHAR_DATA_LEN;
CyBle_GattsWriteAttributeValue(&STATUS,FALSE,&connHandle,FALSE);
}
// battery voltage
if(CYBLE_BATTERY_BATTERY_VALUE_CHAR_HANDLE == write_request_param->handleValPair.attrHandle)
{
BLE_Battery = write_request_param->handleValPair.value.val[0];
BLE_Battery = ((uint8)Battery_value);
BATTERY.attrHandle = CYBLE_BATTERY_BATTERY_VALUE_CHAR_HANDLE;
BATTERY.value.val = &BLE_Battery;
BATTERY.value.len = BATTERY_CHAR_DATA_LEN;
CyBle_GattsWriteAttributeValue(&BATTERY,FALSE,&connHandle,FALSE);
}
/* Send the response to the write request received. */
CyBle_GattsWriteRsp(((CYBLE_GATTS_WRITE_REQ_PARAM_T *)eventparam)->connHandle);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Herb,
Yes, you can ignore whatever is there in CYBLE_EVT_GAP_DEVICE_CONNECTED.
I am attaching a simple project here on read write characteristics value.
Few Notes -
-> Selecting 'READ' property of a characteristics makes the central(client) device to read the characteristics value from peripheral(Server) device.
-> Selecting 'WRITE' property enables the central device (PEER Initiated) and peripheral device (Locally initiated) to write a characteristics value in the server GATT database.
If you want to read the characteristics value first you need to write the characteristics value in the peripheral (server) database.
Attached project description:
On pressing a switch every time , I am writing an incremented variable value for a characteristics . When you read the same characteristics value in your central device after every time switch is pressed in peripheral device , you will see incremented value.
Hope it will help you to understand the concept.
-Gyan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Gyan, thank you again for your patience, that is exactly what i am doing, it does not function, here is my code and BLE setting. I have an LED blinking that tells me status is not zero, verified with the debugger, but when I do a read, all i get is zeros? Bundle attached.
uint8 Status = 0;
uint8 BLE_Status = 0;
CYBLE_GATT_HANDLE_VALUE_PAIR_T STATUS;
#define STATUS_CHAR_DATA_LEN 1
/*STATUS*/
if(CYBLE_STATUS_STATUS_VALUE_CHAR_HANDLE == write_request_param->handleValPair.attrHandle)
{
BLE_Status = Status;
STATUS.attrHandle = CYBLE_STATUS_STATUS_VALUE_CHAR_HANDLE;
STATUS.value.val = &BLE_Status;
STATUS.value.len = STATUS_CHAR_DATA_LEN;
CyBle_GattsWriteAttributeValue(&STATUS,FALSE,&connHandle,FALSE);
}
/* Send the response to the write request received. */
CyBle_GattsWriteRsp(((CYBLE_GATTS_WRITE_REQ_PARAM_T *)eventparam)->connHandle);
}
break;