This tutorial explains how to use the phone to dynamically modify the device name, the device name after reaching the device to connect to the phone, and then disconnect and then scan to see the new device name.
The tutorial is based on Uartdemo under sdk9.0, in the following directory Xxx\keil_v5\arm\pack\nordicsemiconductor\nrf_examples\9.0.0\ble_peripheral\ble_app_ Uart
The Nordic protocol stack implementation will have a Generic access service and Generic attribute service by default (some BLE apps may not show the name, only the UUID of the two services, 0x1800 and 0x1801, respectively).
That is, even if no service is defined in a project, the two services can be seen on the phone connection after burning to the board.
We dynamically modify the name of the device to take advantage of the first service generic Access.
The service is a common attribute specification service, and the service provides a way to determine information for the device, including the name of the device itself, the appearance characteristics, the first connection parameters and so on.
With the device name attribute, you can implement the dynamic modification of the device name that we need.
The way to do this is to access the device Name property under the service after the device is connected, and then write a new name through this property, the device side to determine whether the phone sent over to the generic access service under the device Name property of the write operation. If it is, save the name to Flash. and update the device name so that when the device restarts or disconnects, the phone will be scanned to see the new device name.
PS: Of course you can also create a service and then add a feature value to use as a modification name. Receive a new name from your phone and save the changes. However, since the default generic access service already has the device name attribute, it is used directly, no longer dedicated to creating services
Because flash-related storage is first added to flash-relevant processing (see the previous tutorial on how to use Flash in the protocol stack for Flash operations)
Adding SYS_EVT Event Handling
static void Sys_evt_dispatch (uint32_t sys_evt)
{
Pstorage_sys_event_handler (SYS_EVT);
}
Register the above distribution function in the protocol stack initialization
static void Ble_stack_init (void)
{
uint32_t Err_code;
Initialize Softdevice.
Softdevice_handler_init (nrf_clock_lfclksrc_xtal_20_ppm, NULL);
..................
..................
..................
Subscribe for BLE events.
Err_code = Softdevice_ble_evt_handler_set (Ble_evt_dispatch);
App_error_check (Err_code);
//Add SYS_EVT event handler registration. Flash needs to use
Err_code = Softdevice_sys_evt_handler_set (sys_evt_dispatch);
App_error_check (Err_code);
}
First initialize flash, and define your own flash operation after the completion of the callback function, at the top of the Main.c file to add the following code
The first byte holds the identifier that indicates whether the data in Flash is a valid name
DEVICE_NAME[0]=0XAA = Valid Name,device_name[1] Indicates the length of name
#define NAME_SIZE 32
uint8_t Device_name[name_size];
pstorage_handle_t my_name_addr; Record the flash address stored by name
The callback function after the flash operation is complete. Did not do anything useful, but register the Flash block//When you need a callback function, so here need to define
static void My_cb (pstorage_handle_t * handle,
uint8_t Op_code,
uint32_t result,
uint8_t * P_data,
uint32_t Data_len)
{
Switch (Op_code)
{
Case Pstorage_update_op_code:
if (result = = nrf_success)
{
printf ("Update End");
}
Break
}
}
Defining the Flash initialization function
void My_flash_init (void) {
uint32_t Err_code;
pstorage_module_param_t param;
Apply for a block to hold the name
Param.block_count = 1;
Param.block_size = name_size;
PARAM.CB = MY_CB;
Err_code = Pstorage_init ();
printf ("Init err_code:%d\r\n", Err_code);
Err_code = Pstorage_register (¶m, &my_name_addr);
printf ("Register err_code:%d\r\n", Err_code);
Load Flash content. The name will be determined later, and if it is valid, it will be changed by name.
Otherwise, use the default name
Err_code = Pstorage_load (Device_name, &my_name_addr, name_size, 0);
printf ("Load err_code:%d\r\n", err_code);
}
The Flash initialization function is then placed in the main function
int main (void)
{
uint32_t Err_code;
BOOL Erase_bonds;
uint8_t start_string[] = start_string;
Initialize.
App_timer_init (App_timer_prescaler, App_timer_max_timers, App_timer_op_queue_size, false);
uart_init ();
//Add flash initialization because the print needs to be placed after the Uart_init function
//Because the Gap_params_init function will determine whether to use the name in Flash or the default name
//So you need to put it before the function
my_flash_init ();
Buttons_leds_init (&erase_bonds);
Ble_stack_init ();
gap_params_init ();
Services_init ();
Advertising_init ();
Conn_params_init ();
printf ("%s\r\n", start_string);
Err_code = Ble_advertising_start (ble_adv_mode_fast);
App_error_check (Err_code);
Enter main loop.
for (;;)
{
Power_manage ();
}
}
Then modify the Gap_params_init function called in the main function. This function determines whether the Flash content loaded in the my_flash_init function is a valid name and is used instead of the default name.
static void Gap_params_init (void)
{
uint32_t Err_code;
ble_gap_conn_params_t Gap_conn_params;
ble_gap_conn_sec_mode_t Sec_mode;
Ble_gap_conn_sec_mode_set_open (&sec_mode);
Flash data is valid using the name in Flash
if (device_name[0] = = 0xaa) {
Use new names effectively
DEVICE_NAME[1] for name length
printf ("Update name\r\n");
Err_code = Sd_ble_gap_device_name_set (&sec_mode,
(const uint8_t *) device_name+2,
DEVICE_NAME[1]);
}else{
printf ("Default name\r\n");
Err_code = Sd_ble_gap_device_name_set (&sec_mode,
(Const uint8_t *) Device_name,
Strlen (device_name));
}
App_error_check (Err_code);
memset (&gap_conn_params, 0, sizeof (gap_conn_params));
Gap_conn_params.min_conn_interval = Min_conn_interval;
Gap_conn_params.max_conn_interval = Max_conn_interval;
...............
............
}
The content in Flash was added, and then the new name that was sent over the phone was processed.
Defining event handler functions
static void Name_change (ble_evt_t * p_ble_evt)
{
ble_gatts_evt_write_t * P_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
Use UUID to determine if an event is written generic the name attribute in the Access service
if ((P_evt_write->context.char_uuid.uuid = = ble_uuid_gap_characteristic_device_name) &&
(p_ble_evt->header.evt_id = = Ble_gatts_evt_write))
{
printf ("name change \ r \ n");
Device_name[0] = 0XAA;
DEVICE_NAME[1] = p_evt_write->len;
memcpy (device_name+2, P_evt_write->data, P_evt_write->len);
Pstorage_update (&my_name_addr, device_name, name_size, 0);
}
}
This event handler is then added to the event dispatch function Ble_evt_dispatch.
static void Ble_evt_dispatch (ble_evt_t * p_ble_evt)
{
Name_change (p_ble_evt);
BLE_CONN_PARAMS_ON_BLE_EVT (P_BLE_EVT);
Ble_nus_on_ble_evt (&m_nus, p_ble_evt);
ON_BLE_EVT (P_BLE_EVT);
BLE_ADVERTISING_ON_BLE_EVT (P_BLE_EVT);
BSP_BTN_BLE_ON_BLE_EVT (P_BLE_EVT);
}
To the basic realization of the mobile phone modification device name. However, when the name of the connection is changed and the scan is clicked, the name is not updated and a hardware device needs to be reset to see that the device name has changed.
If you want to disconnect and then click Scan to see the new device name, you will also need to re-initialize the broadcast data after disconnecting.
Continue to modify the event dispatch function Ble_evt_dispatch
The function should be defined below and used here, so declare
void Advertising_init (void);
static void Ble_evt_dispatch (ble_evt_t * p_ble_evt)
{
Name_change (p_ble_evt);
//Add code to initialize broadcast data after a disconnect event
if (p_ble_evt->header.evt_id = = ble_gap_evt_disconnected) {
advertising_init ();
}
BLE_CONN_PARAMS_ON_BLE_EVT (P_BLE_EVT);
Ble_nus_on_ble_evt (&m_nus, p_ble_evt);
ON_BLE_EVT (P_BLE_EVT);
BLE_ADVERTISING_ON_BLE_EVT (P_BLE_EVT);
BSP_BTN_BLE_ON_BLE_EVT (P_BLE_EVT);
}
Now compile and burn to the board, the phone connects to the Generic Access Service (some may only see the UUID 0x1800), and then click on the device name (UUID 0x2a00) property to write a new name.
Then disconnect the connection. Click the Scan button to see the new device name.