Bluetooth 教程

了解如何使用低功耗蓝牙

通过本节,你将学会:

  • 初始化蓝牙模块
  • 搜索周围设备
  • 连接设备
  • 获取设备服务信息
  • 获取设备特征值信息
  • 向设备写入数据
  • 读取设备数据
  • 监听设备数据变化
  • 注销蓝牙模块

使用方法

初始化蓝牙模块

为了使用蓝牙功能,你需要先初始化蓝牙模块。除了设置状态监听以外,所有的蓝牙接口都需要在初始化完成以后才能正常使用。

  1. //初始化蓝牙模块
  2. bluetooth.openAdapter({
  3. //是否打开系统蓝牙开关,默认false
  4. operateAdapter: true,
  5. success: function() {
  6. console.log('success')
  7. },
  8. fail: function(data, code) {
  9. console.log(`handling fail, code = ${code}`)
  10. if (code === 10001) {
  11. //蓝牙未打开,提示用户打开蓝牙
  12. }
  13. },
  14. complete: function() {
  15. console.log('complete')
  16. }
  17. })

搜索周围设备

你可以通过搜索操作,发现周围的低功耗蓝牙设备。在进行扫描前,你需要注册设备发现回调以及时接收搜索结果

  1. //在扫描之前先注册设备发现回调
  2. bluetooth.ondevicefound = function (data) {
  3. console.log("new device list has founded");
  4. data.devices.forEach(device => {
  5. //发现所需设备后停止扫描
  6. bluetooth.stopDevicesDiscovery();
  7. _this.deviceId = device.deviceId;
  8. console.log(`handling find new devive:${JSON.stringify(device)}`);
  9. console.log(`handling advertisData = ${_this.ab2hex(device.advertisData)}`);
  10. for (let key in device.serviceData) {
  11. console.log(
  12. `handling serviceData: uuid = ${key}, serviceData = ${_this.ab2hex(device.serviceData[key])}`
  13. );
  14. }
  15. });
  16. };
  17. //开始扫描
  18. bluetooth.startDevicesDiscovery({
  19. //指定设备uuid,支持16-bit,32-bit,128-bit uuid,不填则扫描周围所有设备
  20. services: ["1105"],
  21. //是否允许重复设备上报,如果不需要监听广播包数据,建议不设置此项,默认值为false
  22. allowDuplicatesKey: false,
  23. //上报间隔,单位毫秒,为0则立即上报,默认值为0
  24. interval: 1000,
  25. success: function () {
  26. console.log("success");
  27. }
  28. });

连接设备

在操作设备前,你需要先连接设备,连接操作可以通过deviceId直接进行,扫描并不是必要的操作。在连接前,你可以注册设备连接状态接口来监听设备断连状态

  1. //注册设备连接状态监听
  2. bluetooth.onbleconnectionstatechange = function (data) {
  3. console.log(`handling device state change: deviceId = ${data.deviceId}, connected = ${data.connected}`)
  4. //更新设备连接状态
  5. _this.connected = data.connected
  6. if (data.connected) {
  7. //目标设备连接后,获取服务列表
  8. _this.getServices()
  9. } else {
  10. //做断开连接的相关操作,比如重新连接,或者重新扫描等
  11. }
  12. }
  13. //连接设备
  14. bluetooth.createBLEConnection({
  15. deviceId: _this.deviceId,
  16. success: function () {
  17. console.log("success")
  18. },
  19. fail: function (data, code) {
  20. console.log(`handling fail, code = ${code}`)
  21. },
  22. complete: function () {
  23. console.log("complete")
  24. }
  25. })

获取设备服务信息

每个设备都会定义若干个服务,你可以从中获取需要操作的服务信息

  1. bluetooth.getBLEDeviceServices({
  2. deviceId: _this.deviceId,
  3. success: function (data) {
  4. data.services.forEach(service => {
  5. console.log(`handling device services: uuid = ${service.uuid}, isPrimary = ${service.isPrimary}`)
  6. //获取需要的服务,可以根据设备定义的uuid筛选
  7. if (service.isPrimary) {
  8. _this.serviceId = service.uuid
  9. //获取特征值列表
  10. _this.getCharacteristics()
  11. }
  12. })
  13. },
  14. fail: function (data, code) {
  15. console.log(`handling fail, code = ${code}`)
  16. },
  17. complete: function () {
  18. console.log("complete")
  19. }
  20. })

获取设备特征值信息

每个服务内会定义若干个特征值,你可以从中获取需要操作的特征值信息

  1. bluetooth.getBLEDeviceCharacteristics({
  2. deviceId: _this.deviceId,
  3. serviceId: _this.serviceId,
  4. success: function (data) {
  5. data.characteristics.forEach(characteristic => {
  6. console.log(`handling device characteristic : ${JSON.stringify(characteristic)}`)
  7. //获取需要的特征值,可以根据设备定义的uuid筛选
  8. if (characteristic.properties.write) {
  9. _this.writeCharacteristicId = characteristic.uuid
  10. } else if (characteristic.properties.read) {
  11. _this.readCharacteristicId = characteristic.uuid
  12. } else if (characteristic.properties.notify || characteristic.properties.indicate) {
  13. _this.notifyCharacteristicId = characteristic.uuid
  14. }
  15. })
  16. },
  17. fail: function (data, code) {
  18. console.log(`handling fail, code = ${code}`)
  19. },
  20. complete: function () {
  21. console.log("complete")
  22. }
  23. })

向设备写入数据

通过获取到的服务与特征值信息,可以向设备对应的特征值写入数据,需要该特征值支持 write

  1. let buffer = new ArrayBuffer(2)
  2. let dataView = new DataView(buffer)
  3. dataView.setUint8(0, 0)
  4. dataView.setUint8(1, 0xf)
  5. bluetooth.writeBLECharacteristicValue({
  6. // 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound接口中获取
  7. deviceId: _this.deviceId,
  8. // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
  9. serviceId: _this.serviceId,
  10. // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
  11. characteristicId: _this.writeCharacteristicId,
  12. // 这里的value是ArrayBuffer类型
  13. value: buffer,
  14. success: function () {
  15. console.log("success")
  16. },
  17. fail: function (data, code) {
  18. console.log(`handling fail, code = ${code}`)
  19. },
  20. complete: function () {
  21. console.log("complete")
  22. }
  23. })

读取设备数据

通过获取到的服务与特征值信息,可以读取设备对应特征值数据,需要该特征值支持 read,读取到的设备信息会通过onblecharacteristicvaluechange监听接口上报,此接口蓝牙模块通用,无需重复注册

  1. //注册特征值改变监听
  2. bluetooth.onblecharacteristicvaluechange = function (data) {
  3. console.log(`handling characteristic value change: deviceId = ${data.deviceId}, serviceId = ${data.serviceId}, characteristicId = ${data.characteristicId}, value = ${_this.ab2hex(data.value)}`)
  4. }
  5. bluetooth.readBLECharacteristicValue({
  6. // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
  7. deviceId: _this.deviceId,
  8. // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
  9. serviceId: _this.serviceId,
  10. // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
  11. characteristicId: _this.readCharacteristicId,
  12. success: function () {
  13. // 执行操作成功,读取的值会在onblecharacteristicvaluechange 接口中上报
  14. console.log("success")
  15. }
  16. })

监听设备数据变化

通过获取到的服务与特征值信息,可以开启或者关闭设备相应的特征值变化时的通知功能,需要该特征值支持 notify 或者 indicate,读取到的设备信息会通过onblecharacteristicvaluechange监听接口上报,此接口蓝牙模块通用,无需重复注册

  1. //注册特征值改变监听
  2. bluetooth.onblecharacteristicvaluechange = function (data) {
  3. console.log(`handling characteristic value change: deviceId = ${data.deviceId}, serviceId = ${data.serviceId}, characteristicId = ${data.characteristicId}, value = ${_this.ab2hex(data.value)}`)
  4. }
  5. bluetooth.notifyBLECharacteristicValueChange({
  6. // 启用 notify 功能,为true则开启通知
  7. state: enable,
  8. // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
  9. deviceId: _this.deviceId,
  10. // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
  11. serviceId: _this.serviceId,
  12. // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
  13. characteristicId: _this.notifyCharacteristicId,
  14. success: function () {
  15. // 执行操作成功,读取的值会在onblecharacteristicvaluechange 接口中上报
  16. _this.notifyEnabled = enable
  17. console.log("success")
  18. },
  19. fail: function (data, code) {
  20. console.log(`handling fail, code = ${code}`)
  21. },
  22. complete: function () {
  23. console.log("complete")
  24. }
  25. })

注销蓝牙模块

在不需要使用蓝牙时,需要注销蓝牙模块,以释放系统资源

  1. //取消不需要的状态监听
  2. bluetooth.onadapterstatechange = null
  3. bluetooth.onbleconnectionstatechange = null
  4. bluetooth.onblecharacteristicvaluechange = null
  5. bluetooth.ondevicefound = null
  6. //注销蓝牙模块
  7. bluetooth.closeAdapter({
  8. //是否关闭系统蓝牙开关,默认false,此操作会直接关闭系统蓝牙,为了不影响用户其他蓝牙设备的体验,不建议设置为true
  9. operateAdapter: false,
  10. success: function () {
  11. console.log("success");
  12. },
  13. fail: function (data, code) {
  14. console.log(`handling fail, code = ${code}`);
  15. },
  16. complete: function () {
  17. console.log("complete");
  18. }
  19. });

示例代码如下

  1. <template>
  2. <div class="doc-page">
  3. <div class="item-container">
  4. <text></text>
  5. <input type="button" class="btn" onclick="startDiscovery" value="扫描设备" />
  6. <input type="button" class="btn" onclick="createConnection" value="连接设备" />
  7. <input type="button" class="btn" onclick="closeConnection" value="断开设备" />
  8. </div>
  9. <div class="item-container" if=false>
  10. <input type="button" class="btn" onclick="write" value="写入数据" />
  11. <input type="button" class="btn" onclick="read" value="读取数据" />
  12. </div>
  13. </div>
  14. </template>
  15. <style>
  16. .doc-page {
  17. flex: 1;
  18. flex-direction: column;
  19. }
  20. .item-container {
  21. flex - direction: column;
  22. margin-bottom: 50px;
  23. margin-right: 60px;
  24. margin-left: 60px;
  25. }
  26. .text {
  27. width: 100%;
  28. margin-top: 5px;
  29. background-color: white;
  30. padding: 3px;
  31. margin-top: 1px;
  32. font-size: 28px;
  33. color: black;
  34. }
  35. .btn {
  36. height: 80px;
  37. text-align: center;
  38. border-radius: 5px;
  39. margin-right: 60px;
  40. margin-left: 60px;
  41. margin-bottom: 50px;
  42. color: #ffffff;
  43. font-size: 30px;
  44. background-color: #0faeff;
  45. line-height: 80px;
  46. }
  47. </style>
  48. <script>
  49. import bluetooth from "@system.bluetooth";
  50. export default {
  51. private: {
  52. connected: false,
  53. notifyEnabled: false,
  54. deviceId: '',
  55. readCharacteristicId: '',
  56. writeCharacteristicId: '',
  57. notifyCharacteristicId: ''
  58. },
  59. //arrayBuffer转String
  60. ab2hex(buffer) {
  61. var hexArr = Array.prototype.map.call(
  62. new Uint8Array(buffer),
  63. function (bit) {
  64. return ("00" + bit.toString(16)).slice(-2);
  65. });
  66. return hexArr.join("");
  67. },
  68. //在页面初始化时进行蓝牙模块初始化操作
  69. onInit() {
  70. let _this = this
  71. //注册蓝牙适配器监听
  72. bluetooth.onadapterstatechange = function (data) {
  73. console.log("adapterState changed, now is", data.available);
  74. };
  75. //注册设备连接状态监听
  76. bluetooth.onbleconnectionstatechange = function (data) {
  77. console.log(`handling device state change: deviceId = ${data.deviceId}, connected = ${data.connected}`)
  78. //更新设备连接状态
  79. _this.connected = data.connected
  80. if (data.connected) {
  81. //目标设备连接后,获取服务列表
  82. _this.getServices()
  83. } else {
  84. //做断开连接的相关操作,比如重新连接,或者重新扫描等
  85. }
  86. }
  87. //注册特征值改变监听
  88. bluetooth.onblecharacteristicvaluechange = function (data) {
  89. console.log(`handling characteristic value change: deviceId = ${data.deviceId}, serviceId = ${data.serviceId}, characteristicId = ${data.characteristicId}, value = ${_this.ab2hex(data.value)}`)
  90. }
  91. //初始化蓝牙模块
  92. bluetooth.openAdapter({
  93. //是否打开系统蓝牙开关,默认false
  94. operateAdapter: true,
  95. success: function () {
  96. console.log("success");
  97. },
  98. fail: function (data, code) {
  99. console.log(`handling fail, code = ${code}`);
  100. if (code === 10001) {
  101. //蓝牙未打开,提示用户打开蓝牙
  102. }
  103. },
  104. complete: function () {
  105. console.log("complete");
  106. }
  107. });
  108. },
  109. //在结束时注销蓝牙模块
  110. onDestroy() {
  111. //取消不需要的状态监听
  112. bluetooth.onadapterstatechange = null
  113. bluetooth.onbleconnectionstatechange = null
  114. bluetooth.onblecharacteristicvaluechange = null
  115. bluetooth.ondevicefound = null
  116. //注销蓝牙模块
  117. bluetooth.closeAdapter({
  118. //是否关闭系统蓝牙开关,默认false,此操作会直接关闭系统蓝牙,为了不影响用户其他蓝牙设备的体验,不建议设置为true
  119. operateAdapter: false,
  120. success: function () {
  121. console.log("success");
  122. },
  123. fail: function (data, code) {
  124. console.log(`handling fail, code = ${code}`);
  125. },
  126. complete: function () {
  127. console.log("complete");
  128. }
  129. });
  130. },
  131. startDiscovery() {
  132. let _this = this
  133. //在扫描之前先注册设备发现回调
  134. bluetooth.ondevicefound = function (data) {
  135. console.log("new device list has founded");
  136. data.devices.forEach(device => {
  137. //发现所需设备后停止扫描
  138. bluetooth.stopDevicesDiscovery();
  139. _this.deviceId = device.deviceId;
  140. console.log(`handling find new devive:${JSON.stringify(device)}`);
  141. console.log(`handling advertisData = ${_this.ab2hex(device.advertisData)}`);
  142. for (let key in device.serviceData) {
  143. console.log(
  144. `handling serviceData: uuid = ${key}, serviceData = ${_this.ab2hex(device.serviceData[key])}`
  145. );
  146. }
  147. });
  148. };
  149. //开始扫描
  150. bluetooth.startDevicesDiscovery({
  151. //指定设备uuid,支持16-bit,32-bit,128-bit uuid,不填则扫描周围所有设备
  152. services: ["1105"],
  153. //是否允许重复设备上报,如果不需要监听广播包数据,建议不设置此项,默认值为false
  154. allowDuplicatesKey: false,
  155. success: function () {
  156. console.log("success");
  157. }
  158. });
  159. },
  160. createConnection() {
  161. let _this = this
  162. //连接设备
  163. bluetooth.createBLEConnection({
  164. deviceId: _this.deviceId,
  165. success: function () {
  166. console.log("success")
  167. },
  168. fail: function (data, code) {
  169. console.log(`handling fail, code = ${code}`)
  170. },
  171. complete: function () {
  172. console.log("complete")
  173. }
  174. })
  175. },
  176. closeConnection() {
  177. let _this = this
  178. bluetooth.closeBLEConnection({
  179. deviceId: _this.deviceId,
  180. success: function () {
  181. console.log("success")
  182. },
  183. fail: function (data, code) {
  184. console.log(`handling fail, code = ${code}`)
  185. },
  186. complete: function () {
  187. console.log("complete")
  188. }
  189. })
  190. },
  191. getServices() {
  192. let _this = this
  193. bluetooth.getBLEDeviceServices({
  194. deviceId: _this.deviceId,
  195. success: function (data) {
  196. data.services.forEach(service => {
  197. console.log(`handling device services: uuid = ${service.uuid}, isPrimary = ${service.isPrimary}`)
  198. //获取需要的服务,可以根据设备定义的uuid筛选
  199. if (service.isPrimary) {
  200. _this.serviceId = service.uuid
  201. //获取特征列表
  202. _this.getCharacteristics()
  203. }
  204. })
  205. },
  206. fail: function (data, code) {
  207. console.log(`handling fail, code = ${code}`)
  208. },
  209. complete: function () {
  210. console.log("complete")
  211. }
  212. })
  213. },
  214. getCharacteristics() {
  215. let _this = this
  216. bluetooth.getBLEDeviceCharacteristics({
  217. deviceId: _this.deviceId,
  218. serviceId: _this.serviceId,
  219. success: function (data) {
  220. data.characteristics.forEach(characteristic => {
  221. console.log(`handling device characteristic : ${JSON.stringify(characteristic)}`)
  222. //获取需要的特征,可以根据设备定义的uuid筛选
  223. if (characteristic.properties.write) {
  224. _this.writeCharacteristicId = characteristic.uuid
  225. } else if (characteristic.properties.read) {
  226. _this.readCharacteristicId = characteristic.uuid
  227. } else if (characteristic.properties.notify || characteristic.properties.indicate) {
  228. _this.notifyCharacteristicId = characteristic.uuid
  229. }
  230. })
  231. },
  232. fail: function (data, code) {
  233. console.log(`handling fail, code = ${code}`)
  234. },
  235. complete: function () {
  236. console.log("complete")
  237. }
  238. })
  239. },
  240. write() {
  241. let _this = this
  242. let buffer = new ArrayBuffer(2)
  243. let dataView = new DataView(buffer)
  244. dataView.setUint8(0, 0)
  245. dataView.setUint8(1, 0xf)
  246. bluetooth.writeBLECharacteristicValue({
  247. // 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound接口中获取
  248. deviceId: _this.deviceId,
  249. // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
  250. serviceId: _this.serviceId,
  251. // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
  252. characteristicId: _this.writeCharacteristicId,
  253. // 这里的value是ArrayBuffer类型
  254. value: buffer,
  255. success: function () {
  256. console.log("success")
  257. },
  258. fail: function (data, code) {
  259. console.log(`handling fail, code = ${code}`)
  260. },
  261. complete: function () {
  262. console.log("complete")
  263. }
  264. })
  265. },
  266. read() {
  267. let _this = this
  268. bluetooth.readBLECharacteristicValue({
  269. // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
  270. deviceId: _this.deviceId,
  271. // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
  272. serviceId: _this.serviceId,
  273. // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
  274. characteristicId: _this.readCharacteristicId,
  275. success: function () {
  276. // 执行操作成功,读取的值会在onblecharacteristicvaluechange 接口中上报
  277. console.log("success")
  278. }
  279. })
  280. },
  281. notifyDevice(enable) {
  282. let _this = this
  283. bluetooth.notifyBLECharacteristicValueChange({
  284. // 启用 notify 功能
  285. state: enable,
  286. // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
  287. deviceId: _this.deviceId,
  288. // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
  289. serviceId: _this.serviceId,
  290. // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
  291. characteristicId: _this.notifyCharacteristicId,
  292. success: function () {
  293. // 执行操作成功,读取的值会在onblecharacteristicvaluechange 接口中上报
  294. _this.notifyEnabled = enable
  295. console.log("success")
  296. },
  297. fail: function (data, code) {
  298. console.log(`handling fail, code = ${code}`)
  299. },
  300. complete: function () {
  301. console.log("complete")
  302. }
  303. })
  304. }
  305. };
  306. </script>