bluetooth.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. let dataTransition = require('./dataTransition.js');
  2. let util = require('./util.js');
  3. /**
  4. * v2.1.2
  5. * 胡宇健
  6. * 注:电池锁等获取设备状态的功能暂只兼容了WA-206的设备
  7. */
  8. function BluetoothOperate() {
  9. let _machineNO = null; //当前类保留的设备编号
  10. let _operateType = null; //操作
  11. let _discoveryDevicesTimer = null;
  12. let _deviceId = null;
  13. let _serviceId = 'FEF6'; //UUID
  14. let _characteristicId_notify = null; //读特征值
  15. let _characteristicId_write = null; //写特征值
  16. let _sequenceId = 10; //流水号
  17. let _sendData = ''; //发送的包数据
  18. let _dataLen = 0; //数据长度
  19. let _systemState = '';
  20. let _sequenceId_16 = ''; //流水号16进制
  21. let _CRC16 = '';
  22. let _dataContent = '';
  23. let _connected = false;
  24. let _hasReceive = false;
  25. let _callBack = null; //回调函数
  26. let _key = ''; //蓝牙密钥
  27. let _sendCommandTime = 0;
  28. let _sendCommandTimer = null; //是否重新发送消息的定时器
  29. let _listenerTime = 0;
  30. let _listenerTimer = null;
  31. let _reConnect = 1; //重新连接次数
  32. let _logList = []; //日志包
  33. let _machineState = []; //设备状态二进制数组
  34. let _machineVerson = ''; //设备版本号
  35. let _machinevoltage = ''; //设备电压
  36. this.start = (operateType, machineNO, key, cb) => {
  37. _initVariable(); //初始化变量
  38. //变量赋值
  39. _operateType = operateType;
  40. _key = key;
  41. _callBack = cb;
  42. this.log(machineNO, _machineNO, 'operate:', _operateType); //对比两个设备编号
  43. _initBluetooth(() => { //初始化
  44. //若存在该设备编号表面与前面的操作一致,直接使用deviceId进行连接
  45. if (machineNO == _machineNO && _deviceId && _operateType) {
  46. _startConnectDevices(); //进入直接连接步骤
  47. } else {
  48. _machineNO = machineNO;
  49. _deviceId = null;
  50. _operate(); //进入搜索步骤
  51. }
  52. })
  53. }
  54. this.end = (cb) => {
  55. my.hideLoading();
  56. my.hideToast();
  57. if (_sendCommandTimer) {
  58. clearTimeout(_sendCommandTimer);
  59. }
  60. if (_listenerTimer) {
  61. clearTimeout(_listenerTimer);
  62. }
  63. my.disconnectBLEDevice({
  64. deviceId: _deviceId,
  65. complete: () => {
  66. _closeBluetoothAdapter();
  67. _stopBluetoothDevicesDiscovery();
  68. this.log('结束蓝牙操作!');
  69. cb && cb();
  70. _initVariable();
  71. }
  72. })
  73. }
  74. this.getMachineNO = () => {
  75. return _machineNO;
  76. }
  77. this.getKey = () => {
  78. return _key;
  79. }
  80. this.getLog = () => {
  81. return _logList;
  82. }
  83. //获取电池锁状态
  84. this.getBatteryLockState = () => {
  85. return _machineState[0];
  86. }
  87. //判断电池锁是否开启
  88. this.isOpenBatteryLock = () => {
  89. if (_machineState[0] == 0)
  90. return true;
  91. else
  92. return false;
  93. }
  94. //获取设备运动状态
  95. this.getMotionState = () => {
  96. return _machineState[6];
  97. }
  98. //判断设备是否运动中
  99. this.isMotion = () => {
  100. if (_machineState[6] == 1)
  101. return true;
  102. else
  103. return false;
  104. }
  105. //获取设备借还车状态
  106. this.getBorrowState = () => {
  107. return _machineState[7];
  108. }
  109. //判断设备是否已借车
  110. this.isBorrowed = () => {
  111. if (_machineState[7] == 0)
  112. return true;
  113. else
  114. return false;
  115. }
  116. this.getMachinevoltage = () => {
  117. return _machinevoltage / 1000;
  118. }
  119. const _initVariable = () => {
  120. _operateType = null;
  121. _discoveryDevicesTimer = null;
  122. _serviceId = 'FEF6';
  123. _characteristicId_notify = null;
  124. _characteristicId_write = null;
  125. _sequenceId = 10;
  126. _sendData = '';
  127. _dataLen = 0;
  128. _systemState = '';
  129. _sequenceId_16 = '';
  130. _CRC16 = '';
  131. _dataContent = '';
  132. _connected = false;
  133. _hasReceive = false;
  134. _callBack = null;
  135. _sendCommandTime = 0;
  136. _sendCommandTimer = null;
  137. _listenerTime = 0;
  138. _listenerTimer = null;
  139. _logList = [];
  140. _reConnect = 1;
  141. }
  142. const _operate = () => {
  143. //进入常规搜索流程
  144. _deviceId = null; //一旦进入常规搜索流程初始化id,确保中断操作时下一次操作不会误使用该id
  145. _startBluetoothDevicesDiscovery();
  146. }
  147. //开启蓝牙搜索,下一步打开监听事件
  148. const _startBluetoothDevicesDiscovery = () => {
  149. my.startBluetoothDevicesDiscovery({
  150. allowDuplicatesKey: false,
  151. services: ['FEF6', 'FEF5'],
  152. success: (res) => {
  153. this.log('蓝牙搜索启用成功!');
  154. this.log(res.errMsg);
  155. if (res.isDiscovering) {
  156. _onBluetoothDeviceFound();
  157. } else {
  158. this.log('没有开启定位服务', 'isDiscovering = false');
  159. }
  160. },
  161. fail: (err) => {
  162. if (err.errMsg.indexOf('not init') > -1) {
  163. _initBluetooth(() => {
  164. _startBluetoothDevicesDiscovery();
  165. });
  166. } else {
  167. this.end(() => {
  168. _callBack && _callBack(false);
  169. });
  170. this.log('startBluetoothDevicesDiscovery error:', err.errMsg);
  171. }
  172. }
  173. })
  174. }
  175. //蓝牙搜索监听事件
  176. const _onBluetoothDeviceFound = () => {
  177. _repeatDiscoveryMachine();
  178. my.onBluetoothDeviceFound((res) => {
  179. let device = res.devices[0];
  180. if (device && device.advertisData && device.advertisData.byteLength != 0) {
  181. let machineNO = dataTransition.encrypt(dataTransition.ab2hex(device.advertisData).slice(4, 13));
  182. this.log('搜索到的设备编号:' + machineNO + ",目标:" + _machineNO);
  183. if (machineNO == _machineNO) {
  184. _stopBluetoothDevicesDiscovery();
  185. clearInterval(_discoveryDevicesTimer);
  186. _discoveryDevicesTimer = null;
  187. _deviceId = device.deviceId;
  188. this.log('deviceId:', _deviceId);
  189. // if (_operateType == 'open' || _operateType == 'close')
  190. if (_operateType != '')
  191. _startConnectDevices();
  192. else
  193. _callBack && _callBack(true);
  194. }
  195. }
  196. })
  197. }
  198. //定时器
  199. const _repeatDiscoveryMachine = () => {
  200. let discoveryDevicesTime = 0;
  201. if (_discoveryDevicesTimer) {
  202. clearInterval(_discoveryDevicesTimer);
  203. _discoveryDevicesTimer = null;
  204. }
  205. _discoveryDevicesTimer = setInterval(() => {
  206. if (discoveryDevicesTime > 14) {
  207. clearInterval(_discoveryDevicesTimer);
  208. _discoveryDevicesTimer = null;
  209. discoveryDevicesTime = 0;
  210. my.hideToast();
  211. my.hideLoading();
  212. _stopBluetoothDevicesDiscovery();
  213. this.end(() => {
  214. _callBack && _callBack(false);
  215. });
  216. // my.confirm({
  217. // title: '温馨提示',
  218. // content: '搜索设备失败,请尝试重新打开定位与蓝牙,是否重新搜索?',
  219. // success: (res) => {
  220. // if (res.confirm==false) {
  221. // this.end(() => {
  222. // _callBack && _callBack(false);
  223. // });
  224. // } else { //蒙层和confirm
  225. // my.showToast({
  226. // content: '请稍候',
  227. // icon: 'loading',
  228. // mask: true,
  229. // duration: 1000000
  230. // })
  231. // _startBluetoothDevicesDiscovery();
  232. // }
  233. // }
  234. // })
  235. } else {
  236. discoveryDevicesTime++;
  237. console.log('搜索时间:', discoveryDevicesTime)
  238. }
  239. }, 1000)
  240. }
  241. //通过deviceId连接蓝牙设备
  242. const _startConnectDevices = () => {
  243. if (_deviceId.length > 0) {
  244. my.connectBLEDevice({
  245. deviceId: _deviceId,
  246. timeout: 15000,
  247. success: (res) => {
  248. this.log('createBLEConnection success:', res.errMsg);
  249. if (res.errCode == 0) {
  250. _getService();
  251. }
  252. },
  253. fail: (err) => {
  254. this.log('createBLEConnection error:', err.errMsg);
  255. if (err.errCode != -1 && err.errCode != 10000) {
  256. if (err.errCode == 10006 || err.errCode == 10003 || err.errCode == 10012) {
  257. this.end(() => {
  258. _callBack && _callBack(false);
  259. });
  260. // my.confirm({
  261. // title: '温馨提示',
  262. // content: '连接失败,请尝试: (1)重新打开手机定位 (2)点击重试',
  263. // confirmText: '重试',
  264. // success: (res) => {
  265. // if (res.confirm == false) {
  266. // this.end(() => {
  267. // _callBack && _callBack(false);
  268. // });
  269. // } else {
  270. // this.log('正在重连...');
  271. // //这里加一个
  272. // my.closeBLEConnection({
  273. // deviceId: _deviceId,
  274. // complete: () => {
  275. // my.closeBluetoothAdapter({
  276. // success: () => {
  277. // my.openBluetoothAdapter({
  278. // success: () => {
  279. // this.log('重连之前,重启蓝牙适配器成功!')
  280. // if (_reConnect >= 2) {
  281. // _startBluetoothDevicesDiscovery();
  282. // } else {
  283. // _reConnect++;
  284. // _startConnectDevices();
  285. // }
  286. // }
  287. // })
  288. // }
  289. // });
  290. // },
  291. // })
  292. // }
  293. // }
  294. // })
  295. }
  296. } else if (err.errMsg.indexOf('not init') > -1) { //入口之一,判断无初始化直接执行
  297. _initBluetooth(() => {
  298. _startConnectDevices();
  299. });
  300. } else {
  301. this.end(() => {
  302. _callBack && _callBack(false);
  303. });
  304. }
  305. },
  306. complete: () => {
  307. }
  308. });
  309. }
  310. }
  311. //获取所有服务
  312. const _getService = () => {
  313. _reConnect = 1;
  314. // 获取蓝牙设备service值
  315. my.getBLEDeviceServices({
  316. deviceId: _deviceId,
  317. success: (res) => {
  318. this.log('获取的所有服务值', res.errMsg);
  319. _getCharacter(res.services);
  320. },
  321. fail: (err) => {
  322. this.log('getBLEDeviceServices error', err.errMsg);
  323. my.showToast({
  324. content: 'service获取失败',
  325. icon: 'none',
  326. })
  327. this.end(() => {
  328. _callBack && _callBack(false);
  329. });
  330. }
  331. })
  332. }
  333. //获取特征值
  334. const _getCharacter = (services) => {
  335. services.forEach((service, index) => {
  336. if (service.uuid.indexOf(_serviceId) > -1) {
  337. _serviceId = service.uuid;
  338. this.log("serviced", _serviceId)
  339. my.getBLEDeviceCharacteristics({
  340. deviceId: _deviceId,
  341. serviceId: _serviceId,
  342. success: (res) => {
  343. this.log('特征值:', res.errMsg);
  344. res.characteristics.forEach((item) => {
  345. if (item.properties.write)
  346. _characteristicId_write = item.uuid;
  347. if (!item.properties.write && item.properties.notify)
  348. _characteristicId_notify = item.uuid;
  349. })
  350. this.log('特征值读:', _characteristicId_notify, '特征值写:', _characteristicId_write);
  351. _notifyBLECharacteristicValueChange(() => {
  352. _connectCtrl();
  353. });
  354. },
  355. fail: (err) => {
  356. this.log('读取特征值失败:' + err.errMsg);
  357. this.end(() => {
  358. _callBack && _callBack(false);
  359. });
  360. util.showModal_nocancel('读取特征值失败,请重试。')
  361. }
  362. })
  363. return;
  364. }
  365. });
  366. }
  367. //秘钥连接指令
  368. const _connectCtrl = () => {
  369. let secretKey = _key.toString().trim().toLowerCase();
  370. //拼接数据头
  371. let sequenceId_16 = dataTransition.getSequenceId(_sequenceId);
  372. _sequenceId++;
  373. let c = secretKey.toString().replace(/\s+/g, "");
  374. let cLength = dataTransition.getSecretKeyLength(c);
  375. //发送内容
  376. let sendValue = `02 00 01 ${cLength}`; //02 连接命令 01连接请求 cLength秘钥长度。
  377. let allData = `${sendValue} ${secretKey}`;
  378. let header = dataTransition.header(allData, 0, '00', sequenceId_16);
  379. let data = header + allData.replace(/\s+/g, "");
  380. this.log('发送的连接数据:', data);
  381. _sendCtrl(data);
  382. }
  383. //发送指令。判断是否分包发送数据
  384. const _sendCtrl = (data) => {
  385. //保存一下发送的数据
  386. _sendData = data;
  387. //如果大于20个字节则分包发送,两个字符一个字节
  388. let dataLen = Math.ceil(data.length / 40);
  389. if (dataLen > 1) { //3
  390. for (let i = 0; i < data.length; i += 40) {
  391. let value = dataTransition.hexStringToArrayBuffer(data.slice(i, i + 40));
  392. this.log("分包发送的数据", data.slice(i, i + 40))
  393. _writeBLECharacteristicValue(value);
  394. }
  395. } else {
  396. let value = dataTransition.hexStringToArrayBuffer(data);
  397. _writeBLECharacteristicValue(value);
  398. }
  399. }
  400. //发送信息
  401. const _writeBLECharacteristicValue = (value, cb) => {
  402. setTimeout(() => {
  403. my.writeBLECharacteristicValue({
  404. deviceId: _deviceId,
  405. serviceId: _serviceId,
  406. characteristicId: _characteristicId_write,
  407. // 这里的value是ArrayBuffer类型
  408. value: value,
  409. success: (res) => {
  410. this.log('发送信息成功', res.errMsg);
  411. cb && cb();
  412. },
  413. fail: (err) => {
  414. this.log('writeBLECharacteristicValue error ', err.errMsg);
  415. let code = err.errCode;
  416. if (code == 10006 || code == 10000) { //连接断开
  417. _startConnectDevices();
  418. } else if (code == 10008) {
  419. this.log('重发数据', dataTransition.ab2hex(value));
  420. _writeBLECharacteristicValue(value);
  421. } else {
  422. util.showModal_nocancel('数据发送失败,请重试。');
  423. this.end(() => {
  424. _callBack && _callBack(false);
  425. });
  426. }
  427. }
  428. })
  429. }, 200);
  430. }
  431. //监听事件开启
  432. const _notifyBLECharacteristicValueChange = (cb) => {
  433. my.notifyBLECharacteristicValueChange({
  434. state: true,
  435. deviceId: _deviceId,
  436. serviceId: _serviceId,
  437. characteristicId: _characteristicId_notify,
  438. success: () => {
  439. if (_listenerTime != -1) { //超时安全判断
  440. _listenerTimer = setTimeout(() => {
  441. if (_listenerTime == 0) {
  442. this.log('未接收到回复信息!自动重发一次!');
  443. _listenerTime++;
  444. _connectCtrl();
  445. } else {
  446. my.hideToast();
  447. my.hideLoading();
  448. my.confirm({
  449. content: '未接收到回复信息!',
  450. confirmText: '重试',
  451. success: (res) => {
  452. if (res.confirm == true) {
  453. my.showToast({
  454. content: '请稍后',
  455. icon: 'loading',
  456. mask: true,
  457. duration: 100000
  458. })
  459. _connectCtrl();
  460. } else {
  461. this.end(() => {
  462. _callBack && _callBack(false);
  463. });
  464. }
  465. }
  466. })
  467. }
  468. }, 5000)
  469. }
  470. my.onBLECharacteristicValueChange((res) => {
  471. clearTimeout(_listenerTimer);
  472. _listenerTime = -1;
  473. let data = dataTransition.ab2hex(res.value)
  474. this.log('********notify收到的数据:', data);
  475. if (data.slice(0, 4) == 'aa10') {
  476. this.log('指令发送成功:');
  477. } else if (data.slice(0, 4) == 'aa30') {
  478. this.log('CRC校验失败');
  479. util.showModal_nocancel('CRC校验失败,请重试。');
  480. this.end(() => {
  481. _callBack && _callBack(false);
  482. });
  483. //end
  484. } else if (data.slice(0, 3) == 'aa0' && _dataLen == 0) {
  485. //设备版本号
  486. _machineVerson = data.slice(2, 4);
  487. //16进制流水号
  488. _sequenceId_16 = data.slice(6, 8); //0a
  489. //计算数据包长度
  490. _dataLen = parseInt(data.slice(8, 12), 16); //003e,16=62
  491. //计算systemState
  492. _systemState = data.slice(4, 6); //4c
  493. _analysisSystem(_systemState);
  494. //crc
  495. _CRC16 = data.slice(12, 16); //290e
  496. this.log("需要接收的字节长度", _dataLen);
  497. if (data.length > 16) {
  498. _connectData(data.slice(16))
  499. }
  500. } else {
  501. if (_dataLen > 0) {
  502. _connectData(data)
  503. }
  504. }
  505. })
  506. cb && cb();
  507. },
  508. fail: (err) => {
  509. this.log('notifyBLECharacteristicValueChange', err.errMsg);
  510. util.showModal_nocancel('特征值监听开启失败,请重试。')
  511. this.end(() => {
  512. _callBack && _callBack(false);
  513. });
  514. }
  515. })
  516. }
  517. //解析存储车辆状态
  518. const _analysisSystem = (systemState) => {
  519. //16进制转换为10进制
  520. let decimalState = parseInt(systemState, 16);
  521. //10进制转换为2进制
  522. let binaryState = parseInt(decimalState).toString(2);
  523. if (binaryState.length < 8) {
  524. let supplyNum = 8 - binaryState.length;
  525. while (supplyNum > 0) {
  526. binaryState = '0' + binaryState;
  527. supplyNum--;
  528. }
  529. }
  530. //字符串拆分成为数组
  531. let stateArray = Array.prototype.slice.call(binaryState);
  532. _machineState = stateArray;
  533. console.log(stateArray);
  534. }
  535. //拼接数据,判断数据并发送
  536. const _connectData = (data) => {
  537. this.log('拼接内容:', data);
  538. _dataContent += data;
  539. this.log('内容长度', _dataContent.length, '接收到的数据长度', _dataLen, '*2');
  540. if (_dataContent.length == _dataLen * 2) { //接收完该长度的字节和校验CRC成功之后再发送ACK
  541. let dc = _dataContent;
  542. let dcArr = [];
  543. this.log('接收的数据长度字节:', dc.length / 2);
  544. let contentArr = dataTransition.addFlagBeforeArr(dataTransition.strAverage2Arr(dc, 2));
  545. if (parseInt(dataTransition.getCRC16(contentArr), 16) == parseInt(_CRC16, 16)) {
  546. this.log('CRC16校验成功');
  547. let value = dataTransition.hexStringToArrayBuffer(`aa12${_systemState}${_sequenceId_16}00000000`);
  548. this.log(`返回的确认数据${dataTransition.ab2hex(value)}`);
  549. //分析数据返回的内容
  550. _analysisBLEContent(dc, value);
  551. } else {
  552. this.log('CRC16校验失败', dataTransition.getCRC16(contentArr) + "_应为:" + _CRC16);
  553. util.showModal_nocancel('CRC16校验失败,请重试。');
  554. this.end(() => {
  555. _callBack && _callBack(false);
  556. });
  557. //end
  558. }
  559. _dataLen = 0;
  560. _systemState = '';
  561. _dataContent = '';
  562. _sequenceId_16 = '';
  563. _CRC16 = '';
  564. }
  565. }
  566. //解析蓝牙发送内容
  567. const _analysisBLEContent = (content, reply) => {
  568. this.log('解析数据数据***************', content);
  569. if (content.indexOf('020101') > -1) {
  570. if (!_connected) {
  571. _connected = true;
  572. this.log('连接成功');
  573. _writeBLECharacteristicValue(reply, () => {
  574. _ctrl(_operateType);
  575. });
  576. _analysisVoltage(content);
  577. }
  578. } else if (content.indexOf('0300820100') > -1) {
  579. if (_sendCommandTimer) { //每次都将清楚等待任务
  580. clearTimeout(_sendCommandTimer);
  581. _sendCommandTimer = null;
  582. }
  583. if (!_hasReceive) {
  584. _hasReceive = true;
  585. _writeBLECharacteristicValue(reply, () => {
  586. this.log('开锁成功,开始回调ctrl_cb');
  587. this.end(() => {
  588. _callBack && _callBack(true);
  589. });
  590. });
  591. }
  592. } else if (content.indexOf('0300810100') > -1) {
  593. if (_sendCommandTimer) { //每次都将清楚等待任务
  594. clearTimeout(_sendCommandTimer);
  595. _sendCommandTimer = null;
  596. }
  597. if (!_hasReceive) {
  598. _hasReceive = true;
  599. _writeBLECharacteristicValue(reply, () => {
  600. this.log('上锁成功,开始回调ctrl_cb');
  601. this.end(() => {
  602. _callBack && _callBack(true);
  603. });
  604. });
  605. }
  606. } else if (content.indexOf('0300840100') > -1) {
  607. //响铃成功
  608. if (_sendCommandTimer) { //每次都将清楚等待任务
  609. clearTimeout(_sendCommandTimer);
  610. _sendCommandTimer = null;
  611. }
  612. if (!_hasReceive) {
  613. _hasReceive = true;
  614. _writeBLECharacteristicValue(reply, () => {
  615. this.log('响铃成功,开始回调ctrl_cb');
  616. this.end(() => {
  617. _callBack && _callBack(true);
  618. });
  619. });
  620. }
  621. } else if (content.indexOf('0300870100') > -1) {
  622. //临时关锁成功
  623. if (_sendCommandTimer) { //每次都将清楚等待任务
  624. clearTimeout(_sendCommandTimer);
  625. _sendCommandTimer = null;
  626. }
  627. if (!_hasReceive) {
  628. _hasReceive = true;
  629. _writeBLECharacteristicValue(reply, () => {
  630. this.log('响铃成功,开始回调ctrl_cb');
  631. this.end(() => {
  632. _callBack && _callBack(true);
  633. });
  634. });
  635. }
  636. } else if (content.indexOf('0300850100') > -1) {
  637. //开电池锁成功
  638. if (_sendCommandTimer) { //每次都将清楚等待任务
  639. clearTimeout(_sendCommandTimer);
  640. _sendCommandTimer = null;
  641. }
  642. if (!_hasReceive) {
  643. _hasReceive = true;
  644. _writeBLECharacteristicValue(reply, () => {
  645. this.log('响铃成功,开始回调ctrl_cb');
  646. this.end(() => {
  647. _callBack && _callBack(true);
  648. });
  649. });
  650. }
  651. } else if (content.indexOf('04008524') > -1) {
  652. _writeBLECharacteristicValue(reply, () => {
  653. this.log('心跳包');
  654. });
  655. } else if (content.indexOf('020100') > -1) {
  656. if (_sendCommandTimer) { //每次都将清楚等待任务
  657. clearTimeout(_sendCommandTimer);
  658. _sendCommandTimer = null;
  659. }
  660. this.log('鉴权失败:', _sendData);
  661. util.showModal_nocancel('鉴权失败!')
  662. this.end(() => {
  663. _callBack && _callBack(false);
  664. });
  665. //end
  666. } else {
  667. if (_sendCommandTimer) { //每次都将清楚等待任务
  668. clearTimeout(_sendCommandTimer);
  669. _sendCommandTimer = null;
  670. }
  671. this.end(() => {
  672. let text = content === '0300810102' ? '运动中不能上锁!' : '蓝牙操作失败,请重试!';
  673. this.log(text)
  674. my.showToast({
  675. content: text,
  676. mask: true,
  677. icon: 'none',
  678. duration: 5000
  679. })
  680. _callBack && _callBack(false);
  681. })
  682. }
  683. }
  684. const _analysisVoltage = (content) => {
  685. //判断81 :终端电池电压
  686. if (content.indexOf('02010181') > -1) {
  687. //这之后两位表示电池电压:81,两位表示长度:02,加上020101共十位
  688. let startN = content.indexOf('020101') + 10;
  689. //后四位表示电压值:16进制
  690. let voltageData = content.slice(startN, startN + 4);
  691. let voltage = parseInt(voltageData, 16);
  692. if (_machineVerson == '02')
  693. _machinevoltage = voltage * 10;
  694. else
  695. _machinevoltage = voltage;
  696. }
  697. }
  698. //指令
  699. const _ctrl = (type) => {
  700. let sequenceId_16 = dataTransition.getSequenceId(_sequenceId);
  701. _sequenceId++;
  702. let sendData = '';
  703. if (type === 'open') //<aa02000b 00057edb 03000201 00 >
  704. sendData = '03 00 02 01 00';
  705. else if (type === 'close') //<aa02000c 00058036 03000101 01 >
  706. sendData = '03 00 01 01 01';
  707. else if (type === 'bell') //<aa02000c 00058036 03000101 01 >
  708. sendData = '03 00 04 01 01';
  709. else if (type === 'batteryOpen') //<aa02000c 00058036 03000101 01 >
  710. sendData = '03 00 05 01 01';
  711. else if (type === 'temporaryClose') //<aa02000c 00058036 03000101 01 >
  712. sendData = '03 00 01 01 30';
  713. else if (type === 'temporaryOpen') //<aa02000c 00058036 03000101 01 >
  714. sendData = '03 00 01 01 31';
  715. let header = dataTransition.header(sendData, 0, '00', sequenceId_16);
  716. let data = header + sendData.replace(/\s+/g, "");
  717. this.log(`发送${type}指令`, data);
  718. _sendCtrl(data);
  719. _sendCommandTimer = setTimeout(() => { //可能出现发送消息后没有收到应答,将再次发送
  720. if (_sendCommandTime == 0) {
  721. this.log('设备未响应,自动重发')
  722. _sendCommandTime++;
  723. _ctrl(_operateType);
  724. } else {
  725. this.log('设备未响应')
  726. my.hideLoading();
  727. util.showModal('设备未响应,是否重新发送指令?', () => {
  728. this.log('手动重发ctrl')
  729. my.showLoading({
  730. content: '开锁中',
  731. })
  732. _ctrl(_operateType);
  733. }, () => {
  734. this.end(() => {
  735. _callBack && _callBack(false);
  736. });
  737. })
  738. }
  739. }, 5000)
  740. }
  741. const _stopBluetoothDevicesDiscovery = () => {
  742. my.stopBluetoothDevicesDiscovery({
  743. success: (res) => {
  744. this.log('停止搜寻附近的蓝牙外围设备');
  745. },
  746. fail: (err) => {
  747. this.log(err.errMsg);
  748. }
  749. })
  750. }
  751. const _closeBluetoothAdapter = () => {
  752. my.closeBluetoothAdapter({
  753. success: (res) => {
  754. this.log('关闭蓝牙适配器')
  755. },
  756. fail: (err) => {
  757. this.log(err.errMsg);
  758. }
  759. })
  760. }
  761. const _initBluetooth = (cb) => {
  762. my.openBluetoothAdapter({
  763. success: (res) => {
  764. },
  765. fail: (err) => {
  766. this.log('initBluetooth:', err.errMsg);
  767. // my.showToast({
  768. // content: '蓝牙初始化失败',
  769. // icon: 'none',
  770. // })
  771. },
  772. complete: () => {
  773. cb && cb();
  774. }
  775. })
  776. }
  777. this.log = (...str) => {
  778. let now = new Date();
  779. now = util.formatTime(now)
  780. console.log(now, ...str);
  781. _logList.push(str.join(','))
  782. }
  783. }
  784. module.exports = BluetoothOperate