bluetooth.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  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.closeBLEConnection({
  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. my.confirm({
  214. title: '温馨提示',
  215. content: '搜索设备失败,请尝试重新打开定位与蓝牙,是否重新搜索?',
  216. success: (res) => {
  217. if (res.confirm==false) {
  218. this.end(() => {
  219. _callBack && _callBack(false);
  220. });
  221. } else { //蒙层和confirm
  222. my.showToast({
  223. content: '请稍候',
  224. icon: 'loading',
  225. mask: true,
  226. duration: 1000000
  227. })
  228. _startBluetoothDevicesDiscovery();
  229. }
  230. }
  231. })
  232. }else{
  233. discoveryDevicesTime++;
  234. console.log('搜索时间:', discoveryDevicesTime)
  235. }
  236. },1000)
  237. }
  238. //通过deviceId连接蓝牙设备
  239. const _startConnectDevices = () => {
  240. if (_deviceId.length > 0) {
  241. my.createBLEConnection({
  242. deviceId: _deviceId,
  243. timeout: 15000,
  244. success: (res) => {
  245. this.log('createBLEConnection success:', res.errMsg);
  246. if (res.errCode == 0) {
  247. _getService();
  248. }
  249. },
  250. fail: (err) => {
  251. this.log('createBLEConnection error:', err.errMsg);
  252. if (err.errCode != -1 && err.errCode != 10000) {
  253. if (err.errCode == 10006 || err.errCode == 10003 || err.errCode == 10012) {
  254. my.confirm({
  255. title: '温馨提示',
  256. content: '连接失败,请尝试: (1)重新打开手机定位 (2)点击重试',
  257. confirmText: '重试',
  258. success: (res) => {
  259. if (res.confirm==false) {
  260. this.end(() => {
  261. _callBack && _callBack(false);
  262. });
  263. } else {
  264. this.log('正在重连...');
  265. //这里加一个
  266. my.closeBLEConnection({
  267. deviceId: _deviceId,
  268. complete: () => {
  269. my.closeBluetoothAdapter({
  270. success: () => {
  271. my.openBluetoothAdapter({
  272. success: () => {
  273. this.log('重连之前,重启蓝牙适配器成功!')
  274. if(_reConnect >= 2){
  275. _startBluetoothDevicesDiscovery();
  276. } else {
  277. _reConnect++;
  278. _startConnectDevices();
  279. }
  280. }
  281. })
  282. }
  283. });
  284. },
  285. })
  286. }
  287. }
  288. })
  289. }
  290. } else if (err.errMsg.indexOf('not init') > -1) { //入口之一,判断无初始化直接执行
  291. _initBluetooth(() => {
  292. _startConnectDevices();
  293. });
  294. } else {
  295. this.end(() => {
  296. _callBack && _callBack(false);
  297. });
  298. }
  299. },
  300. complete: () => {
  301. }
  302. });
  303. }
  304. }
  305. //获取所有服务
  306. const _getService = () => {
  307. _reConnect = 1;
  308. // 获取蓝牙设备service值
  309. my.getBLEDeviceServices({
  310. deviceId: _deviceId,
  311. success: (res) => {
  312. this.log('获取的所有服务值', res.errMsg);
  313. _getCharacter(res.services);
  314. },
  315. fail: (err) => {
  316. this.log('getBLEDeviceServices error', err.errMsg);
  317. my.showToast({
  318. content: 'service获取失败',
  319. icon: 'none',
  320. })
  321. this.end(() => {
  322. _callBack && _callBack(false);
  323. });
  324. }
  325. })
  326. }
  327. //获取特征值
  328. const _getCharacter = (services) => {
  329. services.forEach((service, index) => {
  330. if (service.uuid.indexOf(_serviceId) > -1) {
  331. _serviceId = service.uuid;
  332. this.log("serviced", _serviceId)
  333. my.getBLEDeviceCharacteristics({
  334. deviceId: _deviceId,
  335. serviceId: _serviceId,
  336. success: (res) => {
  337. this.log('特征值:', res.errMsg);
  338. res.characteristics.forEach((item) => {
  339. if(item.properties.write)
  340. _characteristicId_write = item.uuid;
  341. if(!item.properties.write && item.properties.notify)
  342. _characteristicId_notify = item.uuid;
  343. })
  344. this.log('特征值读:', _characteristicId_notify, '特征值写:', _characteristicId_write);
  345. _notifyBLECharacteristicValueChange(() => {
  346. _connectCtrl();
  347. });
  348. },
  349. fail: (err) => {
  350. this.log('读取特征值失败:' + err.errMsg);
  351. this.end(() => {
  352. _callBack && _callBack(false);
  353. });
  354. util.showModal_nocancel('读取特征值失败,请重试。')
  355. }
  356. })
  357. return;
  358. }
  359. });
  360. }
  361. //秘钥连接指令
  362. const _connectCtrl = () => {
  363. let secretKey = _key.toString().trim().toLowerCase();
  364. //拼接数据头
  365. let sequenceId_16 = dataTransition.getSequenceId(_sequenceId);
  366. _sequenceId++;
  367. let c = secretKey.toString().replace(/\s+/g, "");
  368. let cLength = dataTransition.getSecretKeyLength(c);
  369. //发送内容
  370. let sendValue = `02 00 01 ${cLength}`; //02 连接命令 01连接请求 cLength秘钥长度。
  371. let allData = `${sendValue} ${secretKey}`;
  372. let header = dataTransition.header(allData, 0, '00', sequenceId_16);
  373. let data = header + allData.replace(/\s+/g, "");
  374. this.log('发送的连接数据:', data);
  375. _sendCtrl(data);
  376. }
  377. //发送指令。判断是否分包发送数据
  378. const _sendCtrl = (data) => {
  379. //保存一下发送的数据
  380. _sendData = data;
  381. //如果大于20个字节则分包发送,两个字符一个字节
  382. let dataLen = Math.ceil(data.length / 40);
  383. if (dataLen > 1) { //3
  384. for (let i = 0; i < data.length; i += 40) {
  385. let value = dataTransition.hexStringToArrayBuffer(data.slice(i, i + 40));
  386. this.log("分包发送的数据", data.slice(i, i + 40))
  387. _writeBLECharacteristicValue(value);
  388. }
  389. } else {
  390. let value = dataTransition.hexStringToArrayBuffer(data);
  391. _writeBLECharacteristicValue(value);
  392. }
  393. }
  394. //发送信息
  395. const _writeBLECharacteristicValue = (value,cb) => {
  396. setTimeout(() => {
  397. my.writeBLECharacteristicValue({
  398. deviceId: _deviceId,
  399. serviceId: _serviceId,
  400. characteristicId: _characteristicId_write,
  401. // 这里的value是ArrayBuffer类型
  402. value: value,
  403. success: (res) => {
  404. this.log('发送信息成功', res.errMsg);
  405. cb && cb();
  406. },
  407. fail: (err) => {
  408. this.log('writeBLECharacteristicValue error ', err.errMsg);
  409. let code = err.errCode;
  410. if (code == 10006 || code == 10000) { //连接断开
  411. _startConnectDevices();
  412. } else if (code == 10008) {
  413. this.log('重发数据', dataTransition.ab2hex(value));
  414. _writeBLECharacteristicValue(value);
  415. } else {
  416. util.showModal_nocancel('数据发送失败,请重试。');
  417. this.end(() => {
  418. _callBack && _callBack(false);
  419. });
  420. }
  421. }
  422. })
  423. }, 200);
  424. }
  425. //监听事件开启
  426. const _notifyBLECharacteristicValueChange = (cb) => {
  427. my.notifyBLECharacteristicValueChange({
  428. state: true,
  429. deviceId: _deviceId,
  430. serviceId: _serviceId,
  431. characteristicId: _characteristicId_notify,
  432. success: () => {
  433. if (_listenerTime != -1){ //超时安全判断
  434. _listenerTimer = setTimeout(() => {
  435. if (_listenerTime == 0) {
  436. this.log('未接收到回复信息!自动重发一次!');
  437. _listenerTime++;
  438. _connectCtrl();
  439. } else {
  440. my.hideToast();
  441. my.hideLoading();
  442. my.confirm({
  443. content: '未接收到回复信息!',
  444. confirmText: '重试',
  445. success: (res) => {
  446. if (res.confirm==true) {
  447. my.showToast({
  448. content: '请稍后',
  449. icon: 'loading',
  450. mask: true,
  451. duration: 100000
  452. })
  453. _connectCtrl();
  454. } else {
  455. this.end(() => {
  456. _callBack && _callBack(false);
  457. });
  458. }
  459. }
  460. })
  461. }
  462. }, 5000)
  463. }
  464. my.onBLECharacteristicValueChange((res) => {
  465. clearTimeout(_listenerTimer);
  466. _listenerTime = -1;
  467. let data = dataTransition.ab2hex(res.value)
  468. this.log('********notify收到的数据:', data);
  469. if(data.slice(0,4) == 'aa10'){
  470. this.log('指令发送成功:');
  471. } else if (data.slice(0, 4) == 'aa30') {
  472. this.log('CRC校验失败');
  473. util.showModal_nocancel('CRC校验失败,请重试。');
  474. this.end(() => {
  475. _callBack && _callBack(false);
  476. });
  477. //end
  478. } else if (data.slice(0, 3) == 'aa0' && _dataLen == 0){
  479. //设备版本号
  480. _machineVerson = data.slice(2,4);
  481. //16进制流水号
  482. _sequenceId_16 = data.slice(6, 8); //0a
  483. //计算数据包长度
  484. _dataLen = parseInt(data.slice(8, 12), 16); //003e,16=62
  485. //计算systemState
  486. _systemState = data.slice(4, 6); //4c
  487. _analysisSystem(_systemState);
  488. //crc
  489. _CRC16 = data.slice(12, 16); //290e
  490. this.log("需要接收的字节长度", _dataLen);
  491. if (data.length > 16) {
  492. _connectData(data.slice(16))
  493. }
  494. } else {
  495. if (_dataLen > 0) {
  496. _connectData(data)
  497. }
  498. }
  499. })
  500. cb && cb();
  501. },
  502. fail: (err) => {
  503. this.log('notifyBLECharacteristicValueChange', err.errMsg);
  504. util.showModal_nocancel('特征值监听开启失败,请重试。')
  505. this.end(() => {
  506. _callBack && _callBack(false);
  507. });
  508. }
  509. })
  510. }
  511. //解析存储车辆状态
  512. const _analysisSystem = (systemState) => {
  513. //16进制转换为10进制
  514. let decimalState = parseInt(systemState,16);
  515. //10进制转换为2进制
  516. let binaryState = parseInt(decimalState).toString(2);
  517. if (binaryState.length < 8){
  518. let supplyNum = 8 - binaryState.length;
  519. while(supplyNum > 0){
  520. binaryState = '0' + binaryState;
  521. supplyNum--;
  522. }
  523. }
  524. //字符串拆分成为数组
  525. let stateArray = Array.prototype.slice.call(binaryState);
  526. _machineState = stateArray;
  527. console.log(stateArray);
  528. }
  529. //拼接数据,判断数据并发送
  530. const _connectData = (data) => {
  531. this.log('拼接内容:',data);
  532. _dataContent += data;
  533. this.log('内容长度', _dataContent.length,'接收到的数据长度', _dataLen,'*2');
  534. if (_dataContent.length == _dataLen * 2) { //接收完该长度的字节和校验CRC成功之后再发送ACK
  535. let dc = _dataContent;
  536. let dcArr = [];
  537. this.log('接收的数据长度字节:', dc.length / 2);
  538. let contentArr = dataTransition.addFlagBeforeArr(dataTransition.strAverage2Arr(dc, 2));
  539. if (parseInt(dataTransition.getCRC16(contentArr), 16) == parseInt(_CRC16, 16)) {
  540. this.log('CRC16校验成功');
  541. let value = dataTransition.hexStringToArrayBuffer(`aa12${_systemState}${_sequenceId_16}00000000`);
  542. this.log(`返回的确认数据${dataTransition.ab2hex(value)}`);
  543. //分析数据返回的内容
  544. _analysisBLEContent(dc,value);
  545. } else {
  546. this.log('CRC16校验失败', dataTransition.getCRC16(contentArr) + "_应为:" + _CRC16);
  547. util.showModal_nocancel('CRC16校验失败,请重试。');
  548. this.end(() => {
  549. _callBack && _callBack(false);
  550. });
  551. //end
  552. }
  553. _dataLen = 0;
  554. _systemState = '';
  555. _dataContent = '';
  556. _sequenceId_16 = '';
  557. _CRC16 = '';
  558. }
  559. }
  560. //解析蓝牙发送内容
  561. const _analysisBLEContent = (content, reply) => {
  562. this.log('解析数据数据***************', content);
  563. if (content.indexOf('020101') > -1) {
  564. if (!_connected) {
  565. _connected = true;
  566. this.log('连接成功');
  567. _writeBLECharacteristicValue(reply, () => {
  568. _ctrl(_operateType);
  569. });
  570. _analysisVoltage(content);
  571. }
  572. } else if (content.indexOf('0300820100') > -1) {
  573. if (_sendCommandTimer) { //每次都将清楚等待任务
  574. clearTimeout(_sendCommandTimer);
  575. _sendCommandTimer = null;
  576. }
  577. if (!_hasReceive) {
  578. _hasReceive = true;
  579. _writeBLECharacteristicValue(reply, () => {
  580. this.log('开锁成功,开始回调ctrl_cb');
  581. this.end(() => {
  582. _callBack && _callBack(true);
  583. });
  584. });
  585. }
  586. } else if (content.indexOf('0300810100') > -1) {
  587. if (_sendCommandTimer) { //每次都将清楚等待任务
  588. clearTimeout(_sendCommandTimer);
  589. _sendCommandTimer = null;
  590. }
  591. if (!_hasReceive) {
  592. _hasReceive = true;
  593. _writeBLECharacteristicValue(reply, () => {
  594. this.log('上锁成功,开始回调ctrl_cb');
  595. this.end(()=>{
  596. _callBack && _callBack(true);
  597. });
  598. });
  599. }
  600. } else if(content.indexOf('0300840100') > -1){
  601. //响铃成功
  602. if (_sendCommandTimer) { //每次都将清楚等待任务
  603. clearTimeout(_sendCommandTimer);
  604. _sendCommandTimer = null;
  605. }
  606. if (!_hasReceive) {
  607. _hasReceive = true;
  608. _writeBLECharacteristicValue(reply, () => {
  609. this.log('响铃成功,开始回调ctrl_cb');
  610. this.end(() => {
  611. _callBack && _callBack(true);
  612. });
  613. });
  614. }
  615. } else if(content.indexOf('0300870100') > -1){
  616. //临时关锁成功
  617. if (_sendCommandTimer) { //每次都将清楚等待任务
  618. clearTimeout(_sendCommandTimer);
  619. _sendCommandTimer = null;
  620. }
  621. if (!_hasReceive) {
  622. _hasReceive = true;
  623. _writeBLECharacteristicValue(reply, () => {
  624. this.log('响铃成功,开始回调ctrl_cb');
  625. this.end(() => {
  626. _callBack && _callBack(true);
  627. });
  628. });
  629. }
  630. } else if(content.indexOf('0300850100') > -1){
  631. //开电池锁成功
  632. if (_sendCommandTimer) { //每次都将清楚等待任务
  633. clearTimeout(_sendCommandTimer);
  634. _sendCommandTimer = null;
  635. }
  636. if (!_hasReceive) {
  637. _hasReceive = true;
  638. _writeBLECharacteristicValue(reply, () => {
  639. this.log('响铃成功,开始回调ctrl_cb');
  640. this.end(() => {
  641. _callBack && _callBack(true);
  642. });
  643. });
  644. }
  645. } else if (content.indexOf('04008524') > -1) {
  646. _writeBLECharacteristicValue(reply, () => {
  647. this.log('心跳包');
  648. });
  649. } else if (content.indexOf('020100') > -1) {
  650. if (_sendCommandTimer) { //每次都将清楚等待任务
  651. clearTimeout(_sendCommandTimer);
  652. _sendCommandTimer = null;
  653. }
  654. this.log('鉴权失败:', _sendData);
  655. util.showModal_nocancel('鉴权失败!')
  656. this.end(()=>{
  657. _callBack && _callBack(false);
  658. });
  659. //end
  660. } else {
  661. if (_sendCommandTimer) { //每次都将清楚等待任务
  662. clearTimeout(_sendCommandTimer);
  663. _sendCommandTimer = null;
  664. }
  665. this.end(() => {
  666. let text = content === '0300810102' ? '运动中不能上锁!' : '蓝牙操作失败,请重试!';
  667. this.log(text)
  668. my.showToast({
  669. content: text,
  670. mask: true,
  671. icon: 'none',
  672. duration: 5000
  673. })
  674. _callBack && _callBack(false);
  675. })
  676. }
  677. }
  678. const _analysisVoltage = (content) => {
  679. //判断81 :终端电池电压
  680. if (content.indexOf('02010181') > -1){
  681. //这之后两位表示电池电压:81,两位表示长度:02,加上020101共十位
  682. let startN = content.indexOf('020101') + 10;
  683. //后四位表示电压值:16进制
  684. let voltageData = content.slice(startN, startN + 4);
  685. let voltage = parseInt(voltageData,16);
  686. if(_machineVerson == '02')
  687. _machinevoltage = voltage * 10;
  688. else
  689. _machinevoltage = voltage;
  690. }
  691. }
  692. //指令
  693. const _ctrl = (type) => {
  694. let sequenceId_16 = dataTransition.getSequenceId(_sequenceId);
  695. _sequenceId++;
  696. let sendData = '';
  697. if (type === 'open') //<aa02000b 00057edb 03000201 00 >
  698. sendData = '03 00 02 01 00';
  699. else if (type === 'close') //<aa02000c 00058036 03000101 01 >
  700. sendData = '03 00 01 01 01';
  701. else if (type === 'bell') //<aa02000c 00058036 03000101 01 >
  702. sendData = '03 00 04 01 01';
  703. else if (type === 'batteryOpen') //<aa02000c 00058036 03000101 01 >
  704. sendData = '03 00 05 01 01';
  705. else if (type === 'temporaryClose') //<aa02000c 00058036 03000101 01 >
  706. sendData = '03 00 01 01 30';
  707. else if (type === 'temporaryOpen') //<aa02000c 00058036 03000101 01 >
  708. sendData = '03 00 01 01 31';
  709. let header = dataTransition.header(sendData, 0, '00', sequenceId_16);
  710. let data = header + sendData.replace(/\s+/g, "");
  711. this.log(`发送${type}指令`, data);
  712. _sendCtrl(data);
  713. _sendCommandTimer = setTimeout(()=>{ //可能出现发送消息后没有收到应答,将再次发送
  714. if (_sendCommandTime == 0) {
  715. this.log('设备未响应,自动重发')
  716. _sendCommandTime++;
  717. _ctrl(_operateType);
  718. }else{
  719. this.log('设备未响应')
  720. my.hideLoading();
  721. util.showModal('设备未响应,是否重新发送指令?', () => {
  722. this.log('手动重发ctrl')
  723. my.showLoading({
  724. content: '开锁中',
  725. })
  726. _ctrl(_operateType);
  727. },() => {
  728. this.end(()=>{
  729. _callBack && _callBack(false);
  730. });
  731. })
  732. }
  733. },5000)
  734. }
  735. const _stopBluetoothDevicesDiscovery = () => {
  736. my.stopBluetoothDevicesDiscovery({
  737. success: (res) => {
  738. this.log('停止搜寻附近的蓝牙外围设备');
  739. },
  740. fail: (err) => {
  741. this.log(err.errMsg);
  742. }
  743. })
  744. }
  745. const _closeBluetoothAdapter = () => {
  746. my.closeBluetoothAdapter({
  747. success: (res) => {
  748. this.log('关闭蓝牙适配器')
  749. },
  750. fail: (err) => {
  751. this.log(err.errMsg);
  752. }
  753. })
  754. }
  755. const _initBluetooth = (cb) => {
  756. my.openBluetoothAdapter({
  757. success: (res) => {
  758. },
  759. fail: (err) => {
  760. this.log('initBluetooth:', err.errMsg);
  761. my.showToast({
  762. content: '蓝牙初始化失败',
  763. icon: 'none',
  764. })
  765. },
  766. complete: () => {
  767. cb && cb();
  768. }
  769. })
  770. }
  771. this.log = (...str) => {
  772. let now = new Date();
  773. now = util.formatTime(now)
  774. console.log(now , ...str);
  775. _logList.push(str.join(','))
  776. }
  777. }
  778. module.exports = BluetoothOperate