FlutterApp开发蓝牙协议
FlutterApp开发蓝⽛协议
Flutter App开发蓝⽛协议
Summary
BLE低功耗蓝⽛,是我们常说的蓝⽛4.0, 该技术有极低的运⾏待机功耗,本⽂记录使⽤Flutter开发安卓App的过程,使⽤蓝⽛模块的配置和⼀些细节。
Background
公司需求⼀款⽤于欧洲的海外版离线交流充电桩APP,通过蓝⽛⽅式与交流桩连接。主要控制充电桩的启停,及查看当前充电记录等参数。⾼级功能如充电桩设置界⾯,远程固件升级、⽹络连接、⾼级配置等。
Goals
Linkcharging App
安卓版 : ⽤于操作充电桩,查看充电桩参数信息的移动端软件。可以在主流⼚家优化后的
android 平台使⽤,需要上架于 Google Play。
iOS版: ⽤于操作充电桩,查看充电桩参数信息的移动端软件。在 IOS 平台使⽤,需要上架于
APP Store
Non-Goals
To narrow the scope of what we’re working on, outline what this proposal will not accomplish.
Proposed Solution
Describe the solution to the problems outlined above. Include enough detail to allow for productive discussion and comments from readers.
流程
⼀、声明蓝⽛权限和定位权限
<!--蓝⽛权限-->
<uses-permission name="android.permission.BLUETOOTH"/><!--让应⽤启动设备发现或操纵蓝⽛设置-->
<uses-permission name="android.permission.BLUETOOTH_ADMIN"/><!-- LE Beacons位置相关权限-->
<!-- 如果设配Android9及更低版本,可以申请 ACCESS_COARSE_LOCATION -->
<uses-permission name="android.permission.ACCESS_FINE_LOCATION"/><!--ble模块设置为true表⽰只有⽀持ble的⼿机才能安装-->
<uses-feature
name="android.hardware.bluetooth_le"required="true"/>
由于蓝⽛扫描需要⽤到模糊定位权限( `Android10` 后需要精准定位权限 ),所以`android6.0`之后,除了在 `l`中申明权限之外,还需要动态申请定位权限,才可进⾏蓝⽛扫描,否则不会扫描到任何Ble设备。
⼆、中⼼设备与外围设备
Ble开发中,存在着两个⾓⾊:中⼼设备⾓⾊和外围设备⾓⾊。粗略了解下:
小视频app开发外围设备:⼀般指⾮常⼩或者低功耗设备,更强⼤的中⼼设备可以连接外围设备为中⼼设备提供数据。外设会不停的向外⼴播,让中⼼设备知道它的存在。 例如⼩⽶⼿环。
中⼼设备:可以扫描并连接多个外围设备,从外设中获取信息。
外围设备会设定⼀个⼴播间隔,每个⼴播间隔中,都会发送⾃⼰的⼴播数据。⼴播间隔越长,越省电。**⼀个没有被连接的`Ble`外设会不断发送⼴播数据* *,这时可以被多个中⼼设备发现。**⼀旦外设被连接,则会马上停⽌⼴播。**
`android 4.3` 时引⼊的`Ble`核⼼`Api`只⽀持android⼿机作为**中⼼设备⾓⾊**,当`android 5.0` 更新`Api`后,android⼿机⽀持充当作为**外设⾓⾊和中⼼⾓⾊**。即 `android 5.0` 引⼊了外设⾓⾊的`Api`,同时也更新了部分中⼼⾓⾊的`Api`。⽐如:中⼼⾓⾊中,更新了蓝⽛扫描的`Api`。
三、打开蓝⽛
安装flutter_blue 0.8.0,需要将github下载的实例中的android\app\src\main\java\com\pauldemarco\flutter_blue_example⾥的java⽂件拷过来同样位置
再配置l, 否则开启蓝⽛关闭蓝⽛的状态切换App⽆法检测到,不能够呈现出来预期的结果。
<activity
name=".EmbeddingV1Activity"
theme="@android:style/Theme.Black.NoTitleBar"
configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
hardwareAccelerated="true"
windowSoftInputMode="adjustResize">
</activity>
Android {
defaultConfig {
minSdkVersion: 19
四、扫描
1.扫描及状态获取
FlutterBlue.instance.startScan(timeout:Duration(seconds:4));
使⽤该插件, 可以直接StreamBuilder来分发数据,插件中的StreamBuilder部分代码已经实现了,可以⽤它直接在Widget上⾯使⽤。
body: StreamBuilder<BluetoothState>(
stream: FlutterBlue.instance.state,
initialData: BluetoothState.unknown,
builder:(c, snapshot){
final state = snapshot.data;
if(state == ){
return Index();
}else{
return BluetoothOffscreen(state: state);//蓝⽛未打开的呈现
}
}),
//uter.navigateTo(context,'/login', transition: TransitionType.fadeIn);
);
此处可以呈现出关闭|打开状态下两种不同的widget。扫描状态获取,并呈现不同的widget
floatingActionButton: StreamBuilder<bool>(
stream: FlutterBlue.instance.isScanning,
initialData: false,
builder:(c, snapshot){
if(snapshot.data!){
return FloatingActionButton(
child: Icon(Icons.stop),
onPressed:()=> FlutterBlue.instance.stopScan(),
backgroundColor: d,
);
}else{
return FloatingActionButton(
child: Icon(Icons.search),
onPressed:()=> FlutterBlue.instance.startScan(timeout: Duration(seconds:4)),
);
}
},
),
2.扫描结果呈现
写⼀个弹窗,⾥⾯是列表的形式呈现扫描的结果,这⾥有个注意点,Column中嵌套ListView,需要给listView嵌套⼀个container,然后设置⼀个⾼度。否则滚动会有问题。
class DeviceListDialog {
static Widget contentWidget(
BuildContext context,{
double maxWidth = double.infinity,
double maxHeight = double.infinity,
}){
return Container(
constraints: BoxConstraints(maxHeight: maxHeight, maxWidth: maxWidth),
decoration: BoxDecoration(
color: Colors.white,
boxShadow:[BoxShadow(color: Colors.black12, blurRadius:20, spreadRadius:10)], ),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children:<Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(20,10,20,10),
child: Text(
S.of(context).devicelist,
style: TextStyle(fontSize:22, fontWeight: FontWeight.bold),
),
),
Container(
height: maxHeight -66,
child: ListView(
children:[
StreamBuilder<List<ScanResult>>(
stream: FlutterBlue.instance.scanResults,
initialData:[],
builder:(c, snapshot)=> Column(
children: snapshot.data!
.map(
(r)=> ScanResultTile(
result: r,
onTap:()=> t(),
),
)
.toList(),
),
)
],
)
,
),
],
),
);
}
}
五、扫描回调
通信
⼀、蓝⽛基础协议
GAP(Generic Access Profile) 和 GATT(Generic Attribute Profile)。 GPA主要控制蓝⽛连接和⼴播。GAP使蓝⽛设备对外界可见,并决定设备是否可以或者怎样与其他设备进⾏交互。
GAP⼴播数据
GAP 中外围设备通过两种⽅式向外⼴播数据:⼴播数据 和 扫描回复( 每种数据最长可以包含 31 byte。)。
⼴播数据是必需的,因为外设必需不停的向外⼴播,让中⼼设备知道它的存在。⽽扫描回复是可选的,中⼼设备可以向外设请求扫描回复,这⾥包含⼀些设备额外的信息。
GATT(Generic Attribute Profile)
GATT配置⽂件是⼀个通⽤规范,⽤于在BLE链路上发送和接收被称为“属性”的数据块。⽬前所有的BLE应⽤都基于GATT。
BLE设备通过叫做 Service 和 Characteristic 的东西进⾏通信
GATT使⽤了 ATT(Attribute Protocol)协议,ATT 协议把 Service, Characteristic对应的数据保存在⼀个查询表中,次查表使⽤ 16 bit ID 作为每⼀项的索引。
GATT 连接是独占的。也就是⼀个 BLE 外设同时只能被⼀个中⼼设备连接。⼀旦外设被连接,它就会马上停⽌⼴播,这样它就对其他设备不可见了。当外设与中⼼设备断开,外设⼜开始⼴播,让其他中⼼设备感知该外设的存在。⽽中⼼设备可同时与多个外设进⾏连接。
⼆、Services and Characteristics
BLE GATT通信是基于嵌套的Profiles, Services andCharacteristics结构之上的,下图是其框架:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。