美文网首页微信小程序微信小程序开发微信小程序开发
微信小程序小票打印功能(以及中文乱码的解决)

微信小程序小票打印功能(以及中文乱码的解决)

作者: 当前明月 | 来源:发表于2019-04-19 21:19 被阅读8次

    因为业务需求,需要实现微信小程序连接热敏打印机打印小票。首先我要先知道微信小程序有没有蓝牙操作相关的API,然后就是如何蓝牙连接打印机,发送打印指令了。

    通过查看小程序文档,我看到微信小程序是支持蓝牙操作的

    小程序文档
    但是我看到它有两个,低功耗蓝牙,蓝牙。蓝牙我们知道,低功耗蓝牙是什么东西,网上查了下,解释如下:
    以前可能有蓝牙1.0、蓝牙2.0、蓝牙3.0、蓝牙4.0之类的以数字结尾的蓝牙版本号,而实际上,在最新的标准中,已经不再使用数字版本号作为蓝牙版本的区分了,取而代之的是经典蓝牙与低功耗蓝牙(BLE)这两种区别
    低功耗蓝牙(Bluetooth Low Energy,或称Bluetooth LEBLE,旧商标Bluetooth Smart)也称低功耗蓝牙,是蓝牙技术联盟设计和销售的一种个人局域网技术,旨在用于医疗保健、运动健身、信标、安防、家庭娱乐等领域的新兴应用。相较经典蓝牙,低功耗蓝牙旨在保持同等通信范围的同时显著降低功耗和成本.

    我要打印肯定要与打印机进行数据通信的,通过文档我看到,只有低功耗蓝牙里面有一个写和读的方法,那么微信就限定我只能通过低功耗蓝牙相关api进行与打印机相关交互,同时也限定了我的打印机也要支持低功耗蓝牙连接,幸运的是我的打印机是支持的。
    接下来看怎么写代码了,官方给了我们一个蓝牙操作的demo,那我就直接在demo上改了。



    点上面就能打开示例代码了。


    demo显示界面
    上面是demo界面,点击开始扫描就能收到周围的蓝牙了,我的打印机蓝牙也在搜索结果的列表里,我试了下,能够连接到我的打印机。
    接下来我打印一段文字试试。
    在index.js里面我改写了这个方法,我打印了一个hello world.
    writeBLECharacteristicValue() {
        let str = "hello world";
        let dataBuffer = new ArrayBuffer(100)
        let dataView = new DataView(dataBuffer)
         for (var i = 0; i < str.length; i++) {
          dataView.setUint8(i, str.charAt(i).charCodeAt())
        }
        wx.writeBLECharacteristicValue({
          deviceId: this._deviceId,
          serviceId: this._serviceId,
          characteristicId: this._characteristicId,
          value: dataBuffer,
          success: function(res) {
            console.log('发送的数据:' + that.writeDatas)
            console.log('message发送成功')
          },
          fail: function(res) {
            console.log("data:" + res)
          },
          complete: function(res) {
            console.log("data:" + res)
          }
        })
    }
    
    

    打印结果:


    打印结果

    看到了打印成功,接下来我试了下中文

    writeBLECharacteristicValue() {
        let str = "你好 世界";
        let dataBuffer = new ArrayBuffer(100)
        let dataView = new DataView(dataBuffer)
         for (var i = 0; i < str.length; i++) {
          dataView.setUint8(i, str.charAt(i).charCodeAt())
        }
        wx.writeBLECharacteristicValue({
          deviceId: this._deviceId,
          serviceId: this._serviceId,
          characteristicId: this._characteristicId,
          value: dataBuffer,
          success: function(res) {
            console.log('message发送成功')
          },
          fail: function(res) {
            console.log("data:" + res)
          },
          complete: function(res) {
            console.log("data:" + res)
          }
        })
    }
    

    打印结果:


    这打的是什么鬼,乱码了。初步推断可能是编码问题,网上也收到了相关问题的一些解答。
    小程序丨【已解决】蓝牙打印机打印中文乱码

    说是我的中文编码不对,应该转成gbk,然后再转成16进制,最后发送给打印机,说是这么说,但是代码怎么写,这片文章没说。我记得js是没有转gbk的方法的,只能看看别人怎么搞得,还真找到一个人写的。
    小程序蓝牙打印

    赶紧放到我的代码里试了一下,运行后发现了一个问题:

    这个gbk转换的代码怎么来的,通篇就这个一句话,并没有讲怎么来的,我推测他可能引入了一个库gbk相关的,于是接着搜索,还真有相关的库http://www.vuln.cn/2901
    下载下来
    下载后,打开这个库
    库文件内容
    这个该怎么放到小程序里面用呢,在下载页面我们看到了它的用法介绍

    这个写法小程序里不能用啊,不支持这种使用方式啊。小程序只支持下面这样的
    function send0X0A() {
      const buffer = new ArrayBuffer(1)
      const dataView = new DataView(buffer)
      dataView.setUint8(0, 0x0a)
      return buffer;
    }
    
    定义方法的地方模块导出
    module.exports = {
      hexStringToArrayBuffer: hexStringToArrayBuffer,
      hexStringToBuff: hexStringToBuff,
      send0X0A: send0X0A
    }
    
    使用的地方要引用一下
    var util = require('../../utils/util.js');
    
    

    没办法,只能修改库,一顿操作猛如虎,搞成了下面这样的



    这里我只导出了一个编码的方法,调用的地方是这样使用的

    const gbk = require('./gbk.js');
    const hexStringToBuff = str => { //str='中国:WXHSH'
      const buffer = new ArrayBuffer((sumStrLength(str)) * 4)
      const dataView = new DataView(buffer)
      var data = str.toString();
      var p = 0; //ArrayBuffer 偏移量
      for (var i = 0; i < data.length; i++) {
        if (isCN(data[i])) { //是中文
          //调用GBK 转码
          var t = gbk.encode(data[i]);
          for (var j = 0; j < 2; j++) {
            var code = t[j * 2] + t[j * 2 + 1];
            var temp = parseInt(code, 16)
            dataView.setUint8(p++, temp)
          }
        } else {
          var temp = data.charCodeAt(i);
          dataView.setUint8(p++, temp)
        }
      }
      return buffer;
    }
    }
    

    运行结果:图我就不截了,直接说结果,结果就是啥也没打印出来,这是怎么回事呢,调试下看看。



    发现问题了,一个中文是占两个字节的%C4%C3,按照上面那个哥们的写法我只分割了%C,4%,这是什么鬼,应该是%C4,%C3,才对,两个各代表一个字节码编号。于是改了下代码:

    const hexStringToBuff = str => { //str='中国:WXHSH'
      const buffer = new ArrayBuffer((sumStrLength(str)) * 4)
      const dataView = new DataView(buffer)
      var data = str.toString();
      var p = 0; //ArrayBuffer 偏移量
      for (var i = 0; i < data.length; i++) {
        if (isCN(data[i])) { //是中文
          //调用GBK 转码
          var t = gbk.encode(data[i]);
          for (var j = 0; j < 2; j++) {
            //var code = t[j * 2] + t[j * 2 + 1];
            var code = t[j * 3 + 1] + t[j * 3 + 2];
            var temp = parseInt(code, 16)
            dataView.setUint8(p++, temp)
          }
        } else {
          var temp = data.charCodeAt(i);
          dataView.setUint8(p++, temp)
        }
      }
      return buffer;
    }
    

    再次调试运行下看看:



    嗯这下 算分割对了,但是打印机还是没反应,在看代码发现temp = NaN,这是怎么回事呢,于是网上搜索gbk转16进制,总共发现这两个可用的方法

    function toUnicode(s) {
      var str = "";
      for (var i = 0; i < s.length; i++) {
        str += "\\u" + s.charCodeAt(i).toString(16) + "\t";
      }
      return str;
    }
    
    function strToHexCharCode(str) {
      if (str === "")
        return "";
      var hexCharCode = [];
      hexCharCode.push("0x");
      for (var i = 0; i < str.length; i++) {
        hexCharCode.push((str.charCodeAt(i)).toString(16));
      }
      return hexCharCode.join("");
    }
    

    调用其中一个看一下



    哎呀,这回好像temp有值了,还是16进制的,赶紧通过断点,看看打印机反应,乖乖有反应了,不截图了,直接说结果吧,乱码 乱码 乱码,这就奇了怪了,都转好了,怎么还打印不出来呢。网上一顿搜也没什么结果, 静下心来想一想,之前我们App是有打印功能的,那App传输的数据是什么样的呢,对比下我传的有什么不一样么?



    这个是android程序,它是通过getBytes()获取文本字节流。运行程序,查看打印结果

    我发现 android 转出来的都是负的整数,不像我传的0x...... ,看来还是我的数据转换的不对,再看一眼调试页面。



    C4 E3,冒是十六进制数据,%号什么鬼,它不可能转成整形,temp 一直是NaN,得 我去掉%号试试。

    呀嘿,temp有值了,跟Android的数据差不多,都是整数。过掉断点看看。
    哈哈,出来了,这一刻的心情你懂的。

    到此 小程序蓝牙打印算是流程搞通了,网上资料有时候不太全,有时还有错误,这就需要我们大胆猜测勇敢验证,最后福利来了,我把完整demo贡献上。
    https://github.com/lerpo/bluethooth.git

    相关文章

      网友评论

        本文标题:微信小程序小票打印功能(以及中文乱码的解决)

        本文链接:https://www.haomeiwen.com/subject/vibcgqtx.html