有些应用场景,最终客户(用户)希望可以在手机APP上修改BLE设备的设备名称。实现这个功能的方法如下:
- 修改“Device Name”特性的设置,把“Variable length”选项勾上,如下图:
- 添加新的服务“New Name”,设置保持默认设置即可。
- 在新的服务下添加新的特性“New Name”,设置如下:
- 保存GATT配置,并点“Generate”生成代码。
- 在app.c中的appMain函数中添加如下代码:
case gecko_evt_gatt_server_user_read_request_id:
if (evt->data.evt_gatt_server_user_write_request.characteristic == gattdb_new_name) {
read_rsp = gecko_cmd_gatt_server_read_attribute_value(gattdb_device_name, 0);
gecko_cmd_gatt_server_send_user_read_response(
evt->data.evt_gatt_server_user_read_request.connection,
gattdb_new_name,
read_rsp->result, read_rsp->value.len, read_rsp->value.data);
}
break;
case gecko_evt_gatt_server_user_write_request_id:
if (evt->data.evt_gatt_server_user_write_request.characteristic == gattdb_new_name) {
gecko_cmd_gatt_server_send_user_write_response(
evt->data.evt_gatt_server_user_write_request.connection,
gattdb_new_name,
bg_err_success);
gecko_cmd_gatt_server_write_attribute_value(gattdb_device_name, 0,
evt->data.evt_gatt_server_user_write_request.value.len,
evt->data.evt_gatt_server_user_write_request.value.data);
}
再接下来,为了让新的设备名在设备复位后不会丢失,需要把它写入到flash的User data区域,如下图。
先看上图中的NVM3在程序里是如何定义的:
在efr32mg22c224f512im40.ld文件里定义了“.simee”的section:
.nvm_dummy (DSECT):
{
KEEP(*(.simee));
} > FLASH
/* Set NVM to end of FLASH*/
__nvm3Base = 0x00080000-8192- SIZEOF(.nvm_dummy);
ASSERT((__etext + SIZEOF(.text_application_data)) <= __nvm3Base, "FLASH memory overlapped with NVM section.")
在工程属性的设置中定义了“NVM3_DEFAULT_NVM_SIZE”的宏:
在nvm3_default.c文件里定义了“nvm3Storage”变量:
#ifndef __NVM3__
#define __NVM3__ ".simee"
#endif
__attribute__((used)) uint8_t nvm3Storage[NVM3_DEFAULT_NVM_SIZE] __attribute__ ((section(__NVM3__)));
/* If linker does not provide __nvm3Base symbol, then use nvm3Storage*/
extern char __nvm3Base __attribute__((alias("nvm3Storage")));
#define NVM3_BASE (&__nvm3Base)
因此,在app.c文件里定义userData、deviceName和相关函数如下:
extern uint8_t nvm3Storage[NVM3_DEFAULT_NVM_SIZE];
uint32_t* const flashUserDataBase = (uint32_t*)(nvm3Storage + NVM3_DEFAULT_NVM_SIZE);
#define DEVICE_NAME_MAX_LEN 31
typedef struct {
uint8_t len;
uint8_t data[DEVICE_NAME_MAX_LEN];
}TypeDeviceName;
typedef struct {
TypeDeviceName deviceName;
}TypeUserData;
TypeUserData userData;
void ReadUserDataFromFlash(void)
{
memcpy(&userData, flashUserDataBase, sizeof(TypeUserData));
}
void SaveUserDataToFlash(void)
{
MSC_ErasePage(flashUserDataBase);
MSC_WriteWord(flashUserDataBase, &userData, sizeof(TypeUserData));
}
void SaveDeviceNameToFlash(TypeDeviceName* name)
{
memcpy(&userData.deviceName, name, sizeof(TypeDeviceName));
SaveUserDataToFlash();
}
void ReadDeviceNameFromFlash(TypeDeviceName* name)
{
memcpy(name, &((TypeUserData*)flashUserDataBase)->deviceName, sizeof(TypeDeviceName));
}
然后在appMain函数里添加如下代码:
……
struct gecko_msg_gatt_server_read_attribute_value_rsp_t* read_rsp;
TypeDeviceName* device_name;
……
case gecko_evt_system_boot_id:
bootMessage(&(evt->data.evt_system_boot));
ReadUserDataFromFlash();
if(userData.deviceName.len != 0xFF)
{
gecko_cmd_gatt_server_write_attribute_value(gattdb_device_name, 0,
userData.deviceName.len,
userData.deviceName.data);
}
read_rsp = gecko_cmd_gatt_server_read_attribute_value(gattdb_device_name, 0);
printLog("device name: %s \n", read_rsp->value.data);
……
case gecko_evt_gatt_server_user_write_request_id:
if (evt->data.evt_gatt_server_user_write_request.characteristic == gattdb_new_name) {
gecko_cmd_gatt_server_send_user_write_response(
evt->data.evt_gatt_server_user_write_request.connection,
gattdb_new_name,
bg_err_success);
device_name = (TypeDeviceName*)&(evt->data.evt_gatt_server_user_write_request.value);
gecko_cmd_gatt_server_write_attribute_value(gattdb_device_name, 0,
device_name->len,
device_name->data);
SaveDeviceNameToFlash(device_name);
printLog("write new device name, len=%d, data=%s \n", device_name->len, device_name->data);
}
打完收工。