ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Charge充电宝项目通信流程分析

Charge充电宝项目通信流程分析 蓝牙板块的目录结构device_manager.dart 设备管理 scan_device.dart 扫描设备 scan_item.dart 扫描结果模型/条目 ble_device.dart 蓝牙设备封装连接设备 ble_message.dart 蓝牙消息 charge_command.dart 充电设备命令 cmd_type.dart 命令类型 charge.dart 充电业务模型/入口具体通信 或者再详细一点解释 bluetooth/scan_device.dart怎么扫描设备 bluetooth/scan_item.dart扫描出来的数据长什么样 bluetooth/ble_device.dart设备对象怎么封装 bluetooth/device_manager.dart连接、断开、管理设备 bluetooth/charge_command.dartApp 给设备发什么命令 bluetooth/ble_message.dart设备返回的数据怎么解析 bluetooth/cmd_type.dart有哪些命令类型1.名词解释 Service一组蓝牙功能 Characteristic真正读写数据的位置 WriteApp 写数据给设备 Notify设备主动推数据给 App MTU一次 BLE 数据包能承载的最大长度 2.项目中使用到的UUID Service UUID: ff20 TX Characteristic: ff21App 写命令给设备 RX Characteristic: ff22设备返回数据给 App 3.蓝牙 connected 只代表连接建立了不代表可以通信。必须继续 discoverServices() 找到 ff20/ff21/ff22并给 rx 开启 notify通信链路才算真正准备好。蓝牙板块中各类的主要方法扫描设备的流程1.判断蓝牙状态和权限还有定位权限 //await Permission.bluetoothConnect.request().then((value) {}); //await Permission.bluetoothScan.request().then((value) {}); //await Permission.locationWhenInUse.request().then((value) {}); 2.ScanPage.startScan() UI层面的扫描方法调用 DeviceManager.scanDevice() //DeviceManager.instance.scanDevice(); 3.DeviceManager.scanDevice() 设备管理层面的扫描方法调用ScanDevice.scan() //_scanner.scan(callback: (Charge result){ 4.ScanDevice.scan() 调用本类的_startScan()方法这是真正的扫描方法 //调用 flutter_blue_plus 的底层扫描方法 //FlutterBluePlus.startScan( // oneByOne: true, //逐个处理设备 // timeout: const Duration(seconds: 300)).then((value) { //// _startScan(); 这个不进行注释就是无限扫描 //}); 5.ScanDevice.scan() 这个方法里面设置了监听扫描结果的代码这里会拿到扫描的结果ScanResult 通过本类的方法isValid()封装成ScanItem类然后过滤出想要的设备 再回到scan()方法里面封装成Charge设备通过回调函数回调回去 //final item isValid(result); //过滤有效设备 //final item ScanItem(result); //if(service.isNotEmpty service.contains(_scanService)) { // return item;// 包含目标服务接受设备 // } //late Charge device; //device Charge.from(item); //_callback?.call(device); //回调给调用者 6.ScanCallback回调给DeviceManager.setScanCallback(), ScanPage.startScan()UI页面调用DeviceManager.setScanCallback 然后把扫描到的设备都放在deviceList列表里面更新UI显示 简单来说就是 扫描流程本质是页面注册回调 - DeviceManager 调度扫描 - ScanDevice 调用 flutter_blue_plus 扫描 - ScanResult 转 ScanItem - ScanItem 转 Charge - 回调给页面显示。 ///这里的都是主要步骤详情还得去看详情代码文章末尾会附上链接图示连接设备流程1.ScanPage.onConnect() UI层面的连接方法调用Charge.connect() //device.connect( callback: (success){ 2.Charge.connect() //super.connect(callback: (success) { 调用父类的连接方法BleDevice.connect(),这里才是真正的连接方法 //device.connect(mtu: 256,license:License.free); //调用 flutter_blue_plus 的底层连接方法 3.设备连接成功后自动调用发现设备的方法discoverService(), 由于这个方法是抽象方法由子类Charge实现 //final result await discoveryService(); //连上设备发现服务才能进行通信 4.Charge.discoveryService() 这个方法发现设备的各种服务然后找到特定服务的特定特征TX和RX //final list await device.discoverServices();//服务发现 //在 ff20 服务下面继续遍历 characteristics //ff21 - 保存为 _tx用于 App 写命令给设备 //ff22 - 保存为 _rx用于设备通过 notify 返回数据给 App 5.找到特定服务的特定特征TX和RX后开启通知 BleDevice.setNotify(),然后监听rx收到的数据 //await setNotify(_rx!); //开启RX特征值的通知 //await characteristic.setNotifyValue(true); //开启通知 ///****创建新监听接受数据 // _valueState _rx?.onValueReceived.listen((event) //BLE 连接成功只代表手机和设备建立了连接不代表已经可以通信。只有 discoveryService() 找到 //正确的 Service 和 Characteristic并开启 RX notify 后App 才真正具备和设备收发数据的能力。图示协调MTU流程1.设备连接成功后自动协商MTU //device.connect(mtu: 256,license:License.free); 2.在发现设备的方法里面监听MTU的变化 // _mtuState device.mtu.listen((event) { // _command.getMtu(); //MTU变化时获取新的MTU值 //}); 3.请求Mtu这里说是请求MTU其实是读MTU因为这边设备的蓝牙芯片的MTU被固定好了 只能读取不能改变 // Futurevoid getMtu() async{ // Log.d(get Mtu()); // _getDeviceInfo(DeviceInfoType.mtu); //} // Futurebool _getDeviceInfo(int info) async { // return _write(cmd: CmdType.info, payload: [info,0]); // } //写入命令的核心方法 // Futurebool _write({ // required int cmd, //命令类型 // required Listint payload,//数据负载 // int size 0, //数据大小 // int offset 0 //偏移量 // }) async { // // //构建帧控制字节 // final frame ((size 4) 0xF0) | (offset 0x0F); // // //构建数据包 // final data [ // 0x00, /// seq - 序列号 // cmd, /// cmd - 命令码 // 0x01, /// request - 请求标志 // frame // frame - 帧控制 // ]; // // data.add(payload.length); //负载长度 // data.addAll(payload); //负载数据 // // //通过设备写入数据 // return device.writeResponse(data); // } 4.通过解析方法拿到MTU的值 //switch(payload[0]) { // case DeviceInfoType.mtu: // mtu payload.last; //取payload列表的最后一个元素 // Log.d(mtu device $mtu); // onConnected(); // command.getDeviceInfo(); //获取全部信息 // break;原理连接成功后App 希望把 BLE 的 MTU 调大到 256。 只是“请求值”最终能不能变成 256要看手机系统和设备双方协商结果。 MTU:一次 BLE 通信最多能传多少字节。BLE 默认 MTU 通常是 23 字节。 但真正能给业务数据用的不是完整 23 字节因为 ATT 协议本身还要占几个字节。 更详细的流程 1. App 调用 flutter_blue_plus 2. flutter_blue_plus 调用 Android/iOS 原生蓝牙 API 3. 手机系统蓝牙栈执行连接、MTU 请求、服务发现等 BLE 协议流程 4. 手机系统蓝牙栈通过手机蓝牙芯片和设备通信 5. 设备返回结果 6. 手机系统蓝牙栈把结果回调给插件 7. 插件再把结果变成 Dart 里的 Stream/Event App 调用 device.connect(mtu: 256) - flutter_blue_plus 收到 mtu256 - Android 上调用原生 requestMtu(256) - Android 蓝牙栈发送 BLE ATT MTU Exchange Request - 充电宝返回 ATT MTU Exchange Response - Android 蓝牙栈得到最终 MTU - flutter_blue_plus 收到 MTU changed 事件 - Dart 层 device.mtu.listen(event) 被触发通信流程前提 1.连接的时候协调MTU //device.connect(mtu: 256,license:License.free); 2.MTU变化执行getMTU方法 //_command.getMtu(); 3.通过解析方法读到设备的MTU的值然后获取设备的全部信息 //command.getDeviceInfo(); //获取全部信息 1.涉及到的类Charge-Charge类-CSDN博客Charge-DeviceManager-CSDN博客Charge-Command-CSDN博客Charge-ScanDevice-CSDN博客Charge-BleDevice-CSDN博客Charge-BleMessage-CSDN博客Charge-ScanItem-CSDN博客Charge-CmdType-CSDN博客
返回列表