蓝牙学习笔记(九)——BLE超过20字节数据包传输(MTU)

前言:在默认情况下,BLE 支持传输一次性最大不超过20字节的数据包,但是很多应用场景下,往往会需要传输更多数据。下面说下如何进行一些修改,使之能够传输更大数据。


实验环境

  • 客户端nRF Connect APP,手机应用市场均可下载,实验手机蓝牙协议版本为5.0。
  • 服务端搭载蓝牙芯片AC6920的开发板,SDK蓝牙协议栈版本为4.2。

1.server与client

  低功耗蓝牙的设备可以分成两类:一类是中央设备,用于找到并与外围设备进行交互,在常见的场景中,一般它具有丰富的功能和复杂的用户界面,比如手机。中央设备在BLE中一般扮演的角色是client
  低功耗蓝牙应用的另一类是外围设备,向中央设备提供信息和服务。在常见的场景中,它一般是搭载在各设备上的蓝牙芯片,扮演server角色。
  类似于互联网的HTTP协议一样,属性协议其本质上也是也是一种无状态协议,它不仅在连接时没有状态,在连接和连接之间也没有状态。因此,在每次信息发生变化时,都需要其中一方主动发送信息。


2.交换MTU请求

  在低功耗蓝牙连接中,属性协议默认的MTU长度为23字节。按照1个字节的类型操作码(六种基本操作:请求、响应、命令、指示、确认、通知)以及最少2个字节操作句柄(16BitsUUID)算,数据传输字节最多不超过20字节。在两个设备连接初期,谁也不知道对方底细,因此数据交换严格按照默认MTU来,即MTU为23字节。
  如果设备想要发送更大的数据包,那么它就要协商一个更长的MTU。只有客户端可以发起这种请求。客户端的请求包含客户端接收的MTU长度;服务器请求则包含服务器接受的MTU长度。对于同时是是客户端服务器的设备而言,二者提供的接收MTU长度中较小的那个即是连接将会使用的MTU长度。


2.服务端

  观察了AC6920的SDK后,发现在每次蓝牙芯片上电初始化时总是先读取一次默认MTU的值作为传输数据的标准。此后客户端若进行MTU请求,则在请求MTU大小和发送数据缓存中取二者最小更新数据,否则一直按照默认MTU发送数据。

/* -----------------定义服务端的MTU------------------*/
#define ATT_DEFAULT_MTU       23

/*--------------初始化ATT发送协议栈参数------------- 
-------------此时att_payload_size初始化为20-------- */
void att_send_init(u16 conn_handle)
{
     
    CPU_INT_DIS();
    att_conn_handle = conn_handle;
    att_ready_send_len = 0;
    att_payload_size = ATT_DEFAULT_MTU - 3;
    att_wakeup_send_flag = 0;

    att_ccc_config_init();
    semlock_set(&send_lock, FALSE);
    cbuf_init(&user_send_cbuf, user_data_buf, USER_BUF_LEN);
    CPU_INT_EN();
}

/* ----------client的MTU请求,获取MTU------------- */
static void client_search_profile_complete(void)
{
     
    u16 mtu;

    if (service_count == 0) {
     
        log_info("find no services!!!\n");
    }

    gatt_client_get_mtu(gc_handle, &mtu);
    log_info("ATT MTU = %u\n", mtu);
    att_send_set_mtu_size(mtu);

    client_puts("\n-target_handle:");
    client_put_buf((void *)&target_handle, sizeof(target_handle_t));
    set_ble_work_state(BLE_ST_SEARCH_COMPLETE);
    log_info("client_search_profile_complete\n");
}

/* --------获取client请求的MTU与默认做比较-----------
--------若不超过数据发送缓存大小,则更新MTU-------- */
void att_send_set_mtu_size(u16 mtu_size)
{
     
    if (mtu_size > sizeof(att_send_data)) {
     
        att_payload_size = sizeof(att_send_data);
    } else {
     
        att_payload_size = mtu_size;
    }
   /*  att_payload_size = ATT_DEFAULT_MTU - 3; */
    log_info("att_payload_size= %d \n", att_payload_size);
}

  • 按照上述逻辑,服务器端应该在最初维持MTU的值为默认的23字节,以确保每次初始化后能够和每个客户端正确连接。
  • 在连接成功后,接收客户端传回的交换MTU请求消息,改变MTU大小。

3.客户端

  • 客户端一开始也使用MTU为23字节的数据确保能够正确连接
  • 连接成功后,客户端发出交换请求MTU的命令,一般限制范围为23~517字节。

  在nRF Connect APP中,找到下图按钮点击,修改MTU值。
蓝牙学习笔记(九)——BLE超过20字节数据包传输(MTU)_第1张图片
蓝牙学习笔记(九)——BLE超过20字节数据包传输(MTU)_第2张图片


4.实验效果

  点击下图APP按钮查看日志,可以发现当MTU为默认23个字节时,发送超过20个字节数据会报错。同样服务端发送超过20字节数据,服务端会分批发送,将之前的数据覆盖掉,最后只显示收到的最后帧尾数据。
  当改变默认MTU后,可以发现双方能发送和接收更多的数据了。
蓝牙学习笔记(九)——BLE超过20字节数据包传输(MTU)_第3张图片

你可能感兴趣的:(蓝牙)