微信蓝牙打印指令+数据

1、说明:微信蓝牙传递的数据格式是GBK编码的二进制格式,下面就说一下在小程序中是如何获取蓝牙打印的数据

2、普通文本的打印:

要转义GBK编码的话要用到GBK.js,库的网址:https://github.com/cnwhy/GBK.js

import GBK from './gbk.min';
GBK.encode('时顺地?abc地')
// 解码GBK为一个字节数组 [ 202, 177, 203, 179, 181, 216, 63, 97, 98, 99, 181, 216 ]
GBK.decode([ 202, 177, 203, 179, 181, 216, 63, 97, 98, 99, 181, 216 ])
//解码GBK编码的字节数组 返回字符串 时顺地?abc地;

然后是打印机指令

//打印机指令 使用的 ESC/POS指令, 十进制方式
const printCommand = {
  left: [27, 97, 0], //居左
  center: [27, 97, 1], //居中
  right: [27, 97, 2], //居右
  clear: [27, 64], //初始化
  enter: [10], //打印
};

对于那些多个数据一行的可以用一些方法调整打印位置,比如左右两个数据,左中右三个数据的

复制代码
/*获取字符长度 */
function getBytesLength(val) {
  let str = new String(val);
  let bytesCount = 0;
  for (let i = 0, n = str.length; i < n; i++) {
    let c = str.charCodeAt(i);
    if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
      bytesCount += 1;
    } else {
      bytesCount += 2;
    }
  }
  return bytesCount;
}
//计算打印的位置  左右各两边  返回带空格的整行字符串
function printTwoData(leftText, rightText) {
  let sb = '';
  let maxLen = 32;
  let leftTextLength = getBytesLength(leftText);
  let rightTextLength = getBytesLength(rightText);
  let spaceLen = maxLen - leftTextLength - rightTextLength;
  sb = sb + leftText;
  for (let i = 0; i < spaceLen; i++) {
    sb = sb + ' ';
  }
  sb = sb + rightText;
  return sb.toString();
}
//计算打印的位置  左 中 右  返回带空格的整行字符串
function printThreeData(leftText, centerText, rightText) {
  let sb = '';
  let maxLen = 32;
  let leftTextLength = getBytesLength(leftText);
  let centerTextLength = getBytesLength(centerText);
  let rightTextLength = getBytesLength(rightText);
  let spaceLeft = maxLen / 2 - leftTextLength - centerTextLength / 2;
  let spaceRight = maxLen / 2 - centerTextLength / 2 - rightTextLength;
  sb = sb + leftText;
  for (let i = 0; i < spaceLeft; i++) {
    sb = sb + ' ';
  }
  sb = sb + centerText;
  for (let i = 0; i < spaceRight; i++) {
    sb = sb + ' ';
  }
  sb = sb + rightText;
  return sb.toString();
}
//计算打印的位置  根据数组平均分配  返回带空格的整行字符串
function printMoreData(arr) {
  let sb = '';
  let maxLen = 32;
  let distance=0
  let data=arr.map((e)=>{
    let obj={}
    obj.text=e;
    obj.len=getBytesLength(e)
    distance+=obj.len
    return obj
  })
  let num=arr.length-1
  distance=Math.floor((maxLen-distance)/(num))
  data.forEach((e,i) => {
      if(i!==num){
        sb=sb+e.text
        for (let i = 0; i < distance; i++) {
          sb = sb + ' ';
        }
      }else{
        sb=sb+e.text
      }
  });
  return sb.toString();
}
复制代码

然后还要通过new Uint8Array().buffer的方法转化成二进制的格式ArrayBuffer

复制代码
let printData = new Uint8Array([...printCommand.clear, ...GBK.encode('我是要打印的字符串'), ...printCommand.enter]).buffer  //单行正常的数据 每次打印调用clear清除打印的格式和打印机缓存,从新的一行开始
let printData = new Uint8Array([...printCommand.clear,...printCommand.right, ...GBK.encode('我是要打印的字符串'), ...printCommand.enter]).buffer  //单行居右的数据
let printData = new Uint8Array([...printCommand.clear, ...GBK.encode(printTwoData('左边的数据','右边的数据')), ...printCommand.enter]).buffer  //单行分左右的数据
let printData = new Uint8Array([...printCommand.clear, ...GBK.encode(printThreeData('左边的数据','中间的数据','右边的数据')), ...printCommand.enter]).buffer  //单行分左中右的数据
    //调用微信写数据的方法 传的数据大小控制在20
        wx.writeBLECharacteristicValue({
          deviceId,
          serviceId,
          characteristicId,
          value:printData,
     })
复制代码

3、二维码的打印:

二维码的打印和普通文本打印的区别就在于指令的不同,打印指令需要的是二进制数据长度,可以通过new ArrayBuffer().byteLength获取

复制代码
let instruct = [29, 107, 97, 7, 4, new Uint8Array(GBK.encode('https://www.baidu.com')).buffer.byteLength, 0]  //二维码打印指令 需要打印二进制数组长度
let printData = new Uint8Array([...printCommand.clear,...instruct, ...GBK.encode('https://www.baidu.com'), ...printCommand.enter]).buffer
    //调用微信写数据的方法 传的数据大小控制在20
        wx.writeBLECharacteristicValue({
          deviceId,
          serviceId,
          characteristicId,
          value:printData,
     })
复制代码

4、图片的打印:

5、蓝牙数据写入的递归方法

复制代码
/*封装的微信的蓝牙api */
function wxAsyncPromise(name, options) {
  const fnName = wx[name];
  return new Promise((resolve, reject) => {
    fnName({
      ...(options ? options : {}),
      success: function (res) {
        resolve(res);
      },
      fail: function (res) {
        reject(res);
      },
    });
  });
}
/*发送数据 */
function sendData(obj) {
  //重新获取长度
  let byteLength = obj.value.byteLength;
  //这里默认一次20个字发送
  const speed = 20;
  if (byteLength > 0) {
    wxAsyncPromise('writeBLECharacteristicValue', {
        ...obj,
        value: obj.value.slice(0, byteLength > speed ? speed : byteLength),
      })
      .then((res) => {
        if (byteLength > speed) {
          sendData({
            ...obj,
            value: obj.value.slice(speed, byteLength),
          });
        } else {
          console.log('打印完成')
        }
      })
      .catch((err) => {
        console.log('发送失败', err)
      });
  }
}
复制代码

 

posted @   Pavetr  阅读(395)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示