该教程讲解如何实现用手机来动态修改设备名,达到手机连接设备后修改设备名称,然后断开连接再扫描能够看到新的设备名。

教程基于sdk9.0 下的uartdemo,如下目录中xxx\Keil_v5\ARM\Pack\NordicSemiconductor\nRF_Examples\9.0.0\ble_peripheral\ble_app_uart

Nordic的协议栈实现中默认都会有一个 Generic Access服务和Generic Attribute服务(有的BLE app可能显示不了名字,只显示这两个服务的UUID,分别是0x1800和0x1801)。

即一个工程中即使没有定义任何服务,烧写到板子上后,手机连接上也能看到这两个服务。

我们动态修改设备名就是利用了第一个服务Generic Access。

该服务为通用属性规范服务,改服务为设备提供了一种确定信息的方式,包括设备自身的名称,外观特性,首先连接参数等。

使用其中的 设备名属性,就能实现我们需要的动态修改设备名。

实现方式就是  手机连接上设备后访问这个服务下的设备名属性,然后通过这个属性写新的名字,设备这边判断手机发送过来的写是不是对Generic Access服务下的 设备名 属性的写操作。如果是就保存名字到flash中。并且更新设备名,这样当设备重启或者断开连接后 手机这边再扫描就能看到新的设备名字了。

PS:当然你也可以专门建立一个服务然后添加一个特征值用来当做修改名字用。接收手机发送过来的新名字然后存储修改。 不过既然默认存在的Generic Access服务中已经有了设备名属性,这里就直接用,不再去专门创建服务

因为涉及到flash的存储首先 添加flash相关的处理(关于flash的操作看前面的教程 如何在协议栈中使用flash)

//添加 sys_evt事件处理

static void sys_evt_dispatch(uint32_t sys_evt)

{

pstorage_sys_event_handler(sys_evt);

}

//协议栈初始化中注册上面的派发函数

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);

   //添加 sys_evt事件处理函数 注册。 flash需要用到

   err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);

APP_ERROR_CHECK(err_code);

}

首先初始化flash,并且定义自己的flash操作完成后的回调函数,在main.c文件的最上面添加如下代码

//第一个字节存放的是标识符表示 flash中的数据是否是有效的 name

//device_name[0]=0xAA 表示是有效name,device_name[1]表示name的长度

#define NAME_SIZE 32

uint8_t device_name[NAME_SIZE];

pstorage_handle_t my_name_addr; //记录name存放的flash地址

//flash操作完成后的回调函数。 并没有做什么有用的事,但是注册flash块//的时候需要有回调函数所以这里需要定义

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;

}

}

//定义flash初始化函数

void my_flash_init(void){

uint32_t err_code;

pstorage_module_param_t param;

//申请一个块 用来存放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(&param, &my_name_addr);

printf("register err_code:%d\r\n",err_code);

//加载flash内容。后面会判断name是否有效,如果有效就会用改name

//否则使用默认name

err_code = pstorage_load(device_name, &my_name_addr, NAME_SIZE, 0);

printf("load err_code:%d\r\n",err_code);

}

然后将该flash初始化函数放到main函数中

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();

   //添加flash初始化,因为用到了打印需要放到uart_init函数之后

   //因为gap_params_init函数中会判断使用flash中的名字还是默认名字

   //所以需要放到该函数之前

   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();

}

}

然后修改 main函数中调用的gap_params_init函数。该函数中判断my_flash_init 函数中加载的flash内容是否是有效name,是就使用,不是就用默认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数据有效则使用flash中的名字

if ( device_name[0] == 0xaa ){

//有效 使用新名字

//device_name[1]为名字长度

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;

……………

…………

}

关于flash中的内容添加完了,然后是处理手机发送过来的新名字。

定义事件处理函数

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;

//通过UUID来判断事件是不是写Generic Access服务中的名字属性

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 );

}

}

然后再将这个事件处理函数加到 事件派发函数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);

}

到这里基本实现了 手机修改设备名字。不过连接上修改名字后断开然后点击扫描发现名字并未更新,需要复位一下硬件设备才能看到设备名字变了。

想在不复位的情况下,断开连接然后点扫描就能看到新的设备名还需要在断开连接后重新初始化 广播数据。

继续修改事件派发函数ble_evt_dispatch

//应为该函数是在下面定义的,这里使用到,所以要声明一下

void advertising_init(void);

static void ble_evt_dispatch(ble_evt_t * p_ble_evt)

{

name_change(p_ble_evt);

//添加代码,在断开连接事件后初始化广播数据

   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);

}

现在编译后烧写到板子,手机连接后进入 Generic Access服务(有的可能只看到UUID 0x1800),然后点击device name(UUID 0x2A00)属性,写新名字。

然后断开连接。 点击扫描按键就可以看到新的设备名字了

BLE-NRF51822教程11-手机动态修改设备名相关推荐

  1. 荣耀手机动态修改电池数据

    较早前文章介绍了怎么样在安卓手机上安装激活xposed框架,xposed框架的牛逼之处功能大伙都介绍过,可以不修改Apk的前提下,修改系统底层的参数,打个比方在某些应用情景,大伙需要修改手机的某个系统 ...

  2. 小米手机动态修改网络类型信息

    前面文章介绍了怎么在安卓手机上安装激活XPOSED框架,XPOSED框架的极强的功能大伙都清楚,能够不修改APK的前提下,修改系统内部的参数,好比在某些应用需要,大伙需要修改手机的某个系统参数,这情况 ...

  3. 华为手机动态修改androidid信息

    较早前文章介绍了怎么在安卓手机上安装激活Xposed框架,Xposed框架的极强的功能大伙都知道,能够不修改APK的前提下,修改系统底层的参数,打比方在某些应用场景,大伙需要修改手机的某个系统参数,这 ...

  4. 小米手机动态修改imei信息

    前面文章介绍了如何在安卓手机上安装激活xposed框架,xposed框架的牛逼之处功能大家都清楚,能够不修改apk的前提下,修改系统内核的参数,打比方在某些应用领域,大家需要修改手机的某个系统参数,这 ...

  5. 魅族手机动态修改系统版本参数

    之前文章介绍了怎么样在安卓手机上安装激活XPOSED框架,XPOSED框架的强大功能各位都介绍过,能够不修改apk的前提下,修改系统底层的参数,好比在某些应用需要,各位需要修改手机的某个系统参数,这时 ...

  6. NRF51822蓝牙服务(9)——动态修改设备的名称

    前言 很多时候我们希望能够通过手机动态修改设备的MAC地址.配对密码或者蓝牙设备信息等,其实原理上都是可以实现的.大概思路其实就是把我们需要修改的内容发送到FLASH中保存,然后再用FLASH中的内容 ...

  7. 【教程】nrf51822实例代码解析及修改实例

    [教程]nrf51822实例代码解析及修改实例 http://www.eeboard.com/bbs/thread-42757-1-1.html 说在前面:此说明用于nrf51822的主从机的实例代码 ...

  8. nrf51822 --- 动态修改连接间隔

    1.目的 在蓝牙连接上的时候动态修改连接间隔,已达到功耗平衡 2.分析 在实际应用的时候,有时候需要发送数据快一点,这个时候我们可以把连接间隔改小一点,这样发送数据快,但是功耗大,当把数据发完的时候, ...

  9. SAP UI5 应用开发教程之三十六 - 使用 Chrome 开发者工具 Elements 标签动态修改 CSS 类试读版

    一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...

最新文章

  1. 黑客基础知识与防护(一)
  2. 抽屉效果----mmdrawercontroller和viewdeck
  3. ubuntu编译内核重启出现:gave up waiting for root device
  4. Dubbo的终端操作方法
  5. 【.NET Core项目实战-统一认证平台】第七章 网关篇-自定义客户端限流
  6. 微型计算机接口与技术的交通灯,微机原理及接口技术课程设计交通灯
  7. Laravel Session 遇到的坑
  8. java se 开发web程序_JDiy快速开发WEB之javaSE环境搭建-初级
  9. 快速了解Java集合框架
  10. 阿里云产品头条(2017年12月刊)
  11. 在线图片转base64工具
  12. [导入]mootools框架【三】-Array篇: 方法完全解析
  13. sqlserver2000换成mysql_MS SQL Server2000转换成MySQL
  14. mongodb 良贴
  15. API(应用程序编程接口)
  16. centos7利用libreoffice将doc文件转换为pdf
  17. 360全景倒车影像怎么看_360全景倒车影像开的时候能看到前面的状况吗
  18. 聚观早报 | 特斯拉上海工厂被曝停产;富士相机X-Pro 3已停产
  19. 前序遍历+中序遍历重建二叉树
  20. cyber physical system

热门文章

  1. 在win10企业版x64下使用curl命令
  2. Null return value from advice does not match primitive return type for: public abstract boolean
  3. IDEA_Spring Data JPA有关报错Cannot resolve table 'XXX'
  4. jsonutil java_Java实现的JSONUtil工具类与用法示例
  5. 全面解析RS232、RS485、RS422、RJ45接口的区别和各自的应用
  6. matlab 表格控件,[转载]matlab读取excel数据并显示在excel(activex控件)中
  7. Paper:《How far are we from solving the 2D 3D Face Alignment problem? 》解读与翻译
  8. TF学习——Tensorflow框架之基础概念、设计思路、常用方法之详细攻略
  9. BlockChain:《Blockchain Gate》听课笔记——区块链的共识机制—简介、理解、畅谈
  10. CV:基于Keras利用训练好的hdf5模型进行目标检测实现输出模型中的脸部表情或性别的gradcam(可视化)