bluetooth.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. import game_store from "../store/game";
  2. import ble_store from "../store/bluetooth";
  3. import Notify from "../../static/vant/notify/notify";
  4. import {setDeviceInDb} from "../requests/game";
  5. var $ff = "ff";
  6. var $8f = "ffffffff"
  7. var control_close = false
  8. var connect_toy = true;
  9. export default {
  10. // 打开大包数据
  11. sendOpenBigData() {
  12. this.SendOrder('ff')
  13. },
  14. // 关闭大包数据
  15. sendCloseBigData() {
  16. this.SendOrder('00')
  17. },
  18. //获取当前连接的教具类型
  19. sendGetToyType() {
  20. this.SendOrder('06')
  21. },
  22. // 开启脑控
  23. sendControl() {
  24. this.SendOrder('07')
  25. },
  26. //暂停脑控
  27. sendControlPause() {
  28. //AA CC 03 00 00 00 09 F3
  29. this.SendOrder('08')
  30. },
  31. // 关闭脑控
  32. sendControlClose() {
  33. let that = this
  34. let $intv = setInterval(() => {
  35. if (!control_close) {
  36. that.SendOrder('09')
  37. } else {
  38. clearInterval($intv)
  39. control_close = false
  40. }
  41. }, 1000)
  42. },
  43. //发送一对多连接
  44. sendConnectOneToMore(id) {
  45. this.WriteBufferInBle(`03 00 ${id} 00 0A`);
  46. },
  47. //发送一对一连接
  48. sendConnectOneToOne(id) {
  49. this.WriteBufferInBle(`03 00 ${id} 01 0A`)
  50. },
  51. //获取教具电量
  52. sendToyPower() {
  53. let that = this;
  54. let toy_intv = setInterval(() => {
  55. if (connect_toy) {
  56. that.SendOrder('8a')
  57. connect_toy = false
  58. }
  59. }, 3000)
  60. },
  61. // 获取大包数据 进行绘制图表
  62. get_big_data(hex) {
  63. if (hex.substr(0, 6) != "555520") {
  64. return false;
  65. }
  66. //当s1为 00时 数据有效
  67. let $s1 = hex.substr(8, 2);
  68. if ($s1 != "00") {
  69. return false;
  70. }
  71. //专注度数据
  72. let $att = parseInt("0x" + hex.substr(12, 2));
  73. //放松度数据
  74. let $med = parseInt("0x" + hex.substr(16, 2));
  75. //Delta数据
  76. let $delta_1 = hex.substr(hex.indexOf("0418") + 4, 2);
  77. let $delta_2 = hex.substr(hex.indexOf("0418") + 6, 2);
  78. let $delta_3 = hex.substr(hex.indexOf("0418") + 8, 2);
  79. let $delta = parseInt($delta_1 + $delta_2 + $delta_3, 16);
  80. //Theta数据
  81. let $theta_1 = hex.substr(hex.indexOf("0418") + 10, 2);
  82. let $theta_2 = hex.substr(hex.indexOf("0418") + 12, 2);
  83. let $theta_3 = hex.substr(hex.indexOf("0418") + 14, 2);
  84. let $theta = parseInt($theta_1 + $theta_2 + $theta_3, 16);
  85. //low_Alpha
  86. let $low_alpha_1 = hex.substr(hex.indexOf("0418") + 16, 2);
  87. let $low_alpha_2 = hex.substr(hex.indexOf("0418") + 18, 2);
  88. let $low_alpha_3 = hex.substr(hex.indexOf("0418") + 20, 2);
  89. let $low_alpha = parseInt($low_alpha_1 + $low_alpha_2 + $low_alpha_3, 16);
  90. //high_Alpha
  91. let $high_alpha_1 = hex.substr(hex.indexOf("0418") + 22, 2);
  92. let $high_alpha_2 = hex.substr(hex.indexOf("0418") + 24, 2);
  93. let $high_alpha_3 = hex.substr(hex.indexOf("0418") + 26, 2);
  94. let $high_alpha = parseInt($high_alpha_1 + $high_alpha_2 + $high_alpha_3, 16);
  95. //low_beta
  96. let $low_beta_1 = hex.substr(hex.indexOf("0418") + 28, 2);
  97. let $low_beta_2 = hex.substr(hex.indexOf("0418") + 30, 2);
  98. let $low_beta_3 = hex.substr(hex.indexOf("0418") + 32, 2);
  99. let $low_beta = parseInt($low_beta_1 + $low_beta_2 + $low_beta_3, 16);
  100. //high_beta
  101. let $high_beta_1 = hex.substr(hex.indexOf("0418") + 34, 2);
  102. let $high_beta_2 = hex.substr(hex.indexOf("0418") + 36, 2);
  103. let $high_beta_3 = hex.substr(hex.indexOf("0418") + 38, 2);
  104. let $high_beta = parseInt($high_beta_1 + $high_beta_2 + $high_beta_3, 16);
  105. let $max_num = 30000;
  106. return {
  107. att: $att,
  108. med: $med,
  109. delta: $delta >= $max_num ? $max_num : $delta,
  110. theta: $theta >= $max_num ? $max_num : $theta,
  111. low_alpha: $low_alpha >= $max_num ? $max_num : $low_alpha,
  112. high_alpha: $high_alpha >= $max_num ? $max_num : $high_alpha,
  113. low_beta: $low_beta >= $max_num ? $max_num : $low_beta,
  114. high_beta: $high_beta >= $max_num ? $max_num : $high_beta
  115. };
  116. },
  117. //获取设备电量
  118. get_device_elc(hex) {
  119. if (hex.substr(0, 8) != "55550203") {
  120. return false;
  121. }
  122. let $power = parseInt("0x" + hex.substr(8, 2));
  123. return $power;
  124. },
  125. // 监听蓝牙连接状态
  126. watch_bluetooth_status($this) {
  127. let that = this;
  128. // 微信自身监听低功耗蓝牙连接状态的改变事件
  129. wx.onBLEConnectionStateChange((res) => {
  130. // 该方法回调中可以用于处理连接意外断开等异常情况
  131. ble_store.setters.setBluetoothLinkStatus(res.connected);
  132. if (res.connected == false) {
  133. //判断游戏是否游戏中
  134. let $game_status = game_store.getters.getGameStatus();
  135. if ($game_status == 1) {
  136. // $that.game_finished();
  137. //清除状态 设置为默认初始状态 0 小乌龟
  138. Notify({
  139. type: 'danger',
  140. duration: 0,
  141. message: '智脑环已断开连接,正在尝试重新连接',
  142. onOpened() {
  143. that.reconnect(res.deviceId, $this)
  144. }
  145. });
  146. // game_store.setters.setGameStatus(0);
  147. // 结束状态更改为1
  148. }
  149. }
  150. });
  151. },
  152. //重新连接蓝牙
  153. reconnect($deviceId, $this) {
  154. let that = this;
  155. let $serviceId = game_store.getters.getServiceId();
  156. let $characteristicId = game_store.getters.getReadCharacterId();
  157. //重连的次数
  158. let $connect_count = 0;
  159. let $rec = setInterval(() => {
  160. $connect_count += 1;
  161. wx.createBLEConnection({
  162. deviceId: $deviceId,
  163. success(res) {
  164. Notify({type: 'success', message: `第${$connect_count}次重新连接成功`});
  165. wx.notifyBLECharacteristicValueChange({
  166. deviceId: $deviceId,
  167. serviceId: $serviceId,
  168. characteristicId: $characteristicId,
  169. state: true,
  170. success(res) {
  171. console.log("重新连接SUCCESS,log", res)
  172. that.watchingDevice($this)
  173. }, fail(res) {
  174. console.log("重新失败,log", res)
  175. }
  176. })
  177. that.watchingDevice($this)
  178. clearInterval($rec)
  179. },
  180. fail(res) {
  181. Notify({type: 'danger', message: `第${$connect_count}次重新连接失败`});
  182. game_store.setters.setGameCloseStatus(1);
  183. }
  184. })
  185. if ($connect_count == 3) {
  186. $this.game_finished();
  187. }
  188. }, 5000)
  189. },
  190. //获取蓝牙设备服务
  191. getBLEDeviceServices(deviceId) {
  192. const $this = this;
  193. wx.getBLEDeviceServices({
  194. deviceId,
  195. success: (res) => {
  196. for (let i = 0; i < res.services.length; i++) {
  197. console.log("serviceItem:" + res.services[i].uuid);
  198. if (res.services[i].uuid.indexOf('6E') != -1 || res.services[i].uuid.indexOf('0000FFF0') != -1) {
  199. console.log("SelectedServiceItem:" + res.services[i].uuid);
  200. $this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid);
  201. return;
  202. }
  203. }
  204. },
  205. fail(res) {
  206. console.log("连接蓝牙成功,获取服务失败");
  207. },
  208. });
  209. },
  210. //获取蓝牙设备某个服务中所有特征值
  211. getBLEDeviceCharacteristics(deviceId, serviceId) {
  212. console.log(deviceId, serviceId);
  213. const $this = this;
  214. wx.getBLEDeviceCharacteristics({
  215. deviceId,
  216. serviceId,
  217. success: (res) => {
  218. console.log("getBLEDeviceCharacteristics success", res.characteristics);
  219. for (let i = 0; i < res.characteristics.length; i++) {
  220. let item = res.characteristics[i];
  221. if (item.properties.read) {
  222. wx.readBLECharacteristicValue({
  223. deviceId,
  224. serviceId,
  225. characteristicId: item.uuid,
  226. });
  227. }
  228. if (item.properties.write) {
  229. $this.deviceId = deviceId;
  230. $this.serviceId = serviceId;
  231. $this.cid = item.uuid;
  232. game_store.setters.setDeviceId(deviceId);
  233. game_store.setters.setServiceId(serviceId);
  234. game_store.setters.setCid(item.uuid);
  235. //打开数据帧
  236. $this.sendOpenBigData();
  237. }
  238. if (item.properties.notify || item.properties.indicate) {
  239. wx.notifyBLECharacteristicValueChange({
  240. deviceId,
  241. serviceId,
  242. characteristicId: item.uuid,
  243. state: true,
  244. });
  245. game_store.setters.setReadCid(item.uuid);
  246. }
  247. }
  248. },
  249. fail(res) {
  250. console.error("getBLEDeviceCharacteristics", res);
  251. },
  252. });
  253. },
  254. // ArrayBuffer转16进度字符串示例
  255. ab2hex(buffer) {
  256. var hexArr = Array.prototype.map.call(
  257. new Uint8Array(buffer),
  258. function (bit) {
  259. return ("00" + bit.toString(16)).slice(-2);
  260. }
  261. );
  262. return hexArr.join("");
  263. },
  264. // 监听脑环数据
  265. watchingDevice($this) {
  266. const that = this;
  267. wx.onBLECharacteristicValueChange((characteristic) => {
  268. let hexStr = that.ab2hex(characteristic.value);
  269. // if (hexStr.toUpperCase().indexOf("AADD") != -1) {
  270. console.log(hexStr);
  271. // }
  272. let $data = that.get_big_data(hexStr);
  273. let $game_status = game_store.getters.getGameStatus();
  274. // 2021年10月20日17:18:13 判断教具 连接
  275. if (hexStr.toUpperCase().indexOf("AADD0A") != -1) {
  276. //没连接上教具
  277. if (hexStr.toUpperCase().indexOf("AADD0A0000") != -1) {
  278. $this.change_toy_connect_status(3);
  279. return false;
  280. }
  281. let $hexAry = $this.current_hex.split(" ")
  282. // 03 00 01 00 0a
  283. // [2] [3]
  284. // 连接上教具
  285. if (new RegExp("00").test($hexAry[2]) == false) {
  286. if (new RegExp("00").test($hexAry[3]) == true) {
  287. that.sendConnectOneToOne($hexAry[2])
  288. $this.current_hex = `03 00 $hexAry[2] 01 0A`
  289. console.log("一对多")
  290. } else {
  291. console.log("一对一")
  292. $this.current_hex = "";
  293. wx.showToast({
  294. title: "已连接到" + $this.toy_item.name
  295. });
  296. $this.toy_connected = true;
  297. $this.change_toy_connect_status(2);
  298. //连接成功后 获取一次教具电量信息
  299. that.SendOrder('8a')
  300. }
  301. }
  302. }
  303. //2021年10月21日16:30:07
  304. // 获取教具电量
  305. if (hexStr.toUpperCase().indexOf("AADD8A") != -1) {//接收教具电量状态
  306. let $_hexStr = hexStr.substr(6);
  307. let $power = parseInt($_hexStr.substr(0, 2), 16)
  308. let $voltage = parseInt($_hexStr.substr(2, 2), 16)
  309. console.log("电量:" + $power)
  310. console.log("电压:" + $voltage / 10)
  311. $this.toy_power = $power;
  312. //连接上教具的标识
  313. connect_toy = true;
  314. //2021年10月25日09:16:06
  315. //获取教具UUID
  316. that.SendOrder('84')
  317. }
  318. //监听佩戴正确
  319. if (hexStr.substr(0, 6) == "555520") {
  320. //当s1为 00时 数据有效
  321. let $s1 = hexStr.substr(8, 2);
  322. // console.log("监听脑环是否带正:", $s1 == '00')
  323. $this.device_bg = $s1 == "00";
  324. }
  325. // 2021年10月25日09:15:50
  326. // 收到一次UUID就发送一次获取教具的电量
  327. // 读取教具UUID
  328. if (hexStr.toUpperCase().indexOf("AADD84") != -1) {//接收UUID 5个字节
  329. let $_hexStr = hexStr.substr(6);
  330. let $datas = $_hexStr.substr(0, 10);
  331. if ($datas != "0000000000") {
  332. $this.toy_UUID = $datas;
  333. }
  334. }
  335. //2021年10月26日11:09:01
  336. // 量产结束读取数据
  337. if (hexStr.toUpperCase().indexOf("AADD02") != -1) {
  338. //脑环型号
  339. let $ring_type = hexStr.substr(10).substr(0, hexStr.substr(10).length - 2);
  340. for (let $i = 0; $i < $ring_type.length; $i += 2) {
  341. let $code = parseInt($ring_type.substr($i, 2), 16)
  342. $this.device_data.product_model += String.fromCharCode($code)
  343. }
  344. that.SendOrder("01")
  345. }
  346. if (hexStr.toUpperCase().indexOf("AADD01") != -1) {
  347. let _UUID = ""
  348. let $_str4 = hexStr.substr(6);
  349. let $UUID = $_str4.substr(0, $_str4.length - 2);
  350. for (let $i = 0; $i < $UUID.length; $i += 8) {
  351. let $code = $UUID.substr($i, 8);
  352. _UUID += `${$code}-`
  353. }
  354. _UUID = _UUID.substr(0, _UUID.length - 1)
  355. $this.device_data.UUID = _UUID
  356. that.SendOrder("03")
  357. }
  358. if (hexStr.toUpperCase().indexOf("AADD03") != -1) {
  359. let $_data = that.DoAnalysis(hexStr, 12);
  360. $this.device_data.software_version = $_data.substr(0, 4)
  361. // $this.device_data.software_date = $_data.substr(4)
  362. that.SendOrder("8d")
  363. }
  364. if (hexStr.toUpperCase().indexOf("AADD8D") != -1) {
  365. let $_str5 = hexStr.substr(10);
  366. let $version_date = $_str5.substr(0, $_str5.length - 2);
  367. let $_data = "";
  368. for (let $i = 0; $i < $version_date.length; $i += 2) {
  369. let $code = parseInt($version_date.substr($i, 2), 16)
  370. $_data += String.fromCharCode($code)
  371. }
  372. let $version_data = $_data.substr(0, 2).split('')
  373. $this.device_data.hardware_version = `${$version_data[0]}.${$version_data[1]}`
  374. setDeviceInDb($this, $this.device.deviceId)
  375. }
  376. if (hexStr.toUpperCase().indexOf("AADD09") != -1) {
  377. control_close = true;
  378. }
  379. // 监听脑环电量
  380. let $power = that.get_device_elc(hexStr);
  381. if ($power) {
  382. // console.log("当前脑环电量:", $power)
  383. $this.device_power = $power;
  384. }
  385. if ($power < 10 && $power > 0) {
  386. wx.showToast({
  387. title: "脑环电量不足",
  388. icon: "none",
  389. duration: 2000,
  390. success() {
  391. // $this.change_device_status(0);
  392. },
  393. });
  394. }
  395. //游戏中模块
  396. if ($game_status == 1 && $data) {
  397. try {
  398. if ($this.played_time > 0) {
  399. //自定义定时器
  400. $this.played_time -= 1;
  401. game_store.setters.setPlayedTime($this.played_time)
  402. $this.played_time_text = that.formatPlaySeconds($this.played_time);
  403. $this.do_datas($data);
  404. if ($this.played_time % 10 == 0) {
  405. //读取教具电量
  406. that.SendOrder('8a')
  407. }
  408. }
  409. if ($this.played_time == 0) {
  410. $this.post_data();
  411. //判断是否隐藏 隐藏则不绘画
  412. that.sendControlClose();
  413. let $hide_status = game_store.getters.getHideStatus();
  414. if (!$hide_status) {
  415. $this.game_finished();
  416. }
  417. }
  418. } catch (e) {
  419. console.log("调用方法失败", e);
  420. }
  421. }
  422. });
  423. },
  424. // 游玩时间倒计时
  425. formatPlaySeconds(value) {
  426. // 字符串转数字
  427. var secondTime = parseInt(value); // 秒
  428. var minuteTime = 0; // 分
  429. if (secondTime > 60) {
  430. //如果秒数大于60,将秒数转换成整数
  431. //获取分钟,除以60取整数,得到整数分钟
  432. minuteTime = parseInt(secondTime / 60);
  433. //获取秒数,秒数取佘,得到整数秒数
  434. secondTime = parseInt(secondTime % 60);
  435. //如果分钟大于60,将分钟转换成小时
  436. }
  437. var result = "" + parseInt(secondTime);
  438. if (minuteTime > 0) {
  439. if (result.length == 1) {
  440. result = "0" + result;
  441. }
  442. if (parseInt(minuteTime).toString().length == 1) {
  443. minuteTime = "0" + parseInt(minuteTime);
  444. }
  445. result = "" + minuteTime + ":" + result;
  446. } else {
  447. result = "00:" + result;
  448. }
  449. return result;
  450. },
  451. //根据错误代码返回字符串信息
  452. GetopenBluetoothAdapterError(errCode) {
  453. let $errmsg = "";
  454. if (errCode == 10000) {
  455. $errmsg = "未初始化蓝牙适配器"
  456. }
  457. if (errCode == 10001) {
  458. $errmsg = "当前蓝牙适配器不可用"
  459. }
  460. if (errCode == 10002) {
  461. $errmsg = "没有找到指定设备"
  462. }
  463. if (errCode == 10003) {
  464. $errmsg = "连接失败"
  465. }
  466. if (errCode == 10006) {
  467. $errmsg = "当前连接已断开"
  468. }
  469. return $errmsg;
  470. },
  471. //写入buffer
  472. WriteBufferInBle($hex, $buffer_len = 8) {
  473. let $device_id = game_store.getters.getDeviceId();
  474. let $service_id = game_store.getters.getServiceId()
  475. let $charateristic = game_store.getters.getCharacterId();
  476. let $hex_header = "aa cc ";
  477. // let $hex = "03 00 01 00 0a";
  478. let $hex_sum = 0;
  479. let $hex_ary = $hex.split(" ");
  480. $hex_ary.forEach(($val, $index) => {
  481. $hex_sum += parseInt($val, 16);
  482. })
  483. let $checksum = ($hex_sum ^ parseInt($8f, 16)) & parseInt($ff, 16);
  484. $hex = $hex_header + $hex + " " + $checksum.toString(16);
  485. let buffer = new ArrayBuffer($buffer_len);
  486. let dataView = new DataView(buffer);
  487. $hex_ary = $hex.split(" ");
  488. $hex_ary.forEach(($val, $index) => {
  489. dataView.setUint8($index, parseInt($val, 16))
  490. })
  491. wx.writeBLECharacteristicValue({
  492. deviceId: $device_id,
  493. serviceId: $service_id,
  494. characteristicId: $charateristic,
  495. value: buffer,
  496. success: function (res) {
  497. console.log($hex + ',写入成功')
  498. },
  499. fail: function (err) {
  500. console.log($hex + "写入失败");
  501. console.log(err);
  502. },
  503. });
  504. },
  505. //写入指令
  506. SendOrder(id) {
  507. let $hexStr = `03 00 00 00 ${id}`;
  508. this.WriteBufferInBle($hexStr)
  509. },
  510. Send16Order(val, id) {
  511. let $str = val;
  512. let $str_ary = $str.split('');
  513. $str = "";
  514. $str_ary.forEach(($val, $index) => {
  515. $str += $val.charCodeAt().toString(16) + " "
  516. });
  517. $str = $str.substr(0, $str.length - 1)
  518. let $hexStr = "03 ff " + $str + ` ${id}`;
  519. this.WriteBufferInBle($hexStr, 16)
  520. },
  521. //解析
  522. DoAnalysis(hexStr, byte_count, sublen = 6) {
  523. //byte_count
  524. let $_str5 = hexStr.substr(sublen);
  525. let $datas = $_str5.substr(0, byte_count * 2);
  526. let $_data = "";
  527. for (let $i = 0; $i < $datas.length; $i += 2) {
  528. let $code = parseInt($datas.substr($i, 2), 16)
  529. $_data += String.fromCharCode($code)
  530. }
  531. return $_data;
  532. },
  533. };