小程序蓝牙通信例子
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

310 lines
9.6 KiB

  1. import * as t from "./tools"
  2. /*
  3. import { HTTP } from "../server";
  4. */
  5. /**
  6. * 蓝牙工具类
  7. * 封装小程序蓝牙流程方法
  8. * 处理事件通信
  9. */
  10. class BLEHandler {
  11. constructor(blename, emitter) {
  12. this.blename = blename //厂家自定义的蓝牙设备名称
  13. this.emitter = emitter
  14. this.readCharacteristicId = ""; //能从硬件返回的信息中自动提取
  15. this.writeCharacteristicId = "00002af1-0000-1000-8000-00805f9b34fb"; //能从硬件返回的信息中自动提取
  16. this.notifyCharacteristicId = "00002af0-0000-1000-8000-00805f9b34fb"; //能从硬件返回的信息中自动提取
  17. this.deviceId = ""; //蓝牙Mac地址
  18. this.serviceId = "000018f0-0000-1000-8000-00805f9b34fb";//具体的serviceId要自己根据硬件提供设置。
  19. this.receivePacket = [];
  20. this.recPktLength = 0;
  21. this.recPktOffset = 0;
  22. }
  23. async openAdapter() {
  24. let [err, res] = await t._openAdapter.call(this);
  25. if (err != null) {
  26. this.emitter.emit("channel", {
  27. type: "connect",
  28. data: "未打开适配器"
  29. })
  30. return false;
  31. }
  32. return true
  33. }
  34. async startSearch() {
  35. let [err, res] = await t._startSearch.call(this);
  36. if (err != null) {
  37. return;
  38. }
  39. this.emitter.emit("channel", {
  40. type: "connect",
  41. data: "正在连接中..."
  42. })
  43. }
  44. async onBluetoothFound() {
  45. let [err, res] = await t._onBluetoothFound.call(this);
  46. if (err != null) {
  47. this.emitter.emit("channel", {
  48. type: "connect",
  49. data: "未找到设备"
  50. })
  51. return false;
  52. }
  53. return true
  54. }
  55. async getBluetoothDevices() {
  56. let [err, res] = await t._getBluetoothDevices.call(this);
  57. if (err != null) {
  58. this.emitter.emit("channel", {
  59. type: "connect",
  60. data: "未找到设备"
  61. })
  62. return false;
  63. }
  64. return true
  65. }
  66. async stopSearchBluetooth() {
  67. let [err, res] = await t._stopSearchBluetooth.call(this);
  68. if (err != null) {
  69. return;
  70. }
  71. }
  72. async connectBlue() {
  73. let [err, res] = await t._connectBlue.call(this);
  74. if (err != null) {
  75. return;
  76. }
  77. }
  78. async setBLEMTU() {
  79. let [err, res] = await t._setBLEMTU.call(this);
  80. if (err != null) {
  81. return;
  82. }
  83. }
  84. async getBLEServices() {
  85. let [err, res] = await t._getBLEServices.call(this);
  86. if (err != null) {
  87. return;
  88. }
  89. }
  90. async getCharacteristics() {
  91. let [err, res] = await t._getCharacteristics.call(this);
  92. if (err != null) {
  93. this.emitter.emit("channel", {
  94. type: "connect",
  95. data: "无法订阅特征值"
  96. })
  97. // 取消连接
  98. this.closeBLEConnection()
  99. this.closeBLEAdapter()
  100. wx.setStorageSync("bluestatus", "");
  101. return false;
  102. }
  103. this.emitter.emit("channel", {
  104. type: "connect",
  105. data: "蓝牙已连接"
  106. })
  107. wx.setStorageSync("bluestatus", "on");
  108. return true
  109. }
  110. async notifyBLECharacteristicValueChange() {
  111. let [err, res] = await t._notifyBLECharacteristicValueChange.call(this);
  112. if (err != null) {
  113. return;
  114. }
  115. }
  116. async closeBLEConnection() {
  117. let [err, res] = await t._closeBLEConnection.call(this);
  118. if (err != null) {
  119. return;
  120. }
  121. }
  122. async closeBLEAdapter() {
  123. let [err, res] = await t._closeBLEAdapter.call(this);
  124. if (err != null) {
  125. return;
  126. }
  127. }
  128. async sentOrder(cmd, payload) {
  129. let data = t._sentOrder(cmd, payload)
  130. console.log("-- 发送数据:", data)
  131. let arrayBuffer = new Uint8Array(data).buffer;
  132. let [err, res] = await t._writeBLECharacteristicValue.call(this, arrayBuffer)
  133. if (err != null) {
  134. return false
  135. }
  136. console.log("数据发送成功!")
  137. return true
  138. }
  139. // 打开蓝牙适配器状态监听
  140. onBLEConnectionStateChange() {
  141. wx.onBLEConnectionStateChange(res => {
  142. // 该方法回调中可以用于处理连接意外断开等异常情况
  143. if (!res.connected) {
  144. this.closeBLEAdapter()
  145. wx.setStorageSync("bluestatus", "");
  146. this.emitter.emit("channel", {
  147. type: "connect",
  148. data: "蓝牙已断开"
  149. })
  150. }
  151. }, err => {
  152. console.log('err', err)
  153. })
  154. }
  155. // 收到设备推送的notification
  156. onBLECharacteristicValueChange() {
  157. wx.onBLECharacteristicValueChange(res => {
  158. //let arrbf = new Uint8Array(res.value)
  159. //console.log(`收到硬件数据反馈!命令码为:${arrbf[2]}`)
  160. //if (this._checkData(arrbf)) {
  161. //}
  162. let arrbf = new Uint8Array(res.value)
  163. if (arrbf[0] == 0x89 && arrbf[1] == 0x89)
  164. {
  165. let dataLength = ((arrbf[10] << 8) & 0xff00) + (arrbf[11] & 0x00ff)
  166. this.recPktLength = 13 + dataLength
  167. this.receivePacket = new Uint8Array(this.recPktLength)
  168. this.recPktOffset = 0
  169. console.log("开始接收数据:length= " + arrbf.length + " data= " + arrbf)
  170. this.receivePacket.set(arrbf, this.recPktOffset)
  171. this.recPktOffset += arrbf.length;
  172. if( this.recPktOffset == this.recPktLength){
  173. this.getReceivePacket(this.receivePacket)
  174. }
  175. }
  176. else
  177. {
  178. console.log("继续接收数据:length= " + arrbf.length + " data= " + arrbf)
  179. this.receivePacket.set(arrbf, this.recPktOffset)
  180. this.recPktOffset += arrbf.length;
  181. if( this.recPktOffset == this.recPktLength){
  182. this.getReceivePacket(this.receivePacket)
  183. }
  184. }
  185. })
  186. }
  187. /*
  188. _uploadInfo(message) {
  189. console.log("-- 准备数据同步!", this._mapToArray(message))
  190. let bleorder = wx.getStorageSync("bleorder");
  191. let blecabinet = wx.getStorageSync("blecabinet")
  192. HTTP({
  193. url: "cabinet/uploadBlueData",
  194. methods: "post",
  195. data: {
  196. cabinetQrCode: blecabinet,
  197. order: bleorder,
  198. message: this._mapToArray(message)
  199. }
  200. }).then(res => {
  201. console.log("✔ 数据同步成功!")
  202. }, err => {
  203. console.log('✘ 数据同步失败', err)
  204. })
  205. }
  206. */
  207. _mapToArray(arrbf) {
  208. let arr = []
  209. arrbf.map(item => {
  210. arr.push(item)
  211. })
  212. return arr
  213. }
  214. // 校验数据正确性
  215. _checkData(arrbf) {
  216. let packetLen = arrbf.length;
  217. console.log("接收数据:" + arrbf)
  218. // 校验帧头帧尾
  219. if (arrbf[0] != 0x89 || arrbf[1] != 0x89) {
  220. console.log('不是该设备返回的包')
  221. return false
  222. }
  223. if (packetLen < 14) {
  224. console.log("包长太短,不是该设备返回的包");
  225. return false;
  226. }
  227. let dataLength = ((arrbf[10] << 8) & 0xff00) + (arrbf[11] & 0x00ff);
  228. if (dataLength != (packetLen - 13)) {
  229. let calLen = packetLen - 13;
  230. console.log("✘ 数据长度错误: " + dataLength + " is not " + calLen);
  231. return false;
  232. }
  233. //校验包
  234. let check = arrbf[0];
  235. for (let i = 1; i < packetLen - 1; i++)
  236. check ^= arrbf[i];
  237. if (check != arrbf[packetLen - 1]) {
  238. console.log("crc校验错误,请重发." + check);
  239. return false;
  240. }
  241. console.log('✔ 数据校验成功,接收完整!')
  242. return true
  243. }
  244. getReceivePacket(arrbf)
  245. {
  246. let packetLen = arrbf.length;
  247. console.log("接收数据:" + arrbf)
  248. // 校验帧头帧尾
  249. if (arrbf[0] != 0x89 || arrbf[1] != 0x89) {
  250. console.log('不是该设备返回的包')
  251. return [0];
  252. }
  253. if (packetLen < 14) {
  254. console.log("包长太短,不是该设备返回的包");
  255. return [0];
  256. }
  257. let dataLength = ((arrbf[10] << 8) & 0xff00) + (arrbf[11] & 0x00ff);
  258. if (dataLength != (packetLen - 13)) {
  259. let calLen = packetLen - 13;
  260. console.log("✘ 数据长度错误: " + dataLength + " is not " + calLen);
  261. return [0];
  262. }
  263. //校验包
  264. let check = arrbf[0];
  265. for (let i = 1; i < packetLen - 1; i++)
  266. check ^= arrbf[i];
  267. if (check != arrbf[packetLen - 1]) {
  268. console.log("crc校验错误,请重发." + check);
  269. return [0];
  270. }
  271. //数据解密
  272. let key = arrbf[3];
  273. let data_offset = 12;
  274. let result = new Uint8Array(dataLength)
  275. for (let i = 0; i < dataLength; i++) {
  276. result[i] = arrbf[i + data_offset];
  277. result[i] = (result[i] ^ (key ^ i));
  278. result[i] += (dataLength - i) ^ key;
  279. }
  280. console.log('✔ 数据校验成功,接收完整! packet= ' + arrbf)
  281. console.log('解密明文 result= ' + result)
  282. return result;
  283. }
  284. }
  285. export default BLEHandler