選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. var WCDBluetooth = require('./WDObuDataUtil.js');
  2. var result = [];
  3. var deviceInfo = {
  4. adviceId: "",//nw 90D0964C-064F-4781-CD75-1A3CFEBE18DF
  5. services: [],
  6. discoveryTimeout: 60000,
  7. connectTimeout: 20000,
  8. sendTimeout: 10000,
  9. delayTime: 1000,
  10. accTimeout: 200,
  11. success: function success(res) { },
  12. fail: function fail(res) { },
  13. complete: function complete(res) { },
  14. srv_uuid: "0000FEE7-0000-1000-8000-00805F9B34FB",
  15. chr_write_uuid: "0000fec7-0000-1000-8000-00805f9b34fb",
  16. chr_indicate_uuid:"0000fec8-0000-1000-8000-00805f9b34fb",
  17. chr_read_uuid: "0000fec9-0000-1000-8000-00805f9b34fb",
  18. localLog: false,
  19. callback_0 : function callback_0 (res){}
  20. };
  21. var preventMultipleClicks = false;
  22. /**
  23. * 链接
  24. */
  25. function connectDevice(device, callback, callback_0) {
  26. deviceInfo.adviceId = device.deviceId
  27. WCDBluetooth.createBLEConnection(Object.assign(deviceInfo,
  28. {
  29. success: function (res) {
  30. WCDBluetooth.setConnectingState(false);
  31. callback({
  32. code: 0,
  33. data: [],
  34. msg: "链接成功",
  35. })
  36. },
  37. fail: function (error) {
  38. WCDBluetooth.setConnectingState(false);
  39. callback({
  40. code: 1,
  41. data: [],
  42. msg: "连接失败",
  43. })
  44. }
  45. }
  46. ), callback_0);
  47. }
  48. /**
  49. * 断开连接
  50. */
  51. function disconnectDevice(params){
  52. WCDBluetooth.disconnectBleDevice(params);
  53. }
  54. /**
  55. * 检查设备是否处于连接状态
  56. */
  57. function checkConnect(){
  58. return WCDBluetooth.isConnectionStateChange();
  59. }
  60. /**
  61. * 发送明文指令 操作通道
  62. * cn 通道号 0: PICC通道 1:ESAM通道
  63. * requestData 需要发送的数据
  64. */
  65. function transCmd(cmdArray, cmdType, callback_1) {
  66. console.log("开始发送指令")
  67. if (!isEven(cmdArray, callback_1)) {
  68. return null
  69. }
  70. if (checkConnect() != 0) {
  71. callback_1({
  72. code: 1,
  73. data :[],
  74. msg: "由于设备未连接导致发送指令失败'"
  75. })
  76. return null
  77. }
  78. if (cmdArray.length == 0) {
  79. console.log("发送的指令", cmdArray)
  80. callback_1({
  81. code: 1,
  82. data: [],
  83. msg: "发送指令为空"
  84. })
  85. return null;
  86. }
  87. result = []
  88. let cmdList = new Array();
  89. let list = new Array();
  90. for (let i = 0; i < cmdArray.length; i++) {
  91. let cmd = "";
  92. if (cmdType == "10") {
  93. cmd = "a300"; //picc签名通道指令
  94. } else {
  95. cmd = "a700"; //esam签名通道指令
  96. }
  97. let tlv = organizationTLV(cmdArray[i]);
  98. let tlvLen = numberToHexString(tlv.length / 2, 2, false);
  99. cmd = cmd + tlvLen + tlv;
  100. console.log("需要发送的明文数据为:" + cmd);
  101. cmdList.push(cmd)
  102. }
  103. WCDBluetooth.transCmd(cmdList[0], function success(res) {
  104. if (res == undefined) return
  105. let rData = WCDBluetooth.bytes2HexStr(res.slice(5));
  106. let rapdu = analysisTLV(rData);
  107. result.push(rapdu)
  108. if (cmdArray.length > 1) {
  109. send(cmdList, 0, callback_1, rapdu)
  110. } else {
  111. callback_1({
  112. code: 0,
  113. data: result,
  114. msg: "发送指令成功",
  115. })
  116. }
  117. }, function fail(res) {
  118. callback_1({
  119. code: 1,
  120. data :[],
  121. msg: res.msg,
  122. });
  123. });
  124. }
  125. function send(cmdList, flag, callback, data) {
  126. flag++
  127. WCDBluetooth.transCmd(cmdList[flag], function success(res) {
  128. if (res != undefined) {
  129. let rData = WCDBluetooth.bytes2HexStr(res.slice(5));
  130. let rapdu = analysisTLV(rData);
  131. result.push(rapdu)
  132. if (flag < cmdList.length - 1) {
  133. send(cmdList, flag, callback, rapdu)
  134. } else {
  135. callback({
  136. code: 0,
  137. data: result,
  138. msg: "发送指令成功",
  139. });
  140. }
  141. }
  142. }, function fail(res) {
  143. callback({
  144. code: 1,
  145. data : [],
  146. msg: res.msg,
  147. })
  148. });
  149. }
  150. function checkParams(params) {
  151. var dict = {
  152. errMsg: "",
  153. errCode: 0
  154. };
  155. if (!checkConnect) {
  156. dict = {
  157. errMsg: "设备未连接,请检查设备是否正常",
  158. errCode: -1
  159. };
  160. return dict
  161. }
  162. //判断命令代码是否为空
  163. if (params.cn.length == 0 ||
  164. params.cn == null) {
  165. console.log("命令通道为空,发送失败");
  166. dict = {
  167. errMsg: "命令通道为空,发送失败",
  168. errCode: -1
  169. };
  170. return dict
  171. }
  172. //检查 发送的数据指令是否为空
  173. if (params.requestData[0].length == 0 ||
  174. params.requestData[0] == null) {
  175. console.log("数据指令为空,发送失败");
  176. dict = {
  177. errMsg: "数据指令为空,发送失败",
  178. errCode: -1
  179. };
  180. return dict
  181. }
  182. //校验数据格式是否正确
  183. for (let i = 0; i < params.requestData[0].length; i++) {
  184. let c = params.requestData[0].charAt(i);
  185. if (!((c >= '0' && c <= '9') ||
  186. (c >= 'a' && c <= 'f') ||
  187. (c >= 'A' && c <= 'F'))) {
  188. console.log("c发送数据出错,发送失败");
  189. dict = {
  190. errMsg: "发送数据出错,发送失败",
  191. errCode: -1
  192. };
  193. return dict
  194. }
  195. }
  196. return dict;
  197. }
  198. /**
  199. * 将外部传入的指令转换成tlv格式的指令. 返回apdu字符串
  200. */
  201. function organizationTLV(command) {
  202. console.log("需要组包的指令 == " + command);
  203. //获取指令数据
  204. var apduArrs = new Array(0);
  205. apduArrs.push(command);
  206. // for (let i = 0; i < command.length;i++){
  207. // console.log("循环 == " + command[i]);
  208. //
  209. // }
  210. //tlv字符串
  211. let tlv = "";
  212. console.log("apduArrs.length = " + apduArrs.length);
  213. for (let i = 0; i < apduArrs.length; i++) {
  214. //获取单条apdu指令
  215. let v = apduArrs[i];
  216. console.log("v === " + v);
  217. //设置t
  218. let t = numberToHexString(i + 1, 1, false);
  219. console.log("t === " + t);
  220. //获取单条apdu指令长度
  221. let l = numberToHexString(v.length / 2, 1, false);
  222. console.log("l === " + l);
  223. //拼接t l v 组成所需tlv格式的16进制字符串
  224. tlv = tlv + t + l + v;
  225. }
  226. console.log("tlv === " + tlv);
  227. //获取tlv格式apdu总长度
  228. let tlvLen = tlv.length / 2;
  229. let index = 1;
  230. //获取16进制总长度
  231. let hexTlvLen = numberToHexString(tlvLen, index, false);
  232. console.log("hexTlvLen === " + hexTlvLen);
  233. while (tlvLen != parseInt(hexTlvLen, 16)) {
  234. index++;
  235. hexTlvLen = numberToHexString(tlvLen, index, false);
  236. }
  237. if (tlvLen > 0x80) {
  238. let head = 0x80 + hexTlvLen.length / 2;
  239. console.log("head === " + head + "hexTlvLen.length/2 === " + hexTlvLen.length/2);
  240. let hexHead = numberToHexString(head, 1, false);
  241. hexTlvLen = hexHead + hexTlvLen;
  242. }
  243. console.log("cmd === " + '80' + hexTlvLen + tlv);
  244. return '80' + hexTlvLen + tlv;
  245. }
  246. // number转换成指定字节数的hexString
  247. // num:要转换的数(number) bitNum:转换后的字节数(number) isBig:是不是大端模式(boolean)
  248. function numberToHexString(num, bitNum, isBig) {
  249. // 转大端hex并补足
  250. let hex = num.toString(16);
  251. for (let i = hex.length; i < bitNum * 2; i++) {
  252. hex = '0' + hex;
  253. }
  254. // 多位截取
  255. if (hex.length > bitNum * 2) {
  256. hex = hex.substring(hex.length - bitNum * 2);
  257. }
  258. // 转小端
  259. if (isBig == false) {
  260. let temp = '';
  261. for (let i = hex.length - 2; i >= 0; i -= 2) {
  262. temp = temp + hex.substring(i, i + 2);
  263. }
  264. hex = temp;
  265. }
  266. return hex;
  267. }
  268. function analysisTLV(command){
  269. //console.log("开始解析tlv",command)
  270. let apdus = new Array();
  271. let totalLength = parseInt(command.substring(2, 4), 16);
  272. let offset = 4;
  273. if (totalLength > 0x80) {
  274. offset = offset + (totalLength - 0x80) * 2;
  275. console.log("大于了")
  276. }
  277. while (offset < command.length) {
  278. //获取t
  279. let t = command.substring(offset, offset + 2);
  280. offset += 2;
  281. //获取单条指令的长度
  282. let l = command.substring(offset, offset + 2);
  283. let len = parseInt(l, 16);
  284. offset += 2;
  285. //获取v
  286. let v = command.substring(offset, offset + len * 2);
  287. offset += len * 2;
  288. apdus.push(v);
  289. }
  290. // let r_cmd = numberToHexString(apdus.length, 1, false);
  291. let r_cmd = "";
  292. for (let i = 0; i < apdus.length; i++) {
  293. let cmd = apdus[i];
  294. let cmdLen = numberToHexString(cmd.length / 2, 1, false);
  295. // r_cmd = r_cmd + cmdLen + cmd;
  296. r_cmd = cmd;
  297. }
  298. return r_cmd;
  299. }
  300. function scan() {
  301. console.log('扫描蓝牙中');
  302. foundDevices = [];
  303. uni.closeBluetoothAdapter();
  304. uni.openBluetoothAdapter({
  305. success: function (res) {
  306. uni.startBluetoothDevicesDiscovery({
  307. services: [],
  308. success: function (res) {
  309. //扫描结果的监听
  310. uni.onBluetoothDeviceFound(function (res) {
  311. var name = res.devices[0]['name'];
  312. var deviceId = res.devices[0]['deviceId'];
  313. if (name != '' && name != undefined && name != 'undefined') {
  314. var prefixName = name.substring(0, 2);
  315. prefixName = prefixName.toUpperCase();
  316. if (prefixName == 'WJ' || prefixName == 'JL' || prefixName == 'JY' || prefixName == 'ZJ' || prefixName == 'WQ' || prefixName == 'HN' || prefixName == 'WD') {
  317. clearTimeout(scanTimeout);
  318. uni.stopBluetoothDevicesDiscovery({
  319. success: function (res) {
  320. device = {};
  321. device.name = name;
  322. device.deviceId = deviceId;
  323. device.prefixName = prefixName;
  324. connectPrefixName = device.prefixName;
  325. console.log(device)
  326. delete device.prefixName
  327. //去连接
  328. },
  329. });
  330. }
  331. }
  332. });
  333. },
  334. fail: function (res) {
  335. console.log(res)
  336. }
  337. });
  338. scanTimeout = setTimeout(function () {
  339. uni.closeBluetoothAdapter();
  340. console.log('扫描蓝牙超时,未找到设备,请打开设备蓝牙')
  341. console.log('scan timeout');
  342. }, 50000);
  343. },
  344. fail: function (res) {
  345. console.log(res);
  346. //alertF('手机蓝牙未打开或不支持蓝牙');
  347. }
  348. })
  349. }
  350. function isEven(cmdArray, callback) {
  351. let result = false
  352. let flag = true
  353. let lengthCmd = 0;
  354. while (flag)
  355. {
  356. if (cmdArray.length == lengthCmd) {
  357. flag = false
  358. break
  359. }
  360. console.log(cmdArray[lengthCmd], cmdArray[lengthCmd] == undefined, cmdArray.length)
  361. if (cmdArray[lengthCmd] == null || cmdArray[lengthCmd] == undefined || cmdArray.length <= 0){
  362. callback({
  363. code: 1,
  364. data: [],
  365. msg: "指令为空"
  366. })
  367. return
  368. }
  369. lengthCmd++
  370. }
  371. for (let i = 0; i < cmdArray.length; i++) {
  372. if (cmdArray[i].length % 2 == 0) {
  373. result = true
  374. } else {
  375. // 奇数
  376. callback({
  377. code: 1,
  378. data:[],
  379. msg: "由于指令" + cmdArray[i] + "错误导致失败发送ICC指令失败"
  380. })
  381. return false
  382. }
  383. }
  384. return result
  385. }
  386. module.exports = {
  387. connectDevice: connectDevice,
  388. disconnectDevice: disconnectDevice,
  389. checkConnect: checkConnect,
  390. transCmd: transCmd,
  391. organizationTLV: organizationTLV,
  392. analysisTLV: analysisTLV,
  393. scan, scan
  394. }