bluetoolth.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  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. uniAsyncPromise('writeBLECharacteristicValue', {
  262. ...options,
  263. value: options.value.slice(0, byteLength > speed ? speed : byteLength),
  264. })
  265. .then((res) => {
  266. // console.log('打印继续=============================', speed, byteLength);
  267. if (byteLength > speed) {
  268. num = 0
  269. sendDataToDevice({
  270. ...options,
  271. value: options.value.slice(speed, byteLength),
  272. });
  273. } else {
  274. num = 0
  275. uni.showToast({
  276. title: '打印完成',
  277. icon: 'none',
  278. duration: 2000
  279. })
  280. number = 0
  281. }
  282. })
  283. .catch((res) => {
  284. if (num != 15) {
  285. var data = {
  286. ...options,
  287. }
  288. sendDataToDevice({
  289. ...data,
  290. value: totalValue,
  291. // value: options.value.slice(speed,parseInt(byteLength)+parseInt(speed)*5),
  292. });
  293. console.log(res, '失败重新打印原因', options.value.slice(speed, byteLength), speed, byteLength);
  294. num++
  295. } else {
  296. num = 0
  297. uni.showToast({
  298. title: '打印失败请检查蓝牙连接状态或打印机状态',
  299. icon: 'none',
  300. duration: 2000
  301. })
  302. number = 0
  303. }
  304. });
  305. }
  306. }
  307. export function charToArrayBuffer(str) {
  308. var out = new ArrayBuffer(str.length);
  309. var uint8 = new Uint8Array(out);
  310. var strs = str.split('');
  311. for (var i = 0; i < strs.length; i++) {
  312. uint8[i] = strs[i].charCodeAt();
  313. }
  314. return uint8;
  315. }
  316. export function charToArray(str) {
  317. var arr = [];
  318. var strs = str.split('');
  319. for (var i = 0; i < strs.length; i++) {
  320. arr[i] = strs[i].charCodeAt();
  321. }
  322. return arr;
  323. }
  324. //打印二维码
  325. /**
  326. * @export
  327. * @param {object} options
  328. * {
  329. deviceId,
  330. serviceId,
  331. characteristicId,
  332. value,//ArrayBuffer:二维码的数据
  333. }
  334. */
  335. export function printQR(options) {
  336. //打印二维码的十进制指令data:
  337. let data = [29, 107, 97, 7, 4, options.value.byteLength, 0];
  338. sendDataToDevice({
  339. ...options,
  340. value: new Uint8Array(data).buffer,
  341. lasterSuccess: () => {
  342. //指令发送成功后,发送二维码的数据
  343. sendDataToDevice(options);
  344. },
  345. });
  346. }
  347. function grayPixle(pix) {
  348. return pix[0] * 0.299 + pix[1] * 0.587 + pix[2] * 0.114;
  349. }
  350. export function overwriteImageData(data) {
  351. let sendWidth = data.width,
  352. sendHeight = data.height;
  353. const threshold = data.threshold || 180;
  354. let sendImageData = new ArrayBuffer((sendWidth * sendHeight) / 8);
  355. sendImageData = new Uint8Array(sendImageData);
  356. let pix = data.imageData;
  357. const part = [];
  358. let index = 0;
  359. for (let i = 0; i < pix.length; i += 32) {
  360. //横向每8个像素点组成一个字节(8位二进制数)。
  361. for (let k = 0; k < 8; k++) {
  362. const grayPixle1 = grayPixle(pix.slice(i + k * 4, i + k * 4 + (4 - 1)));
  363. //阈值调整
  364. if (grayPixle1 > threshold) {
  365. //灰度值大于threshold位 白色 为第k位0不打印
  366. part[k] = 0;
  367. } else {
  368. part[k] = 1;
  369. }
  370. }
  371. let temp = 0;
  372. for (let a = 0; a < part.length; a++) {
  373. temp += part[a] * Math.pow(2, part.length - 1 - a);
  374. }
  375. //开始不明白以下算法什么意思,了解了字节才知道,一个字节是8位的二进制数,part这个数组存的0和1就是二进制的0和1,传输到打印的位图数据的一个字节是0-255之间的十进制数,以下是用权相加法转十进制数,理解了这个就用上面的for循环替代了
  376. // const temp =
  377. // part[0] * 128 +
  378. // part[1] * 64 +
  379. // part[2] * 32 +
  380. // part[3] * 16 +
  381. // part[4] * 8 +
  382. // part[5] * 4 +
  383. // part[6] * 2 +
  384. // part[7] * 1;
  385. sendImageData[index++] = temp;
  386. }
  387. return {
  388. array: Array.from(sendImageData),
  389. width: sendWidth / 8,
  390. height: sendHeight,
  391. };
  392. }
  393. /**
  394. * printImage
  395. * @param {object} opt
  396. * {
  397. deviceId,//蓝牙设备id
  398. serviceId,//服务id
  399. characteristicId,//可用特征值uuid
  400. lasterSuccess , //最后完成的回调
  401. }
  402. */
  403. export function printImage(opt = {}, imageInfo = {}) {
  404. let arr = imageInfo.array,
  405. width = imageInfo.width;
  406. const writeArray = [];
  407. const xl = width % 256;
  408. const xh = width / 256;
  409. //分行发送图片数据,用的十进制指令
  410. const command = [29, 118, 48, 0, xl, xh, 1, 0]; //1D 76 30 00 w h
  411. const enter = [13, 10];
  412. for (let i = 0; i < arr.length / width; i++) {
  413. const subArr = arr.slice(i * width, i * width + width);
  414. const tempArr = command.concat(subArr);
  415. writeArray.push(new Uint8Array(tempArr));
  416. }
  417. writeArray.push(new Uint8Array(enter));
  418. //console.log(writeArray);
  419. const print = (options, writeArray) => {
  420. if (writeArray.length) {
  421. // console.log("send");
  422. sendDataToDevice({
  423. ...options,
  424. value: writeArray.shift().buffer,
  425. lasterSuccess: () => {
  426. if (writeArray.length) {
  427. print(options, writeArray);
  428. } else {
  429. options.lasterSuccess && options.lasterSuccess();
  430. }
  431. },
  432. });
  433. }
  434. };
  435. // console.log("start print");
  436. print(opt, writeArray);
  437. }
  438. /* 16hex insert 0 */
  439. function Hex2Str(num) {
  440. if (num.toString(16).length < 2) return "0" + num.toString(16);
  441. else
  442. return num.toString(16);
  443. }
  444. /*****CPCL指令接口****/
  445. /**
  446. * 配置项如下
  447. * 设置打印纸张的范围
  448. * width: 标签纸的宽度,单位像素點
  449. * height: 标签纸的高度,单位像素點
  450. * 8像素=1mm
  451. * printNum: 打印张数,默认为1
  452. * rotation:页面整体旋转 1-90度 2-180度 3-270度 其他-不旋转
  453. */
  454. export function CreatCPCLPage(width, height, printNum, rotation = 0, offset = 0) {
  455. var strCmd = '! ' + offset + ' 200 200 ' + height + ' ' + printNum + '\n';
  456. strCmd += "PAGE-WIDTH " + width + '\n';
  457. if (rotation == 1)
  458. strCmd += "ZPROTATE90\n";
  459. else if (rotation == 2)
  460. strCmd += "ZPROTATE180\n";
  461. else if (rotation == 3)
  462. strCmd += "ZPROTATE270\n";
  463. else
  464. strCmd += "ZPROTATE0\n";
  465. return strCmd;
  466. }
  467. // * 打印文字
  468. // * x: 文字方块左上角X座标,单位dot
  469. // * y: 文字方块左上角Y座标,单位dot
  470. // * fontName,fontSize: 字体,取值: 參考文檔
  471. // * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
  472. // * content: 文字内容
  473. // */
  474. export function addCPCLText(x, y, fontName, fontSize, rotation, content) {
  475. //console.log(fontName,fontSize,rotation, content);
  476. var strCmd = '';
  477. if (rotation == 1) {
  478. strCmd += 'T90 ';
  479. }
  480. if (rotation == 2) {
  481. strCmd += 'T180 ';
  482. }
  483. if (rotation == 3) {
  484. strCmd += 'T270 ';
  485. } else {
  486. strCmd += 'T ';
  487. }
  488. strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n';
  489. return strCmd;
  490. };
  491. /**
  492. * 打印文字
  493. * x: 文字方块左上角X座标,单位dot
  494. * y: 文字方块左上角Y座标,单位dot
  495. * fontName,fontSize: 字体,取值: 參考文檔
  496. * strCmd += blesdk.addCPCLText(0,0,'4','244',0,'速购速递APP'); //改变默认字体
  497. * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
  498. * content: 文字内容
  499. */
  500. export function addCPCLTextil(x, y, fontName, fontSize, rotation, content) {
  501. //console.log(fontName,fontSize,rotation, content);
  502. const groupedArray = groupStrings(content);
  503. function groupStrings(str, size = 16) {
  504. const result = [];
  505. for (let i = 0; i < str.length; i += size) {
  506. result.push(str.substr(i, size));
  507. }
  508. return result;
  509. }
  510. var strCmd = '';
  511. for (var i in groupedArray) {
  512. if (rotation == 1) {
  513. strCmd += 'T90 ';
  514. } else if (rotation == 2) {
  515. strCmd += 'T180 ';
  516. } else if (rotation == 3) {
  517. strCmd += 'T270 ';
  518. } else if (rotation == 4) {
  519. strCmd += 'VT ';
  520. } else {
  521. strCmd += 'T ';
  522. }
  523. strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + (parseInt(y) + parseInt(i * 30)) + ' ' + groupedArray[i] +
  524. '\n';
  525. }
  526. return strCmd;
  527. };
  528. /**
  529. * 长文本打印
  530. * x: 文字方块左上角X座标,单位dot
  531. * y: 文字方块左上角Y座标,单位dot
  532. * fontName,fontSize: 字体,取值: 參考文檔
  533. * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
  534. * content: 文字内容
  535. */
  536. export function LongText(x, y, fontName, fontSize, rotation, content, nu = 16) {
  537. var num = parseInt(content.length / nu)
  538. var arr = content.split('')
  539. var abb = []
  540. for (var n = 0; n <= num; n++) {
  541. var str = '';
  542. for (var i in arr) {
  543. if (i >= n * nu && i <= (n + 1) * nu) {
  544. str += arr[i]
  545. }
  546. }
  547. abb.push(str)
  548. }
  549. var strCmd = '';
  550. for (var i in abb) {
  551. // console.log(i, num)
  552. if (rotation == 1) {
  553. strCmd += 'T90 ';
  554. }
  555. if (rotation == 2) {
  556. strCmd += 'T180 ';
  557. }
  558. if (rotation == 3) {
  559. strCmd += 'T270 ';
  560. } else {
  561. strCmd += 'T ';
  562. }
  563. if (i != num && num != 0) {
  564. var acc = abb[i].split('')
  565. acc.pop()
  566. abb[i] = acc.join('')
  567. }
  568. strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + (parseInt(y) + parseInt(i * 30)) + ' ' + abb[i] + '\n';
  569. }
  570. return strCmd;
  571. };
  572. /**
  573. * 文本串联
  574. * x: 文字方块左上角X座标,单位dot
  575. * y: 文字方块左上角Y座标,单位dot
  576. * fontName,fontSize: 字体,取值: 參考文檔
  577. * offset: 文本相对起始位置的偏置单位值
  578. * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
  579. * content: 文字内容
  580. */
  581. export function CascAde(x, y, fontName, fontSize, offset, content) {
  582. //console.log(fontName,fontSize,rotation, content);
  583. var strCmd = '';
  584. strCmd += 'CONCAT ';
  585. strCmd += x + ' ' + y + ' ' + '\n' + fontName + ' ' + fontSize + ' ' + '20' + ' ' + content + '\n' + '<ENDCONCAT>';
  586. // strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n';
  587. // console.log(strCmd, '14xxx擦拭发顺丰')
  588. return strCmd;
  589. };
  590. /**
  591. * 打印一维码
  592. *
  593. * x: 文字方块左上角X座标,单位dot
  594. * y: 文字方块左上角Y座标,单位dot
  595. * codeType: 条码类型,取值为128、UPCA、UPCA2、UPCA5、UPCE、UPCE2、UPC5、EAN13、EAN13+2、EAN13+5、
  596. * EAN8、EAN8+2、EAN8+5、39、39C、F39、F39C、93、CODABAR、CODABAR16、ITF、I2OF5
  597. * h: 条码高度,单位dot
  598. * rotation: 顺时针旋转角度,取值如下:
  599. * - 0 不旋转
  600. * - 1 顺时针旋转90度
  601. *
  602. * narrow: 窄条码比例因子(dot) 取值: 參考文檔
  603. * wide: 宽条码比例因子(dot) 取值: 參考文檔
  604. * content: 文字内容
  605. *
  606. */
  607. export function addCPCLBarCode(x, y, codeType, h, rotation, narrow, wide, content) {
  608. var strCmd = '';
  609. if (rotation == 0)
  610. strCmd += 'B ';
  611. else
  612. strCmd += 'VB ';
  613. strCmd += codeType + ' ' + narrow + ' ' + wide + ' ' + h + ' ' + x + ' ' + y + ' ' + content + '\n'
  614. return strCmd;
  615. };
  616. /**
  617. * 打印二维码
  618. *
  619. * x: 文字方块左上角X座标,单位dot
  620. * y: 文字方块左上角Y座标,单位dot
  621. * level: 错误纠正能力等级,取值为L(7%)、M(15%)、Q(25%)、H(30%)
  622. * ver: 1-10 版本,根据内容调整以获取合适容量
  623. * scale: 1-10 放大倍数
  624. * content: 文字内容
  625. *
  626. */
  627. export function addCPCLQRCode(x, y, level, ver, scale, content) {
  628. var strCmd = 'B QR ' + x + ' ' + y + ' M ' + ver + ' U ' + scale + '\n' + level + 'A,' + content + '\n';
  629. strCmd += 'ENDQR\n';
  630. return strCmd;
  631. };
  632. /**
  633. * 放大指令
  634. * scaleX: 横向放大倍数 1,2,3等整数
  635. * scaleY: 纵向放大倍数 1,2,3等整数
  636. */
  637. export function addCPCLSETMAG(scaleX, scaleY) {
  638. var strCmd = 'SETMAG ' + scaleX + ' ' + scaleY + '\n';
  639. return strCmd;
  640. };
  641. /**
  642. * 对齐指令 0-左对齐 1-右对齐 2-居中
  643. */
  644. export function addCPCLLocation(set) {
  645. var strCmd = '';
  646. if (set == 1) {
  647. strCmd += 'RIGHT\n';
  648. } else if (set == 2) {
  649. strCmd += 'CENTER\n';
  650. } else {
  651. strCmd += 'LEFT\n';
  652. }
  653. return strCmd;
  654. };
  655. /**
  656. * 反白线 x0,y0,x1,y1,width
  657. */
  658. export function addCPCLInverseLine(x0, y0, x1, y1, width) {
  659. var strCmd = 'IL ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
  660. return strCmd;
  661. };
  662. /**
  663. * 画线 x0,y0,x1,y1,width
  664. */
  665. export function addCPCLLine(x0, y0, x1, y1, width) { //下划线
  666. var strCmd = 'L ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
  667. return strCmd;
  668. };
  669. /**
  670. * 画框 x0,y0,x1,y1,width
  671. */
  672. export function addCPCLBox(x0, y0, x1, y1, width) {
  673. var strCmd = 'BOX ' + x0 + ' ' + y0 + ' ' + x1 + ' ' + y1 + ' ' + width + '\n';
  674. return strCmd;
  675. };
  676. /**
  677. * 字体加粗
  678. */
  679. export function addCPCLSETBOLD(bold) {
  680. var strCmd = 'SETBOLD ' + bold + '\n';
  681. return strCmd;
  682. };
  683. /**
  684. * 字体下划线
  685. */
  686. export function addCPCLUNDERLINE(c) {
  687. var strCmd = 'UNDERLINE ';
  688. if (c) strCmd += 'ON\n';
  689. else if (c) strCmd += 'OFF\n';
  690. return strCmd;
  691. };
  692. /**
  693. * 水印打印灰度等级 0-255
  694. */
  695. export function addCPCLBACKGROUND(level) {
  696. var strCmd = 'BACKGROUND ';
  697. if (level > 255 || level < 0) level = 255;
  698. strCmd += level + '\n';
  699. return strCmd;
  700. };
  701. /**
  702. * 打印水印文字
  703. * x: 文字方块左上角X座标,单位dot
  704. * y: 文字方块左上角Y座标,单位dot
  705. * fontName,fontSize: 字体,取值: 參考文檔
  706. * rotation: 旋转 1-90度 2-180度 3-270度 其他-不旋转
  707. * content: 文字内容
  708. */
  709. export function addCPCLBKVText(x, y, fontName, fontSize, rotation, content) {
  710. //console.log(fontName,fontSize,rotation, content);
  711. var strCmd = '';
  712. if (rotation == 1) {
  713. strCmd += 'BKT90 ';
  714. }
  715. if (rotation == 2) {
  716. strCmd += 'BKT180 ';
  717. }
  718. if (rotation == 3) {
  719. strCmd += 'BKT270 ';
  720. } else {
  721. strCmd += 'BKT ';
  722. }
  723. strCmd += fontName + ' ' + fontSize + ' ' + x + ' ' + y + ' ' + content + '\n';
  724. return strCmd;
  725. };
  726. /**
  727. * 标签缝隙定位指令
  728. */
  729. export function addCPCLGAP() {
  730. var strCmd = 'GAP-SENSE\nFORM\n';
  731. return strCmd;
  732. };
  733. /**
  734. * 标签右黑标检测指令
  735. */
  736. export function addCPCLSENSE() {
  737. var strCmd = 'BAR-SENSE\nFORM\n';
  738. return strCmd;
  739. };
  740. /**
  741. * 标签左黑标检测指令
  742. */
  743. export function addCPCLSENSELEFT() {
  744. var strCmd = 'BAR-SENSE LEFT\nFORM\n';
  745. return strCmd;
  746. };
  747. /**
  748. * 打印指令
  749. */
  750. export function addCPCLPrint() {
  751. var strCmd = 'PRINT\n';
  752. return strCmd;
  753. };
  754. /**
  755. * 图片打印指令
  756. * x: 文字方块左上角X座标,单位dot
  757. * y: 文字方块左上角Y座标,单位dot
  758. * data{
  759. threshold,//0/1提取的灰度级
  760. width,//图像宽度
  761. height,//图像高度
  762. imageData , //图像数据
  763. }
  764. */
  765. export function addCPCLImageCmd(x, y, data) {
  766. console.log(data.threshold, data.width, data.height, data.imageData,
  767. '查询==================================================')
  768. var strImgCmd = '';
  769. // const threshold = data.threshold || 180;
  770. const threshold = 180;
  771. let myBitmapWidth = data.width,
  772. myBitmapHeight = data.height;
  773. let len = parseInt((myBitmapWidth + 7) / 8); //一行的数据长度
  774. //console.log('len=',len);
  775. //console.log('myBitmapWidth=',myBitmapWidth);
  776. //console.log('myBitmapHeight=',myBitmapHeight);
  777. let ndata = 0;
  778. let i = 0;
  779. let j = 0;
  780. let sendImageData = new ArrayBuffer(len * myBitmapHeight);
  781. sendImageData = new Uint8Array(sendImageData);
  782. // let pix = data.imageData;
  783. let pix = 'https://pos.zdhtmf.com/uploads/20210810/8bf7551773bdb72fbb7f4be9ac608ea9.png';
  784. for (i = 0; i < myBitmapHeight; i++) {
  785. for (j = 0; j < len; j++) {
  786. sendImageData[ndata + j] = 0;
  787. }
  788. for (j = 0; j < myBitmapWidth; j++) {
  789. const grayPixle1 = grayPixle(pix.slice((i * myBitmapWidth + j) * 4, (i * myBitmapWidth + j) * 4 + 3));
  790. if (grayPixle1 < threshold)
  791. sendImageData[ndata + parseInt(j / 8)] |= (0x80 >> (j % 8));
  792. }
  793. ndata += len;
  794. }
  795. console.log('sendImageData=', sendImageData);
  796. //CPCL指令图片数据
  797. strImgCmd += 'EG ' + len + ' ' + myBitmapHeight + ' ' + x + ' ' + y +
  798. ' 00d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';
  799. // console.log(strImgCmd,'查询1111111123455455');
  800. // for (i = 0; i < sendImageData.length; i++) {
  801. // strImgCmd += Hex2Str(sendImageData[i]);
  802. // console.log(strImgCmd,'查询休息下')
  803. // }
  804. // strImgCmd += '\n';
  805. // console.log(strImgCmd);
  806. return strImgCmd;
  807. }
  808. /**
  809. * toast显示捕获的蓝牙异常
  810. */
  811. export function catchToast(err) {
  812. const errMsg = {
  813. 10000: '未初始化蓝牙模块',
  814. 10001: '蓝牙未打开',
  815. 10002: '没有找到指定设备',
  816. 10003: '连接失败',
  817. 10004: '没有找到指定服务',
  818. 10005: '没有找到指定特征值',
  819. 10006: '当前连接已断开',
  820. 10007: '当前特征值不支持此操作',
  821. 10008: '系统上报异常',
  822. 10009: '系统版本低于 4.3 不支持BLE'
  823. };
  824. let coode = err.errCode ? err.errCode.toString() : '';
  825. let msg = errMsg[coode];
  826. plus.nativeUI.toast(msg || coode, {
  827. align: 'center',
  828. verticalAlign: 'center'
  829. });
  830. }