Hello,
I have created my own BLE project. My main looks like this:
int main(void)
{
//bool erase_bonds;
// Initialize.
log_init(); // uses UART
timer_init();
//bsp_board_init(BSP_INIT_LEDS);
power_management_init();
buttons_leds_init(&erase_bonds);
uart_init(); // uses UART
ble_stack_init();
gatt_init();
peer_manager_init();
db_discovery_init();
//hrs_c_init();
sdcs_c_init();
bas_c_init();
scan_init();
NRF_LOG_INFO("SDCS client started.");
scanning_start(&erase_bonds);
NRF_LOG_INFO("Waiting for Button press...");
NRF_LOG_INFO("Button 2 -> start authentication");
NRF_LOG_INFO("Button 3 -> remote access open door request");
NRF_LOG_INFO("Button 4 -> set new encryption key via uart");
// Enter main loop.
for (;;)
{
idle_state_handle();
}
}
As you can see I initialize some modules (e.g. the logging module and the uart module) and I start scanning. After that I can establish a connection to another BLE (peripheral) device.
Debug log:
<info> app_timer: RTC: initialized. <info> app: SDCS client started. <info> app: Starting scan. <info> app: Waiting for Button press... <info> app: Button 2 -> start authentication <info> app: Button 3 -> remote access open door request <info> app: Button 4 -> set new encryption key via uart <info> app: Connected. m_conn_handle: 0x0 <info> app: GATT ATT MTU on connection 0x0 changed to 247. <info> app: BLE_GATTC_EVT_EXCHANGE_MTU_RSP <info> app: Data length for connection 0x0 updated to 251. <info> app: SDCS discovered. <info> ble_sdcs_c: Configuring CCCD. CCCD Handle = 14, Connection Handle = 0 <info> app: BLE_GATTC_EVT_WRITE_RSP, gatt_status: 0x0 <info> app: BLE_GATT_HVX_NOTIFICATION
As soon as the central is connected to the peripheral I can initiate the required authentication process by pressing Button 2. For the authentication I use an encryption key for AES-128 CBC (no padding) encryption. So far this all works when the connected peripheral device is using the standard encryption key. It doesn't work when it has set a custom encryption key.
Now I want to add functionality to my central so that when I press Button 4 on my central device it should show me some information on my RTT (terminal in Segger Embedded Studio) to instruct me to type in a desired encryption key. Then I want to be able to type in the desired encryption key by using UART (via MCU USB port (COM7) on my nRF52840 DK and PuTTY). Once I type q or Q in PuTTY terminal, UART should stop receiving via UART and let me process the input string in my firmware while still not running into errors.
So far I tried to realise this by using code from the examples/peripheral/uart/pca10056/blank/ses example solution. I can debug this example programm and it works.
Because I use the logging module and the uart module from the example program, I got an error in the initialization. I prevent that error from happening by disabling UART for the logging module (NRF_LOG_BACKEND_UART_ENABLED 0 in sdk_config.h). Now the logger is only using RTT.
My current problem is that I don't know exactly how I can make it work with the buttons. Currently I start scanning for BLE peripheral devices near the end of main() before I run into that infinite loop. This way button 2 and 3 work (but get errors because my peer has a custom encryption key) and button 4 doesn't work (it doesn't even show my NRF_LOG_INFO("...") commands on RTT when I press button 4 right after the BLE connection has been established).
my event handler:
void bsp_event_handler(bsp_event_t event)
{
ret_code_t err_code;
switch (event)
{
/*
case BSP_EVENT_KEY_0:
{
NRF_LOG_INFO("Button 1 pressed.");
// Start execution.
NRF_LOG_INFO("SDCS client started.");
scanning_start(&erase_bonds);
// Handle any pending log operation(s), then sleep until the next event occurs.
for (;;)
{
idle_state_handle();
}
break;
}
*/
case BSP_EVENT_KEY_1:
{
NRF_LOG_INFO("Button 2 pressed.");
p_sdcs_auth->value = auth_value;
p_sdcs_auth = &auth_params;
p_sdcs_auth->auth_failed = false;
#ifdef TEST
sdcs_auth_challenge_test(p_sdcs_auth); // sendet eine fertige challenge
#else
sdcs_auth_challenge(p_sdcs_auth); // Funktion für Echtfall enthält ebenfalls Test-Funktionalität die aktiviert werden kann
#endif
ble_gattc_write_params_t const p_write_params =
{
.write_op = BLE_GATT_OP_WRITE_REQ, // type: uint8_t , description: GATT write operations: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.s140.api.v7.2.0%2Fgroup___b_l_e___g_a_t_t___w_r_i_t_e___o_p_s.html
.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE, // type: uint8_t , description: Execute prepared write.
.handle = 0x0D, // uint16_t , description: Handle to the attribute to be written.
.offset = 0, // uint16_t, description: Offset in Bytes. For WRITE_CMD and WRITE_REQ, offset must be 0.
.len = p_sdcs_auth->len , // uint16_t, description: Length of Data in Bytes, Data Pipe: Length 19 but 20 Bytes
//.p_value = &value, // type: uint8_t const * , description: Pointer to the value data.
.p_value = p_sdcs_auth->value,
};
NRF_LOG_INFO("gattc_write_pipe(): authentication challenge");
gattc_write_pipe(p_write_params);
break;
}
case BSP_EVENT_KEY_2:
{
NRF_LOG_INFO("Button 3 pressed.");
p_sdcs_auth->value = auth_value;
p_sdcs_auth = &auth_params;
sdcs_remote_access_timed_open_door(p_sdcs_auth);
ble_gattc_write_params_t const p_write_params =
{
.write_op = BLE_GATT_OP_WRITE_REQ, // type: uint8_t , description: GATT write operations: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.s140.api.v7.2.0%2Fgroup___b_l_e___g_a_t_t___w_r_i_t_e___o_p_s.html
.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE, // type: uint8_t , description: Execute prepared write.
.handle = 0x0D, // uint16_t , description: Handle to the attribute to be written.
.offset = 0, // uint16_t, description: Offset in Bytes. For WRITE_CMD and WRITE_REQ, offset must be 0.
.len = p_sdcs_auth->len , // uint16_t, description: Length of Data in Bytes, Data Pipe: Length 19 but 20 Bytes
//.p_value = &value, // type: uint8_t const * , description: Pointer to the value data.
.p_value = p_sdcs_auth->value,
};
NRF_LOG_INFO("gattc_write_pipe(): sdcs release cylinder for release time (0xE1)");
gattc_write_pipe(p_write_params);
break;
}
case BSP_EVENT_KEY_3:
{
NRF_LOG_INFO("Button 4 pressed.");
NRF_LOG_INFO("Please enter a new encryption_key: ");
uart_receive();
break;
}
case BSP_EVENT_SLEEP:
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
break;
case BSP_EVENT_DISCONNECT:
err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
if (err_code != NRF_ERROR_INVALID_STATE)
{
APP_ERROR_CHECK(err_code);
}
break;
case BSP_EVENT_WHITELIST_OFF:
whitelist_disable();
break;
default:
break;
}
}
Can you please give me some advice on what the problem could be and what the options are to make it work?
Idealy I would like to start scanning for BLE peripherals (with a Button 1 press) after I set the custom encryption key (with a Button 4 press and input via PuTTY). You can see I commented the button 1 event in my event handler code because even with a modified main() it didn't not work.
