sendCommand.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. // pages/sendCommand/sendCommand.js
  2. /**
  3. * 此Demo仅供参考,可打印数字,英文,符号,中文,
  4. * 小程序支持的蓝牙为低功耗蓝牙(BLE),数据量大需分包发送
  5. */
  6. var app = getApp();
  7. var tsc = require("../../utils/tsc.js");
  8. var esc = require("../../utils/esc.js");
  9. var encode = require("../../utils/encoding.js");
  10. function convertToGrayscale(data) {
  11. let g = 0
  12. for (let i = 0; i < data.length; i += 4) {
  13. g = (data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11)
  14. data[i] = g
  15. data[i + 1] = g
  16. data[i + 2] = g
  17. }
  18. return data
  19. }
  20. function setPixel(data, offset, value) {
  21. data[offset] = value;
  22. data[offset+1] = value;
  23. data[offset+2] = value;
  24. }
  25. function adjustPixel(data, offset, value) {
  26. data[offset] += value;
  27. }
  28. // 彩色图转成单色图
  29. function convertToMonoImage(width, height, data, shake) {
  30. let g = 0
  31. let e = 0
  32. for(let i=0; i<data.length; i+=4) {
  33. data[i] = (data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11);
  34. }
  35. for(let y=0; y<height; y++) {
  36. for(let x=0; x<width; x++) {
  37. let dataOffset = (width * y + x) * 4;
  38. g = data[dataOffset];
  39. if(g >= 150) { // 灰色转黑白的阈值, 可以调整打印效果
  40. e = g - 255;
  41. setPixel(data, dataOffset, 255);
  42. } else {
  43. e = g;
  44. setPixel(data, dataOffset, 0);
  45. }
  46. if(!shake)
  47. continue;
  48. if (x < width - 1 && y < height - 1) {
  49. //右边像素处理
  50. data[(width * y + x + 1)*4] += 7 * e / 16;
  51. //下
  52. data[(width * (y + 1) + x)*4] += 5 * e / 16;
  53. //右下
  54. data[(width * (y + 1) + x + 1)*4] += e / 16;
  55. //左下
  56. if (x > 0) {
  57. data[(width * (y + 1) + x - 1)*4] += 3 * e / 16;
  58. }
  59. } else if (x == width - 1 && y < height - 1) {
  60. //下方像素处理
  61. data[(width * (y + 1) + x)*4] += 5 * e / 16;
  62. } else if (x < width - 1 && y == height - 1) {
  63. //右边像素处理
  64. data[(width * y + x + 1)*4] += 7 * e / 16;
  65. }
  66. }
  67. }
  68. return data
  69. }
  70. Page({
  71. /**
  72. * 页面的初始数据
  73. */
  74. data: {
  75. sendContent: "",
  76. looptime: 0,
  77. currentTime: 1,
  78. lastData: 0,
  79. oneTimeData: 0,
  80. returnResult: "",
  81. canvasWidth: 180,
  82. canvasHeight: 180,
  83. imageSrc: '../../imags/abc_ic_star_black_16dp.png',
  84. buffSize: [],
  85. buffIndex: 0,
  86. printNum: [],
  87. printNumIndex: 0,
  88. printerNum: 1,
  89. currentPrint: 1,
  90. isReceiptSend: false,
  91. isLabelSend: false
  92. },
  93. /**
  94. * 生命周期函数--监听页面加载
  95. */
  96. onLoad: function (options) {
  97. var that = this;
  98. wx.notifyBLECharacteristicValueChange({
  99. deviceId: app.BLEInformation.deviceId,
  100. serviceId: app.BLEInformation.notifyServiceId,
  101. characteristicId: app.BLEInformation.notifyCharaterId,
  102. state: true,
  103. success: function (res) {
  104. wx.onBLECharacteristicValueChange(function (r) {
  105. console.log(`characteristic ${r.characteristicId} has changed, now is ${r}`)
  106. })
  107. },
  108. fail: function (e) {
  109. console.log(e)
  110. },
  111. complete: function (e) {
  112. console.log(e)
  113. }
  114. })
  115. },
  116. inputEvent: function (e) { //获取输入内容
  117. this.setData({
  118. sendContent: e.detail.value
  119. })
  120. },
  121. sendData: function () { //输入框点击发送
  122. var data = this.data.sendContent + "\n"
  123. this.setData({
  124. looptime: 0
  125. })
  126. var content = new encode.TextEncoder(
  127. 'gb18030', {
  128. NONSTANDARD_allowLegacyEncoding: true
  129. }).encode(data);
  130. this.prepareSend(content)
  131. },
  132. labelTest: function () { //标签测试
  133. var that = this;
  134. var canvasWidth = that.data.canvasWidth
  135. var canvasHeight = that.data.canvasHeight
  136. var command = tsc.jpPrinter.createNew()
  137. command.setSize(48, 40)
  138. command.setGap(0)
  139. command.setCls()
  140. // command.setText(0, 30, "TSS24.BF2", 1, 1, "图片")
  141. // command.setQrcode(40, 120, "L", 4, "A", "www.gainscha.com佳博浩盛")
  142. // command.setText(60, 90, "TSS24.BF2", 1, 1, "佳博浩盛")
  143. // command.setText(170, 50, "TSS24.BF2", 1, 1, "小程序测试")
  144. // command.setText(170, 90, "TSS24.BF2", 1, 1, "测试数字12345678")
  145. // command.setText(170, 120, "TSS24.BF2", 1, 1, "测试英文abcdefg")
  146. // command.setText(170, 150, "TSS24.BF2", 1, 1, "测试符号/*-+!@#$")
  147. // command.setBarCode(170, 180, "EAN8", 64, 1, 0,3, 3, "1234567")
  148. wx.canvasGetImageData({
  149. canvasId: 'canvasOut',
  150. x: 0,
  151. y: 0,
  152. width: canvasWidth,
  153. height: canvasHeight,
  154. success: function (res) {
  155. console.log('res len= ' + res.data.length)
  156. command.setBitmap(60, 0, 1, res)
  157. command.setPrint(1)
  158. that.prepareSend(command.getData())
  159. },
  160. complete: function () {
  161. command.setPagePrint()
  162. that.setData({
  163. isLabelSend: true
  164. })
  165. }
  166. })
  167. },
  168. receiptTest: function () { //票据测试
  169. var that = this;
  170. var canvasWidth = that.data.canvasWidth
  171. var canvasHeight = that.data.canvasHeight
  172. var command = esc.jpPrinter.createNew()
  173. command.init()
  174. command.setText("票据测试!");
  175. command.setPrint()
  176. command.setText("This is a receipt test!!!")
  177. command.setPrint()
  178. command.setText("二维码测试:")
  179. command.setPrint()
  180. command.setSelectSizeOfModuleForQRCode(5)
  181. command.setSelectErrorCorrectionLevelForQRCode(49)
  182. command.setStoreQRCodeData("佳博浩盛打印机")
  183. command.setPrintQRCode()
  184. command.setPrint()
  185. command.setSelectJustification(0)
  186. command.setText("向左对齐")
  187. command.setPrint()
  188. command.setSelectJustification(1)
  189. command.setText("居中对齐")
  190. command.setPrint()
  191. command.setSelectJustification(2)
  192. command.setText("向右对齐")
  193. command.setPrint()
  194. command.setSelectJustification(0)
  195. command.setText("图片测试")
  196. command.setPrint()
  197. wx.canvasGetImageData({
  198. canvasId: 'canvasOut',
  199. x: 0,
  200. y: 0,
  201. width: canvasWidth,
  202. height: canvasHeight,
  203. success: function (res) {
  204. command.setBitmap(res)
  205. that.prepareSend(command.getData())
  206. },
  207. complete: function (res) {
  208. console.log("finish")
  209. command.setPrint()
  210. that.setData({
  211. isReceiptSend: true
  212. })
  213. //that.prepareSend(command.getData())
  214. }
  215. })
  216. // this.send(buff)
  217. },
  218. openAndDraw() {
  219. var that = this
  220. const MAX_WIDTH = 384; // 58打印宽度
  221. //const MAX_WIDTH = 576; // 80打印宽度
  222. const MAX_HEIGHT = 256;
  223. wx.chooseImage({
  224. success: (res) => {
  225. const ctx_in = wx.createCanvasContext('canvasIn', this);
  226. const ctx_out = wx.createCanvasContext('canvasOut', this);
  227. wx.getImageInfo({
  228. src: res.tempFilePaths[0],
  229. success(info) {
  230. console.log('origin width: ' + info.width)
  231. console.log('origin height: ' + info.height)
  232. var imgWidth = info.width;
  233. var imgHeight = info.height;
  234. var canWidth = imgWidth;
  235. var canHeight = imgHeight;
  236. var canScale = 1.0;
  237. // 按 MAX_WIDTH 调整图片宽度
  238. if(imgWidth > MAX_WIDTH) {
  239. canWidth = MAX_WIDTH;
  240. canScale = canWidth / imgWidth;
  241. canHeight = parseInt(canScale * imgHeight);
  242. console.log("scale = "+canScale);
  243. console.log('scale canvas width: ' + canWidth);
  244. console.log('scale canvas height: ' + canHeight);
  245. }
  246. // 按 MAX_HEIGHT 截取高度 (过多的部分会被裁剪掉)
  247. if(canHeight > MAX_HEIGHT) {
  248. canHeight = MAX_HEIGHT;
  249. imgHeight = parseInt(canHeight / canScale);
  250. }
  251. that.setData({
  252. canvasWidth: canWidth,
  253. canvasHeight: canHeight,
  254. });
  255. ctx_in.drawImage(res.tempFilePaths[0], 0, 0, imgWidth, imgHeight, 0, 0, canWidth, canHeight)
  256. ctx_in.draw()
  257. ctx_out.clearRect(0, 0, imgWidth, imgHeight)
  258. ctx_out.draw()
  259. }
  260. })
  261. }
  262. })
  263. },
  264. process() {
  265. var that = this
  266. const cfg = {
  267. x: 0,
  268. y: 0,
  269. width: that.data.canvasWidth,
  270. height: that.data.canvasHeight,
  271. }
  272. wx.canvasGetImageData({
  273. canvasId: 'canvasIn',
  274. ...cfg,
  275. success: (res) => {
  276. //const data = convertToGrayscale(res.data)
  277. const data = convertToMonoImage(res.width, res.height, res.data, true);
  278. wx.canvasPutImageData({
  279. canvasId: 'canvasOut',
  280. data,
  281. ...cfg,
  282. success: (res) => {
  283. console.log(res)
  284. console.log('deal graphic width: ' + cfg.width)
  285. console.log('deal graphic width: ' + cfg.height)
  286. },
  287. fail: (err) => {
  288. console.error(err)
  289. }
  290. })
  291. },
  292. fail: (err) => {
  293. console.error(err)
  294. }
  295. })
  296. },
  297. prepareSend: function (buff) { //准备发送,根据每次发送字节数来处理分包数量
  298. //console.log(buff)
  299. var that = this
  300. var time = that.data.oneTimeData
  301. var looptime = parseInt(buff.length / time);
  302. var lastData = parseInt(buff.length % time);
  303. //console.log(looptime + "---" + lastData)
  304. that.setData({
  305. looptime: looptime + 1,
  306. lastData: lastData,
  307. currentTime: 1,
  308. })
  309. that.Send(buff)
  310. },
  311. queryStatus: function () { //查询打印机状态
  312. var command = esc.jpPrinter.Query();
  313. command.getRealtimeStatusTransmission(1);
  314. },
  315. Send: function (buff) { //分包发送
  316. var that = this
  317. var currentTime = that.data.currentTime
  318. var loopTime = that.data.looptime
  319. var lastData = that.data.lastData
  320. var onTimeData = that.data.oneTimeData
  321. var printNum = that.data.printerNum
  322. var currentPrint = that.data.currentPrint
  323. var buf
  324. var dataView
  325. if (currentTime < loopTime) {
  326. buf = new ArrayBuffer(onTimeData)
  327. dataView = new DataView(buf)
  328. for (var i = 0; i < onTimeData; ++i) {
  329. dataView.setUint8(i, buff[(currentTime - 1) * onTimeData + i])
  330. }
  331. } else {
  332. buf = new ArrayBuffer(lastData)
  333. dataView = new DataView(buf)
  334. for (var i = 0; i < lastData; ++i) {
  335. dataView.setUint8(i, buff[(currentTime - 1) * onTimeData + i])
  336. }
  337. }
  338. //console.log("第" + currentTime + "次发送数据大小为:" + buf.byteLength)
  339. wx.writeBLECharacteristicValue({
  340. deviceId: app.BLEInformation.deviceId,
  341. serviceId: app.BLEInformation.writeServiceId,
  342. characteristicId: app.BLEInformation.writeCharaterId,
  343. value: buf,
  344. success: function (res) {
  345. wx.showToast({
  346. title: '已打印第' + currentPrint + '张成功',
  347. })
  348. //console.log(res)
  349. },
  350. fail: function (e) {
  351. wx.showToast({
  352. title: '打印第' + currentPrint + '张失败',
  353. icon: 'none',
  354. })
  355. //console.log(e)
  356. },
  357. complete: function () {
  358. currentTime++
  359. if (currentTime <= loopTime) {
  360. that.setData({
  361. currentTime: currentTime
  362. })
  363. that.Send(buff)
  364. } else {
  365. // wx.showToast({
  366. // title: '已打印第' + currentPrint + '张',
  367. // })
  368. if (currentPrint == printNum) {
  369. that.setData({
  370. looptime: 0,
  371. lastData: 0,
  372. currentTime: 1,
  373. isReceiptSend: false,
  374. isLabelSend: false,
  375. currentPrint: 1
  376. })
  377. } else {
  378. currentPrint++
  379. that.setData({
  380. currentPrint: currentPrint,
  381. currentTime: 1,
  382. })
  383. that.Send(buff)
  384. }
  385. }
  386. }
  387. })
  388. },
  389. /**
  390. * 生命周期函数--监听页面初次渲染完成
  391. */
  392. onReady: function () {
  393. var list = []
  394. var numList = []
  395. var j = 0
  396. for (var i = 20; i < 200; i += 10) {
  397. list[j] = i;
  398. j++
  399. }
  400. for (var i = 1; i < 10; i++) {
  401. numList[i - 1] = i
  402. }
  403. this.setData({
  404. buffSize: list,
  405. oneTimeData: list[0],
  406. printNum: numList,
  407. printerNum: numList[0]
  408. })
  409. },
  410. /**
  411. * 生命周期函数--监听页面显示
  412. */
  413. onShow: function () {
  414. },
  415. buffBindChange: function (res) { //更改打印字节数
  416. var index = res.detail.value
  417. var time = this.data.buffSize[index]
  418. this.setData({
  419. buffIndex: index,
  420. oneTimeData: time
  421. })
  422. },
  423. printNumBindChange: function (res) { //更改打印份数
  424. var index = res.detail.value
  425. var num = this.data.printNum[index]
  426. this.setData({
  427. printNumIndex: index,
  428. printerNum: num
  429. })
  430. },
  431. /**
  432. * 生命周期函数--监听页面隐藏
  433. */
  434. onHide: function () {
  435. },
  436. /**
  437. * 生命周期函数--监听页面卸载
  438. */
  439. onUnload: function () {
  440. // wx.closeBLEConnection({
  441. // deviceId: app.BLEInformation.deviceId,
  442. // success: function(res) {
  443. // console.log("关闭蓝牙成功")
  444. // },
  445. // })
  446. },
  447. /**
  448. * 页面相关事件处理函数--监听用户下拉动作
  449. */
  450. onPullDownRefresh: function () {
  451. },
  452. /**
  453. * 页面上拉触底事件的处理函数
  454. */
  455. onReachBottom: function () {
  456. },
  457. /**
  458. * 用户点击右上角分享
  459. */
  460. onShareAppMessage: function () {
  461. }
  462. })