bluetoolth.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. /**
  2. * @export
  3. * @param {string} name 微信api的名称 ,如 uniAsyncPromise("getSystemInfo",options)
  4. * @param {object} options 除了success 和 fail 的其他参数
  5. * @returns
  6. */
  7. export function uniAsyncPromise(name, options) {
  8. return new Promise((resolve, reject) => {
  9. uni[name]({
  10. ...(options || {}),
  11. success: (res) => {
  12. resolve(res);
  13. // console.log('成功')
  14. num = 0
  15. },
  16. fail: (err) => {
  17. reject(err, '查询失败原因');
  18. }
  19. });
  20. });
  21. }
  22. //微信小程序向蓝牙打印机发送数据进行打印的坑:
  23. //小程序api向蓝牙打印机发送数据打印,发送的任何内容都应该要转成二进制数据,而且蓝牙打印的文本编码是GBK的,发送中文需转成GBK编码再转成二进制数据发送
  24. //发送打印机指令也要转成二进制数据发送
  25. //蓝牙打印机一次接收的二级制数据有限制,不同的系统不同的蓝牙设备限制可能不同,微信建议一次20个字节,需做递归分包发送
  26. //发送完要打印的内容后,一定要发送一个打印的指令才能顺利打印 (有些指令就不需要)
  27. //一、初始化蓝牙、开始检索蓝牙设备
  28. // { allowDuplicatesKey: true, interval: 500}
  29. export function openBlue() {
  30. return uniAsyncPromise('openBluetoothAdapter')
  31. }
  32. export function startBluetoothDevicesDiscovery(option) {
  33. // console.log('开始蓝牙扫描');
  34. uniAsyncPromise('startBluetoothDevicesDiscovery', option).then((res) => {
  35. // console.log('正在搜寻蓝牙设备', res);
  36. });
  37. }
  38. export function getConnectedBluetoothDevices(option) {
  39. // console.log('开始获取已连接设备');
  40. return uniAsyncPromise('getConnectedBluetoothDevices', option)
  41. }
  42. //二、
  43. /**
  44. *
  45. *
  46. * @export
  47. * @param {function} getDevices uni.getBluetoothDevices的监听回调函数
  48. */
  49. export function onfindBlueDevices(getDevices) {
  50. //监听寻找到新设备的事件
  51. uni.onBluetoothDeviceFound((devices) => {
  52. //获取在蓝牙模块生效期间所有已发现的蓝牙设备
  53. uniAsyncPromise('getBluetoothDevices').then((res) => {
  54. getDevices && getDevices(res.devices);
  55. });
  56. });
  57. }
  58. /**
  59. * @export
  60. * @param {function} stopBlueDevicesDiscovery 关闭蓝牙扫描
  61. */
  62. export function stopBlueDevicesDiscovery() {
  63. //监听寻找到新设备的事件
  64. console.log('停止蓝牙扫描');
  65. return uniAsyncPromise('stopBluetoothDevicesDiscovery').then((res) => {
  66. console.log('停止搜寻蓝牙设备', res);
  67. });
  68. }
  69. //三、连接蓝牙设备
  70. /**
  71. * @export
  72. * @param {function} createBLEConnection
  73. * @param {number} deviceId 蓝牙设备id
  74. */
  75. export function createBLEConnection(deviceId, sucess, fail) {
  76. //连接蓝牙设备
  77. console.log('连接蓝牙设备', deviceId);
  78. uniAsyncPromise("createBLEConnection", {
  79. deviceId
  80. })
  81. .then(res => {
  82. //连接成功可选择停止搜索蓝牙
  83. //stopBlueDevicesDiscovery();
  84. console.log('连接成功');
  85. sucess && sucess({
  86. res: res,
  87. });
  88. })
  89. .catch(res => {
  90. console.log('连接设备异常' + res);
  91. fail && fail({
  92. res: res,
  93. });
  94. })
  95. /*.finally(res=>{
  96. console.log('连接成功');
  97. sucess && sucess({
  98. res: res,
  99. });
  100. });*/
  101. }
  102. export function closeBLEConnection(deviceId) {
  103. console.log('断开蓝牙设备', deviceId);
  104. uniAsyncPromise("closeBLEConnection", {
  105. deviceId
  106. })
  107. .then(res => {
  108. console.log('BLEDisconnect complete', res);
  109. })
  110. .catch(res => {
  111. console.log('断开设备异常' + res);
  112. })
  113. /*.finally(res=>{
  114. console.log('BLEDisconnect complete', res);
  115. }); */
  116. }
  117. //四、连接成功后, 获取蓝牙设备的service服务
  118. // uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})
  119. export function getBLEDeviceServices(deviceId, success, fail) {
  120. console.log('获取ServiceId', deviceId);
  121. //加延迟避免取不到service
  122. setTimeout(() => {
  123. uniAsyncPromise("getBLEDeviceServices", {
  124. deviceId: deviceId
  125. })
  126. .then(res => {
  127. console.log('服务', res);
  128. success && success({
  129. serviceId: res.services,
  130. });
  131. })
  132. .catch((res) => {
  133. //getBLEDeviceServices(deviceId, success, fail);
  134. console.log('获取ServiceId异常' + res);
  135. fail && fail({
  136. res: res,
  137. });
  138. });
  139. }, 1000)
  140. }
  141. //五、获取的service服务可能有多个,递归获取特征值(最后要用的是能读,能写,能监听的那个值的uuid作为特征值id)
  142. /**
  143. *
  144. *
  145. * @export
  146. * @param {number} deviceId 蓝牙设备id
  147. * @param {array} services uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})获取的res.services
  148. * @param {function} success 成功取得有用特征值uuid的回调函数
  149. */
  150. export function getDeviceCharacteristics(deviceId, services, success, fail) {
  151. //services = services.slice(0);
  152. console.log('获取Characteristics', deviceId, services);
  153. if (services.length) {
  154. const serviceId = services.shift().uuid;
  155. console.log('ServceID ', serviceId);
  156. uniAsyncPromise('getBLEDeviceCharacteristics', {
  157. deviceId,
  158. serviceId,
  159. })
  160. .then((res) => {
  161. console.log('getBLEDeviceCharacteristics', deviceId, serviceId, res);
  162. let finished = false;
  163. let write = false;
  164. let notify = false;
  165. let indicate = false;
  166. var readId;
  167. var writeId;
  168. //有斑马品牌的一款打印机中res.characteristics的所有uuid都是相同的,找所有的properties存在(notify || indicate) && write这种情况就说明这个uuid是可用的(不确保所有的打印机都能用这种方式取得uuid,在主要测试得凯盛诺打印机res.characteristic只有一个uuid,所以也能用这个方式)
  169. for (var i = 0; i < res.characteristics.length; i++) {
  170. if (!notify) {
  171. notify = res.characteristics[i].properties.notify;
  172. if (notify) readId = res.characteristics[i].uuid;
  173. }
  174. if (!indicate) {
  175. indicate = res.characteristics[i].properties.indicate;
  176. if (indicate) readId = res.characteristics[i].uuid;
  177. }
  178. if (!write) {
  179. write = res.characteristics[i].properties.write;
  180. writeId = res.characteristics[i].uuid;
  181. }
  182. if ((notify || indicate) && write) {
  183. /* 获取蓝牙特征值uuid */
  184. success &&
  185. success({
  186. serviceId,
  187. writeId: writeId,
  188. readId: readId,
  189. });
  190. finished = true;
  191. break;
  192. }
  193. }
  194. if (!finished) {
  195. getDeviceCharacteristics(deviceId, services, success, fail);
  196. }
  197. })
  198. .catch((res) => {
  199. getDeviceCharacteristics(deviceId, services, success, fail);
  200. });
  201. } else {
  202. fail && fail();
  203. }
  204. }
  205. //六、启动notify 蓝牙监听功能 然后使用 uni.onBLECharacteristicValueChange用来监听蓝牙设备传递数据
  206. /**
  207. * @export
  208. * @param {object} options
  209. * {
  210. deviceId,//蓝牙设备id
  211. serviceId,//服务id
  212. characteristicId,//可用特征值uuid
  213. }
  214. * @param {function} onChange 监听蓝牙设备传递数据回调函数
  215. */
  216. export function onGetBLECharacteristicValueChange(options, onChange = function() {}) {
  217. console.log('deviceId ', options.deviceId);
  218. console.log('serviceId ', options.serviceId);
  219. console.log('characteristicId ', options.characteristicId);
  220. uniAsyncPromise('notifyBLECharacteristicValueChange', {
  221. state: true,
  222. ...options,
  223. }).then((res) => {
  224. console.log('onBLECharacteristicValueChange ');
  225. uni.onBLECharacteristicValueChange(onChange);
  226. });
  227. }
  228. //七、发送数据(递归分包发送)
  229. /**
  230. * @export
  231. * @param {object} options
  232. * {
  233. deviceId,
  234. serviceId,
  235. characteristicId,
  236. value [ArrayBuffer],
  237. lasterSuccess,
  238. onceLength
  239. }
  240. */
  241. var num = 0
  242. var number = 0
  243. var totalNum = 0
  244. var totalValue
  245. export function sendDataToDevice(options) {
  246. if (number == 0) {
  247. uni.showLoading({
  248. title: '打印中,请稍等',
  249. mask: true,
  250. });
  251. number++
  252. totalNum = options.value.byteLength;
  253. }
  254. // console.log(options, '查询学习学习')
  255. let byteLength = options.value.byteLength;
  256. let totalValue = options.value
  257. // console.log('當前', byteLength, totalNum, '初始数值')
  258. //这里默认一次20个字节发送
  259. const speed = options.onceLength; //20;
  260. if (byteLength > 0) {
  261. setTimeout(() => {
  262. uniAsyncPromise('writeBLECharacteristicValue', {
  263. ...options,
  264. value: options.value.slice(0, byteLength > speed ? speed : byteLength),
  265. })
  266. .then((res) => {
  267. // console.log('打印继续=================', res, speed, byteLength);
  268. if (byteLength > speed) {
  269. num = 0
  270. sendDataToDevice({
  271. ...options,
  272. value: options.value.slice(speed, byteLength),
  273. });
  274. } else {
  275. num = 0
  276. uni.showToast({
  277. title: '打印完成',
  278. icon: 'none',
  279. duration: 2000
  280. })
  281. number = 0
  282. }
  283. })
  284. .catch((res) => {
  285. if (num != 15) {
  286. var data = {
  287. ...options,
  288. }
  289. sendDataToDevice({
  290. ...data,
  291. value: totalValue,
  292. // value: options.value.slice(speed,parseInt(byteLength)+parseInt(speed)*5),
  293. });
  294. console.log(res, '失败重新打印原因', options.value.slice(speed, byteLength), speed,
  295. byteLength);
  296. num++
  297. } else {
  298. num = 0
  299. uni.showToast({
  300. title: '打印失败请检查蓝牙连接状态或打印机状态',
  301. icon: 'none',
  302. duration: 2000
  303. })
  304. number = 0
  305. }
  306. });
  307. }, 100)
  308. }
  309. }
  310. export function charToArrayBuffer(str) {
  311. var out = new ArrayBuffer(str.length);
  312. var uint8 = new Uint8Array(out);
  313. var strs = str.split('');
  314. for (var i = 0; i < strs.length; i++) {
  315. uint8[i] = strs[i].charCodeAt();
  316. }
  317. return uint8;
  318. }
  319. export function charToArray(str) {
  320. var arr = [];
  321. var strs = str.split('');
  322. for (var i = 0; i < strs.length; i++) {
  323. arr[i] = strs[i].charCodeAt();
  324. }
  325. return arr;
  326. }
  327. //打印二维码
  328. /**
  329. * @export
  330. * @param {object} options
  331. * {
  332. deviceId,
  333. serviceId,
  334. characteristicId,
  335. value,//ArrayBuffer:二维码的数据
  336. }
  337. */
  338. export function printQR(options) {
  339. //打印二维码的十进制指令data:
  340. let data = [29, 107, 97, 7, 4, options.value.byteLength, 0];
  341. sendDataToDevice({
  342. ...options,
  343. value: new Uint8Array(data).buffer,
  344. lasterSuccess: () => {
  345. //指令发送成功后,发送二维码的数据
  346. sendDataToDevice(options);
  347. },
  348. });
  349. }
  350. function grayPixle(pix) {
  351. return pix[0] * 0.299 + pix[1] * 0.587 + pix[2] * 0.114;
  352. }
  353. export function overwriteImageData(data) {
  354. let sendWidth = data.width,
  355. sendHeight = data.height;
  356. const threshold = data.threshold || 180;
  357. let sendImageData = new ArrayBuffer((sendWidth * sendHeight) / 8);
  358. sendImageData = new Uint8Array(sendImageData);
  359. let pix = data.imageData;
  360. const part = [];
  361. let index = 0;
  362. for (let i = 0; i < pix.length; i += 32) {
  363. //横向每8个像素点组成一个字节(8位二进制数)。
  364. for (let k = 0; k < 8; k++) {
  365. const grayPixle1 = grayPixle(pix.slice(i + k * 4, i + k * 4 + (4 - 1)));
  366. //阈值调整
  367. if (grayPixle1 > threshold) {
  368. //灰度值大于threshold位 白色 为第k位0不打印
  369. part[k] = 0;
  370. } else {
  371. part[k] = 1;
  372. }
  373. }
  374. let temp = 0;
  375. for (let a = 0; a < part.length; a++) {
  376. temp += part[a] * Math.pow(2, part.length - 1 - a);
  377. }
  378. //开始不明白以下算法什么意思,了解了字节才知道,一个字节是8位的二进制数,part这个数组存的0和1就是二进制的0和1,传输到打印的位图数据的一个字节是0-255之间的十进制数,以下是用权相加法转十进制数,理解了这个就用上面的for循环替代了
  379. // const temp =
  380. // part[0] * 128 +
  381. // part[1] * 64 +
  382. // part[2] * 32 +
  383. // part[3] * 16 +
  384. // part[4] * 8 +
  385. // part[5] * 4 +
  386. // part[6] * 2 +
  387. // part[7] * 1;
  388. sendImageData[index++] = temp;
  389. }
  390. return {
  391. array: Array.from(sendImageData),
  392. width: sendWidth / 8,
  393. height: sendHeight,
  394. };
  395. }
  396. /**
  397. * printImage
  398. * @param {object} opt
  399. * {
  400. deviceId,//蓝牙设备id
  401. serviceId,//服务id
  402. characteristicId,//可用特征值uuid
  403. lasterSuccess , //最后完成的回调
  404. }
  405. */
  406. export function printImage(opt = {}, imageInfo = {}) {
  407. let arr = imageInfo.array,
  408. width = imageInfo.width;
  409. const writeArray = [];
  410. const xl = width % 256;
  411. const xh = width / 256;
  412. //分行发送图片数据,用的十进制指令
  413. const command = [29, 118, 48, 0, xl, xh, 1, 0]; //1D 76 30 00 w h
  414. const enter = [13, 10];
  415. for (let i = 0; i < arr.length / width; i++) {
  416. const subArr = arr.slice(i * width, i * width + width);
  417. const tempArr = command.concat(subArr);
  418. writeArray.push(new Uint8Array(tempArr));
  419. }
  420. writeArray.push(new Uint8Array(enter));
  421. //console.log(writeArray);
  422. const print = (options, writeArray) => {
  423. if (writeArray.length) {
  424. // console.log("send");
  425. sendDataToDevice({
  426. ...options,
  427. value: writeArray.shift().buffer,
  428. lasterSuccess: () => {
  429. if (writeArray.length) {
  430. print(options, writeArray);
  431. } else {
  432. options.lasterSuccess && options.lasterSuccess();
  433. }
  434. },
  435. });
  436. }
  437. };
  438. // console.log("start print");
  439. print(opt, writeArray);
  440. }
  441. /* 16hex insert 0 */
  442. function Hex2Str(num) {
  443. if (num.toString(16).length < 2) return "0" + num.toString(16);
  444. else
  445. return num.toString(16);
  446. }
  447. /*****CPCL指令接口****/
  448. /**
  449. * 配置项如下
  450. * 设置打印纸张的范围
  451. * width: 标签纸的宽度,单位像素點
  452. * height: 标签纸的高度,单位像素點
  453. * 8像素=1mm
  454. * printNum: 打印张数,默认为1
  455. * rotation:页面整体旋转 1-90度 2-180度 3-270度 其他-不旋转
  456. */
  457. export function CreatCPCLPage(width, height, printNum, rotation = 0, offset = 0) {
  458. var strCmd = '! ' + offset + ' 200 200 ' + height + ' ' + printNum + '\n';
  459. strCmd += "PAGE-WIDTH " + width + '\n';
  460. if (rotation == 1)
  461. strCmd += "ZPROTATE90\n";
  462. else if (rotation == 2)
  463. strCmd += "ZPROTATE180\n";
  464. else if (rotation == 3)
  465. strCmd += "ZPROTATE270\n";
  466. else
  467. strCmd += "ZPROTATE0\n";
  468. return strCmd;
  469. }
  470. // * 打印文字
  471. // * x: 文字方块左上角X座标,单位dot
  472. // * y: 文字方块左上角Y座标,单位dot
  473. // * fontName,fontSize: 字体,取值: 參考文檔
  474. // * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
  475. // * content: 文字内容
  476. // */
  477. export function addCPCLText(x, y, fontName, fontSize, rotation, content) {
  478. //console.log(fontName,fontSize,rotation, content);
  479. var strCmd = '';
  480. if (rotation == 1) {
  481. strCmd += 'T90 ';
  482. }
  483. if (rotation == 2) {
  484. strCmd += 'T180 ';
  485. }
  486. if (rotation == 3) {
  487. strCmd += 'T270 ';
  488. } else {
  489. strCmd += 'T ';
  490. }
  491. strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n';
  492. return strCmd;
  493. };
  494. /**
  495. * 打印文字
  496. * x: 文字方块左上角X座标,单位dot
  497. * y: 文字方块左上角Y座标,单位dot
  498. * fontName,fontSize: 字体,取值: 參考文檔
  499. * strCmd += blesdk.addCPCLText(0,0,'4','244',0,'速购速递APP'); //改变默认字体
  500. * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
  501. * content: 文字内容
  502. */
  503. export function addCPCLTextil(x, y, fontName, fontSize, rotation, content) {
  504. //console.log(fontName,fontSize,rotation, content);
  505. const groupedArray = groupStrings(content);
  506. function groupStrings(str, size = 16) {
  507. const result = [];
  508. for (let i = 0; i < str.length; i += size) {
  509. result.push(str.substr(i, size));
  510. }
  511. return result;
  512. }
  513. var strCmd = '';
  514. for (var i in groupedArray) {
  515. if (rotation == 1) {
  516. strCmd += 'T90 ';
  517. } else if (rotation == 2) {
  518. strCmd += 'T180 ';
  519. } else if (rotation == 3) {
  520. strCmd += 'T270 ';
  521. } else if (rotation == 4) {
  522. strCmd += 'VT ';
  523. } else {
  524. strCmd += 'T ';
  525. }
  526. strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + (parseInt(y) + parseInt(i * 30)) + ' ' + groupedArray[i] +
  527. '\n';
  528. }
  529. return strCmd;
  530. };
  531. /**
  532. * 长文本打印
  533. * x: 文字方块左上角X座标,单位dot
  534. * y: 文字方块左上角Y座标,单位dot
  535. * fontName,fontSize: 字体,取值: 參考文檔
  536. * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
  537. * content: 文字内容
  538. */
  539. export function LongText(x, y, fontName, fontSize, rotation, content, nu = 16) {
  540. var num = parseInt(content.length / nu)
  541. var arr = content.split('')
  542. var abb = []
  543. for (var n = 0; n <= num; n++) {
  544. var str = '';
  545. for (var i in arr) {
  546. if (i >= n * nu && i <= (n + 1) * nu) {
  547. str += arr[i]
  548. }
  549. }
  550. abb.push(str)
  551. }
  552. var strCmd = '';
  553. for (var i in abb) {
  554. // console.log(i, num)
  555. if (rotation == 1) {
  556. strCmd += 'T90 ';
  557. }
  558. if (rotation == 2) {
  559. strCmd += 'T180 ';
  560. }
  561. if (rotation == 3) {
  562. strCmd += 'T270 ';
  563. } else {
  564. strCmd += 'T ';
  565. }
  566. if (i != num && num != 0) {
  567. var acc = abb[i].split('')
  568. acc.pop()
  569. abb[i] = acc.join('')
  570. }
  571. strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + (parseInt(y) + parseInt(i * 30)) + ' ' + abb[i] + '\n';
  572. }
  573. return strCmd;
  574. };
  575. /**
  576. * 文本串联
  577. * x: 文字方块左上角X座标,单位dot
  578. * y: 文字方块左上角Y座标,单位dot
  579. * fontName,fontSize: 字体,取值: 參考文檔
  580. * offset: 文本相对起始位置的偏置单位值
  581. * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
  582. * content: 文字内容
  583. */
  584. export function CascAde(x, y, fontName, fontSize, offset, content) {
  585. //console.log(fontName,fontSize,rotation, content);
  586. var strCmd = '';
  587. strCmd += 'CONCAT ';
  588. strCmd += x + ' ' + y + ' ' + '\n' + fontName + ' ' + fontSize + ' ' + '20' + ' ' + content + '\n' + '<ENDCONCAT>';
  589. // strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n';
  590. // console.log(strCmd, '14xxx擦拭发顺丰')
  591. return strCmd;
  592. };
  593. /**
  594. * 打印一维码
  595. *
  596. * x: 文字方块左上角X座标,单位dot
  597. * y: 文字方块左上角Y座标,单位dot
  598. * codeType: 条码类型,取值为128、UPCA、UPCA2、UPCA5、UPCE、UPCE2、UPC5、EAN13、EAN13+2、EAN13+5、
  599. * EAN8、EAN8+2、EAN8+5、39、39C、F39、F39C、93、CODABAR、CODABAR16、ITF、I2OF5
  600. * h: 条码高度,单位dot
  601. * rotation: 顺时针旋转角度,取值如下:
  602. * - 0 不旋转
  603. * - 1 顺时针旋转90度
  604. *
  605. * narrow: 窄条码比例因子(dot) 取值: 參考文檔
  606. * wide: 宽条码比例因子(dot) 取值: 參考文檔
  607. * content: 文字内容
  608. *
  609. */
  610. export function addCPCLBarCode(x, y, codeType, h, rotation, narrow, wide, content) {
  611. var strCmd = '';
  612. if (rotation == 0)
  613. strCmd += 'B ';
  614. else
  615. strCmd += 'VB ';
  616. strCmd += codeType + ' ' + narrow + ' ' + wide + ' ' + h + ' ' + x + ' ' + y + ' ' + content + '\n'
  617. return strCmd;
  618. };
  619. /**
  620. * 打印二维码
  621. *
  622. * x: 文字方块左上角X座标,单位dot
  623. * y: 文字方块左上角Y座标,单位dot
  624. * level: 错误纠正能力等级,取值为L(7%)、M(15%)、Q(25%)、H(30%)
  625. * ver: 1-10 版本,根据内容调整以获取合适容量
  626. * scale: 1-10 放大倍数
  627. * content: 文字内容
  628. *
  629. */
  630. export function addCPCLQRCode(x, y, level, ver, scale, content) {
  631. var strCmd = 'B QR ' + x + ' ' + y + ' M ' + ver + ' U ' + scale + '\n' + level + 'A,' + content + '\n';
  632. strCmd += 'ENDQR\n';
  633. return strCmd;
  634. };
  635. /**
  636. * 放大指令
  637. * scaleX: 横向放大倍数 1,2,3等整数
  638. * scaleY: 纵向放大倍数 1,2,3等整数
  639. */
  640. export function addCPCLSETMAG(scaleX, scaleY) {
  641. var strCmd = 'SETMAG ' + scaleX + ' ' + scaleY + '\n';
  642. return strCmd;
  643. };
  644. /**
  645. * 对齐指令 0-左对齐 1-右对齐 2-居中
  646. */
  647. export function addCPCLLocation(set) {
  648. var strCmd = '';
  649. if (set == 1) {
  650. strCmd += 'RIGHT\n';
  651. } else if (set == 2) {
  652. strCmd += 'CENTER\n';
  653. } else {
  654. strCmd += 'LEFT\n';
  655. }
  656. return strCmd;
  657. };
  658. /**
  659. * 反白线 x0,y0,x1,y1,width
  660. */
  661. export function addCPCLInverseLine(x0, y0, x1, y1, width) {
  662. var strCmd = 'IL ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
  663. return strCmd;
  664. };
  665. /**
  666. * 画线 x0,y0,x1,y1,width
  667. */
  668. export function addCPCLLine(x0, y0, x1, y1, width) { //下划线
  669. var strCmd = 'L ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
  670. return strCmd;
  671. };
  672. /**
  673. * 画框 x0,y0,x1,y1,width
  674. */
  675. export function addCPCLBox(x0, y0, x1, y1, width) {
  676. var strCmd = 'BOX ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
  677. return strCmd;
  678. };
  679. /**
  680. * 字体加粗
  681. */
  682. export function addCPCLSETBOLD(bold) {
  683. var strCmd = 'SETBOLD ' + bold + '\n';
  684. return strCmd;
  685. };
  686. /**
  687. * 字体下划线
  688. */
  689. export function addCPCLUNDERLINE(c) {
  690. var strCmd = 'UNDERLINE ';
  691. if (c) strCmd += 'ON\n';
  692. else if (c) strCmd += 'OFF\n';
  693. return strCmd;
  694. };
  695. /**
  696. * 水印打印灰度等级 0-255
  697. */
  698. export function addCPCLBACKGROUND(level) {
  699. var strCmd = 'BACKGROUND ';
  700. if (level > 255 || level < 0) level = 255;
  701. strCmd += level + '\n';
  702. return strCmd;
  703. };
  704. /**
  705. * 打印水印文字
  706. * x: 文字方块左上角X座标,单位dot
  707. * y: 文字方块左上角Y座标,单位dot
  708. * fontName,fontSize: 字体,取值: 參考文檔
  709. * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
  710. * content: 文字内容
  711. */
  712. export function addCPCLBKVText(x, y, fontName, fontSize, rotation, content) {
  713. //console.log(fontName,fontSize,rotation, content);
  714. var strCmd = '';
  715. if (rotation == 1) {
  716. strCmd += 'BKT90 ';
  717. }
  718. if (rotation == 2) {
  719. strCmd += 'BKT180 ';
  720. }
  721. if (rotation == 3) {
  722. strCmd += 'BKT270 ';
  723. } else {
  724. strCmd += 'BKT ';
  725. }
  726. strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n';
  727. return strCmd;
  728. };
  729. /**
  730. * 标签缝隙定位指令
  731. */
  732. export function addCPCLGAP() {
  733. var strCmd = 'GAP-SENSE\nFORM\n';
  734. return strCmd;
  735. };
  736. /**
  737. * 标签右黑标检测指令
  738. */
  739. export function addCPCLSENSE() {
  740. var strCmd = 'BAR-SENSE\nFORM\n';
  741. return strCmd;
  742. };
  743. /**
  744. * 标签左黑标检测指令
  745. */
  746. export function addCPCLSENSELEFT() {
  747. var strCmd = 'BAR-SENSE LEFT\nFORM\n';
  748. return strCmd;
  749. };
  750. /**
  751. * 打印指令
  752. */
  753. export function addCPCLPrint() {
  754. var strCmd = 'PRINT\n';
  755. return strCmd;
  756. };
  757. /**
  758. * 图片打印指令
  759. * x: 文字方块左上角X座标,单位dot
  760. * y: 文字方块左上角Y座标,单位dot
  761. * data{
  762. threshold,//0/1提取的灰度级
  763. width,//图像宽度
  764. height,//图像高度
  765. imageData , //图像数据
  766. }
  767. */
  768. export function addCPCLImageCmd(x, y, data) {
  769. console.log(data.threshold, data.width, data.height, data.imageData,
  770. '查询==================================================')
  771. var strImgCmd = '';
  772. // const threshold = data.threshold || 180;
  773. const threshold = 180;
  774. let myBitmapWidth = data.width,
  775. myBitmapHeight = data.height;
  776. let len = parseInt((myBitmapWidth + 7) / 8); //一行的数据长度
  777. //console.log('len=',len);
  778. //console.log('myBitmapWidth=',myBitmapWidth);
  779. //console.log('myBitmapHeight=',myBitmapHeight);
  780. let ndata = 0;
  781. let i = 0;
  782. let j = 0;
  783. let sendImageData = new ArrayBuffer(len * myBitmapHeight);
  784. sendImageData = new Uint8Array(sendImageData);
  785. // let pix = data.imageData;
  786. let pix = 'https://pos.zdhtmf.com/uploads/20210810/8bf7551773bdb72fbb7f4be9ac608ea9.png';
  787. for (i = 0; i < myBitmapHeight; i++) {
  788. for (j = 0; j < len; j++) {
  789. sendImageData[ndata + j] = 0;
  790. }
  791. for (j = 0; j < myBitmapWidth; j++) {
  792. const grayPixle1 = grayPixle(pix.slice((i * myBitmapWidth + j) * 4, (i * myBitmapWidth + j) * 4 + 3));
  793. if (grayPixle1 < threshold)
  794. sendImageData[ndata + parseInt(j / 8)] |= (0x80 >> (j % 8));
  795. }
  796. ndata += len;
  797. }
  798. console.log('sendImageData=', sendImageData);
  799. //CPCL指令图片数据
  800. strImgCmd += 'EG ' + len + ' ' + myBitmapHeight + ' ' + x + ' ' + y +
  801. ' 00d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';
  802. // console.log(strImgCmd,'查询1111111123455455');
  803. // for (i = 0; i < sendImageData.length; i++) {
  804. // strImgCmd += Hex2Str(sendImageData[i]);
  805. // console.log(strImgCmd,'查询休息下')
  806. // }
  807. // strImgCmd += '\n';
  808. // console.log(strImgCmd);
  809. return strImgCmd;
  810. }
  811. /**
  812. * toast显示捕获的蓝牙异常
  813. */
  814. export function catchToast(err) {
  815. const errMsg = {
  816. 10000: '未初始化蓝牙模块',
  817. 10001: '蓝牙未打开',
  818. 10002: '没有找到指定设备',
  819. 10003: '连接失败',
  820. 10004: '没有找到指定服务',
  821. 10005: '没有找到指定特征值',
  822. 10006: '当前连接已断开',
  823. 10007: '当前特征值不支持此操作',
  824. 10008: '系统上报异常',
  825. 10009: '系统版本低于 4.3 不支持BLE'
  826. };
  827. let coode = err.errCode ? err.errCode.toString() : '';
  828. let msg = errMsg[coode];
  829. plus.nativeUI.toast(msg || coode, {
  830. align: 'center',
  831. verticalAlign: 'center'
  832. });
  833. }