蓝牙BLE MTU规则与约定
1. 问题引言:
想在gatt client上(一般是手机上)传输长一点的数据给gatt server(一般是一个Bluetooth smart设备,即只有BLE功能的设备),但通过
writeCharacteristic(BluetoothGattCharacteristic)
来写的时候,发现最多只能写入20个byte的数据。
这篇文章会回答下面几个问题:
1)为什么会是20?
2)如何突破20?
3)如何更优雅的来实现?
2. 为什么为限制成20个字节?
core spec里面定义了ATT的默认MTU为23个bytes, 除去ATT的opcode一个字节以及ATT的handle 2个字节之后,剩下的20个字节便是留给GATT的了。
考虑到有些Bluetooth smart设备功能弱小,不敢太奢侈的使用内存空间,因此core spec规定每一个设备都必须支持MTU为23。
在两个设备连接初期,大家都像新交的朋友一样,不知对方底细,因此严格的按照套路来走,即最多一次发20个字节,是最保险的。
由于ATT的最大长度为512byte,因此一般认为MTU的最大长度为512个byte就够了,再大也没什么意义,你不可能发一个超过512的ATT的数据。所以ATT的MTU的最大长度可视为512个bytes。
3. 如何突破20?
很简单嘛,改变传输的ATT的MTU就行了,大家经过友好的协商,得到双方都想要的结果,是最好的。在Android上(API 21),改变ATT MTU的接口为:
public boolean requestMtu (int mtu)
Added in API level 21
Request an MTU size used for a given connection.
When performing a write request operation (write without response), the data sent is truncated to the MTU size. This function may be used to request a larger MTU size to be able to send more data at once.
A onMtuChanged(BluetoothGatt, int, int) callback will indicate whether this operation was successful.
Requires BLUETOOTH permission.
Returns
true, if the new MTU value has been requested successfully
大声的说出来你想要一下子传多少,调用上面的接口就可以了,然后在下面的函数中看最终结果(当然了,如果你的peripheral申请改变MTU并且成功的话,那这个回调也会被调用):
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
this.supportedMTU = mtu;//local var to record MTU size
}
}
之后你就可以快乐的发送supported MTU-3的长度的数据了。
4. 如何优雅的来实现?
万一对方设备不同意你的请求怎么办?
对于app来说,一般是知道自己要最大发送多少数据的,例如一次要发100个bytes,那么就首先试试申请一下103,失败的话,则申请一下53,即二分法,剩下的只能自己分段拆着发了。
一般来讲,app的开发者和对端设备的开发者都是同一伙儿人,这是好事,他们可以根据自己设备的硬件情况,来商量MTU应该是多少。
蓝牙BLE MTU规则与约定的更多相关文章
- 低功耗蓝牙BLE外围模式(peripheral)-使用BLE作为服务端
低功耗蓝牙BLE外围模式(peripheral)-使用BLE作为服务端 Android对外模模式(peripheral)的支持 从Android5.0开始才支持 关键术语和概念 以下是关键BLE术语和 ...
- 深入浅出低功耗蓝牙(BLE)协议栈
深入浅出低功耗蓝牙(BLE)协议栈 BLE协议栈为什么要分层?怎么理解蓝牙"连接"?如果蓝牙协议只有ATT没有GATT会发生什么? 协议栈框架 一般而言,我们把某个协议的实现代码称 ...
- 蓝牙ble数据转语音实现Android AudioRecord方法推荐
蓝牙ble数据转语音实现Android AudioRecord方法推荐 教程 欢迎走进zozo的学习之旅. 概述 蓝牙BLE又称bluetooth smart,主打的是低功耗和快速链接,所以在支持的 ...
- Android-低功耗蓝牙(BLE)-客户端(主机/中心设备)和服务端(从机/外围设备)
一.Android 低功耗蓝牙(BLE)的API简介 从Android 4.3(API 18)才支持低功耗蓝牙(Bluetooth Low Energy, BLE)的核心功能, BLE蓝牙协议是GAT ...
- 蓝牙BLE: ATT协议层中属性(Attribute)
ATT(Attribute Protocol)属性层是GATT和GAP的基础,它定义了BLE协议栈上层的数据结构和组织方式. 属性(Attribute)概念是ATT层的核心,ATT层定义了属性的内容, ...
- 蓝牙 BLE 协议学习: 001-BLE协议栈整体架构
背景 在深入BLE协议帧之前,我们先看一下BLE协议栈整体架构. 转载自:<深入浅出低功耗蓝牙(BLE)协议栈> 架构 如上图所述,要实现一个BLE应用,首先需要一个支持BLE射频的芯片, ...
- 蓝牙BLE传输性能及延迟分析
BLE传输性能主要受以下几个因素影响:操作类型,Connection Interval,每个Connection Event内发送的帧数.每一帧数据的长度.具体参见如下链接: https://devz ...
- 蓝牙BLE实用教程
蓝牙BLE实用教程 Bluetooth BLE 欢迎使用 小书匠(xiaoshujiang)编辑器,您可以通过 设置 里的修改模板来改变新建文章的内容. 1.蓝牙BLE常见问答 Q: Smart Re ...
- 微信蓝牙BLE接入调试指引 硬件篇
1 平台框架简介 微信蓝牙BLE由三个模块组成,分别是蓝牙设备.微信和第三方服务器,如下图: 蓝牙设备与微信之间的通信是通过蓝牙GATT协议进行. 微信与第三方服器之间的通信是通过网络http 接口进 ...
随机推荐
- Android Studio导入Fresco
大概一周之前,Facebook开源了专为Android系统定制的图片下载缓存工具,当天该消息就上了各大技术论坛网站的头条,也成为了各个技术群里讨论的最主要的话题.也就在当天stay4it的QQ群里面就 ...
- node相关--测试
测试: assert模块; //node自带 var assert = require('assert'); var now = Date.now(); console.log(now); asser ...
- Xamarin.Android提示aapt退出,代码为255
Xamarin.Android提示aapt退出,代码为255 错误信息:”aapt.exe”已退出,代码为255.出现这种问题,通常是由于该项目所使用Android SDK不完整.通过SDK Mana ...
- css构造块级元素
css 1. 宽高width:数值;height:数值;也可用百分比!长高的设置不会被后代继承2. 背景(1)背景颜色background-color:颜色值;元素的背景颜色默认为transparen ...
- POJ2817 WordStack(状压DP)
题目给几个字符串,可以给它们添加前导空格,然后排列,计算每一个字符串和前一个字符串相同非空格字符相等的个数,求可能的最大个数. 状态DP: d[S][i][j]表示已经用的字符串集合S且排列的最后一个 ...
- Beat the Spread![HDU1194]
Beat the Spread! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- HttpClient_HttpClient 对 cookie的处理
session的保持是通过cookie来维持的,所以如果用户有勾选X天内免登录,这个session 就X天内一直有效,就是通过这个cookie来维护.如果没选X天内免登录,基本上就本次才能保持sess ...
- 让VIEWSTATE从页面中完全消失(小技巧)
VIEWSTATE是个好东西,是asp.net的一大创举,给web开发带来了极大的便利,然后这种便利是一种双刃剑,尤其是在前台页面,大多数前台页面都是用来展示列表数据,和用户交互的地方现在大都采用 ...
- php 实现qq第三方登录
学习之前,请大家先看一下oAuth协议. 首先呢,我们进入QQ互联的官方网站 http://connect.qq.com登入我们自己的QQ号,没有QQ号的小伙伴可以忽略本篇博文分享!
- yum安装 lnmp
yum nginx是不行的 so,制作一个repo vi /etc/yum.repos.d/nginx.repo 写上 CentOS: [nginx] name=nginx repo baseurl= ...