当前位置: 首页 > news >正文

第二百二十八回

文章目录

  • 1. 概念介绍
  • 2. 具体细节
    • 2.1 发现服务
    • 2.2 发现特征值
    • 2.3 发送数据
    • 2.4 接收数据
  • 3. 示例代码
  • 4. 经验总结

我们在上一章回中介绍了"连接蓝牙设备的细节"相关的内容,本章回中将介绍通过蓝牙发送数据的细节.闲话休提,让我们一起Talk Flutter吧。

1. 概念介绍

我们在本章回中介绍的通过蓝牙设备发送数据仍然使用flutter_blue_plus包提供的接口,我们在第一百一十九回章回中介过通过蓝牙发送数据的方法,不过还有一些
细节问题需要注意,本章回中将详细介绍通过蓝牙发送数据的细节内容。

2. 具体细节

通过蓝牙发送数据的细节主要包含发现服务(BluetoothService)和特征值(Characteristic),发送数据和接收数据。我们把这些内容分成各个小节来介绍。

2.1 发现服务

发现服务使用包中的discoverServices()方法就可以,不过蓝牙设备的服务比较多,需要进行遍历操作,在遍历过程中找到需要操作的服务,通常是通过服务的uuid
来判断服务是否是我们需要操作的某个服务。此外,蓝牙设备的服务具有读写特性,也可以依据读写特性来区分服务。

2.2 发现特征值

发现特征值不需要专门的方法,通过服务的characteristics属性就可以获取到该服务的特征值,该属性是一个列表,包含服务中的多个特征值。我们需要对特征值列表
进行遍历操作,在遍历过程中找到需要操作的特征值,通常是通过特征值的uuid来判断特征值是否是我们需要操作的某个特征值。此外,蓝牙设备的特征值类似服务,也
具有读写特性,也可以依据读写特性来区分不同的特征值。

2.3 发送数据

发送数据有两种方法:读特征值或者写特征值,读取特征值只能从蓝牙设备中读取内容,写特征值可以向蓝牙设备发送特定的内容,蓝牙设备收到具体的内容后可以做出专
门的响应,这种方法在实际项目中比较常用。包中提供了读特征值和写特征值的方法:read()和write()。注意这两个方法是特征值的方法,不是蓝牙设备的方法,在使
用这两个方法前需要判断特征值是否具有读或者写的特性,不具有读写特性的特征值无法调用这两种方法。

2.4 接收数据

接收数据通过Stream来实现,包中提供了名叫onValueReceived的Stream,监听该Stream可以获取到蓝牙设备回复的数据。此外,新版本的包中还提供了event,
里面包含FlutterBluePlus.events.onCharacteristicReceived和FlutterBluePlus.events.onCharacteristicWritten,它们都是Stream,监听
这两个Stream也可以收到蓝牙设备回复的数据。有看官说这些内容比较抽象,我们在后面的小节中将通过具体的示例代码来演示接收数据的方法。此外,还有一点需要特
别注意:监听Stream前一定激活监听,调用特征值的notifysetNotifyValue(true/false)方法就可以激活或者关闭监听。

3. 示例代码

上面小节中介绍的实现方法比较抽象,接下来我们通过具体的代码来演示如何给蓝牙设备读写数据;

  Future<List<BluetoothService>> discoverServices(BluetoothDevice device) async {///获取服务List<BluetoothService> services = await device.discoverServices();List<BluetoothCharacteristic> characteristics;Stream<List<int>> readValueChanged;Stream<List<int>> writeValueChanged;///查找具有读写特性的特征值同时监听Strem来获取蓝牙设备返回的数值for (var element in services) {// log.i("service: ${element.toString()}");characteristics = element.characteristics;for(var char in characteristics) {if(char.properties.read) {///激活监听char.setNotifyValue(true);readValueChanged = char.onValueReceived;readValueChanged.listen((event) {log.i('read chara feedback: ${event.toHes()}');});readCharacteristics(char);}if(char.properties.write) {///激活监听char.setNotifyValue(true);writeValueChanged = char.onValueReceived;writeValueChanged.listen((event) {log.i('write chara feedback: ${event.toHex()}');},onError:(e){log.i('write chara error: ${e.toString()}');},onDone: () => log.i('write chara done'),);writeCharacteristics(char);}}}return services;}///依据指定的UUID读取特征值void readCharacteristics (BluetoothCharacteristic characteristic) async{if(PrivateKey.searchServiceUuid != characteristic.characteristicUuid.toString()) {return null;}List<int> value =  await characteristic.read();log.w('read characteristic:  ${value.toString()}');}///依据指定的UUID写入特征值void writeCharacteristics (BluetoothCharacteristic characteristic) async{if(PrivateKey.writeCharacteristicUuid != characteristic.characteristicUuid.toString()) {return null;}List<int> value = [12,13,14];await characteristic.write(value,withoutResponse: false);log.w('write characteristic:  ${value.toString()}');}

上面的代码中把读写特征值的操作封装成了独立的方法,这样方便调用。我们可以依据特征值的读写属性来区分特征值,也可以依据特征值的uuid来区分特征值,不过需
要与蓝牙设备的开发工程师获取特征值的uuid.发起读写操作后,可以在Stream中的Listen()方法中获取到蓝牙设备返回的数据。我们在代码的关键位置都添加了注释,
这样方便大家理解代码。注意:读写操作需要进行异常操作,不然无法接收到数据。

4. 经验总结

最后,我们对本章回的内容做一个全面的总结:

  • Service,Characteristic和Descriptor都是蓝牙设备的属性,而且每个蓝牙都有这些属性;
  • Service,Characteristic和Descriptor环环相扣:获取到Service后才能获取Characteristic,获取到Characteristic后才能获取Descriptor;
  • 一个蓝牙设备可能会有多个service,我们可以通过它的uuid来区分不同的service;
  • 一个serice可能会有多个characteristic,我们可以通过它的uuid来区分不同的characteristic;
  • 一个characteristic可以具备读写属性中的任意一种,或者二种属性都具备;
  • Service和Characteristic都具有读写属性,可以通过读写特征来区分,或者通过uuid来区分;
  • 读写数据前需要激活特征值的监听功能,读写操作完成后,可以通过特征值的Stream接收蓝牙设备回复的数据;
  • 读写数据的操作需要通过异步方法来实现,否则无法接收到蓝牙设备回复的数据;
    看官们,与"通过蓝牙发送数据的细节"相关的内容就介绍到这里,欢迎大家在评论区交流与讨论!

相关文章:

  • Text2SQL学习整理(五)将Text-to-SQL任务与基本语言模型结合
  • word2003 open word2007+
  • 【开源】基于JAVA语言的企业项目合同信息系统
  • 181.【2023年华为OD机试真题(C卷)】查找接口成功率最优时间段(深度优先搜索(DFS)实现JavaPythonC++JS)
  • 利用Milvus Cloud和LangChain构建机器人:一种引人入胜且通俗易懂的方法
  • 在x64上构建智能家居(home assistant) (六) 安装Node-RED Companion Integration
  • 显示器屏幕oled的性能、使用场景、维护
  • 支付平台在选择服务器租用时要注意什么?
  • Twincat中PLC的ST语言编程实现机器人安全交互
  • mysql参数配置binlog
  • 二维码智慧门牌管理系统:提升社区管理智能化水平
  • web前端项目-七彩夜空烟花【附源码】
  • FB混合C语言编译
  • 图片转excel:“保留数字格式”在什么场景下该勾
  • 怎么卸载macOS上的爱思助手如何卸载macOS上的logitech g hub,如何卸载顽固macOS应用
  • 4. 路由到控制器 - Laravel从零开始教程
  • cookie和session
  • ES6系列(二)变量的解构赋值
  • input实现文字超出省略号功能
  • Linux gpio口使用方法
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • php ci框架整合银盛支付
  • Protobuf3语言指南
  • React-生命周期杂记
  • SpringCloud集成分布式事务LCN (一)
  • 阿里云应用高可用服务公测发布
  • 初识MongoDB分片
  • 动态魔术使用DBMS_SQL
  • 基于Android乐音识别(2)
  • 使用Gradle第一次构建Java程序
  • ​Spring Boot 分片上传文件
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • $.ajax,axios,fetch三种ajax请求的区别
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (力扣)1314.矩阵区域和
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (四)Controller接口控制器详解(三)
  • (一)UDP基本编程步骤
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)memcache、redis缓存
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • (转)原始图像数据和PDF中的图像数据
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET 中的轻量级线程安全
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)