1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Android 蓝牙/wifi云打印机 ESC/POS热敏打印机打印(ESC/POS指令篇)

Android 蓝牙/wifi云打印机 ESC/POS热敏打印机打印(ESC/POS指令篇)

时间:2023-11-08 09:00:26

相关推荐

Android 蓝牙/wifi云打印机  ESC/POS热敏打印机打印(ESC/POS指令篇)

上一篇主要介绍了如何通过蓝牙打印机和wifi云打印机的连接与数据发送,这一篇,我们就介绍向打印机发送打印指令,来打印字符和图片。

由于公司暂且买了两台打印机,一台佳博GP-58MIII,一台GP-SH584。

我们先来看一下最终票据打印效果图:

一、ESC/POS指令

ESC/POS指令体系是由EPSON发明的一套专有POS打印机指令系统,市面上绝大部分打印机兼容ESC/POS指令。

由于我使用的是佳博的蓝牙打印机,我们来看一下佳博打印机背后的型号说明:

上图可见,两台打印机是58mm纸宽的打印机,一台支持USB和蓝牙连接,一台支持USB和wifi云,并且都支持ESC/POS命令。

二、常用的打印命令

手机通过蓝牙或者ip端口向打印机发送的都是纯字节流。打印机通过遵循ESC/POS指令控制打印。

2.1 初始化打印机

指令:该指令会清除打印缓冲区中的数据,但是接收缓冲区的数据并不会清除,一般开始打印的时候需要调用。

ASCII码 ESC @十进制码 27 64十六进制码 1B 40

佳博SDK将ESC指令封装成了一个EsCommand类,对应的代码如下:

EscCommand esc = new EscCommand();esc.addInitializePrinter();//初始化打印机//SDK源码内部public void addInitializePrinter() {byte[] command = new byte[]{27, 64};this.addArrayToCommand(command);}//此处省略了部分核心代码outputStream.write(esc.getCommand , offset, len);...

2.2 打印文本

没有对应指令,直接输出文本

// 打印文字esc.addText("发货单\n");public void addText(String text) {this.addStrToCommand(text);}

2.3 打印多列文本

通用打印纸都是有固定宽度的,比如58mm打印纸最大宽度为384个像素店,80mm打印纸最大宽度为576个像素点。经过大量测试结果表明,一般最大字节数是32个字节(总宽度 = 左侧宽度 + 右侧宽度)

/*** 左侧宽度 + 右侧宽度 = 打印纸总宽度* 打印纸一行最大的字节*/private static final int LINE_BYTE_SIZE = 32;/*** 打印三列时,中间一列的中心线距离打印纸左侧的距离*/private static final int LEFT_LENGTH = 16;/*** 打印三列时,中间一列的中心线距离打印纸右侧的距离*/private static final int RIGHT_LENGTH = 16;/*** 打印四列时,第一列居左,第二列居中,第四列居右,第三列位于第二列和第四列中间* 第三列距离第二列的距离*/private static final int MIDDLE_RIGHT_MIDDLE_LENGTH = 8;/*** 打印四列时,第一列居左,第二列居中,第四列居右,第三列位于第二列和第四列中间* 第三列距离第四列的距离*/private static final int MIDDLE_RIGHT_MIDDLE_RIGHT = 8;/*** 打印三列时,第一列汉字最多显示几个文字*/private static final int LEFT_TEXT_MAX_LENGTH = 5;

当我们打印两列时,一列居左,一列居右;打印三列时,一列居左,一列居中,一列居右。那两列之间的空格,我们用下面的方法可以完美的计算出来剩余空格。这样就不用手动添加多个空格了。

/*** 获取数据长度** @param msg* @return*/@SuppressLint("NewApi")private static int getBytesLength(String msg) {return msg.getBytes(Charset.forName("GB2312")).length;}/*** 打满一列列** @return*/@SuppressLint("NewApi")public static String printOneFullData() {StringBuilder sb = new StringBuilder();for (int i = 0; i < LINE_BYTE_SIZE; i++) {sb.append("-");}return sb.toString();}/*** 打印两列** @param leftText 左侧文字* @param rightText 右侧文字* @return*/@SuppressLint("NewApi")public static String printTwoData(String leftText, String rightText) {StringBuilder sb = new StringBuilder();int leftTextLength = getBytesLength(leftText);int rightTextLength = getBytesLength(rightText);sb.append(leftText);// 计算两侧文字中间的空格int marginBetweenMiddleAndRight = LINE_BYTE_SIZE - leftTextLength - rightTextLength;for (int i = 0; i < marginBetweenMiddleAndRight; i++) {sb.append(" ");}sb.append(rightText);return sb.toString();}/*** 打印三列** @param leftText 左侧文字* @param middleText 中间文字* @param rightText 右侧文字* @return*/@SuppressLint("NewApi")public static String printThreeData(String leftText, String middleText, String rightText) {StringBuilder sb = new StringBuilder();// 左边最多显示 LEFT_TEXT_MAX_LENGTH 个汉字 + 两个点if (leftText.length() > LEFT_TEXT_MAX_LENGTH) {leftText = leftText.substring(0, LEFT_TEXT_MAX_LENGTH) + "..";}int leftTextLength = getBytesLength(leftText);int middleTextLength = getBytesLength(middleText);int rightTextLength = getBytesLength(rightText);sb.append(leftText);// 计算左侧文字和中间文字的空格长度int marginBetweenLeftAndMiddle = LEFT_LENGTH - leftTextLength - middleTextLength / 2;for (int i = 0; i < marginBetweenLeftAndMiddle; i++) {sb.append(" ");}sb.append(middleText);// 计算右侧文字和中间文字的空格长度int marginBetweenMiddleAndRight = RIGHT_LENGTH - middleTextLength / 2 - rightTextLength;for (int i = 0; i < marginBetweenMiddleAndRight; i++) {sb.append(" ");}// 打印的时候发现,最右边的文字总是偏右一个字符,所以需要删除一个空格sb.delete(sb.length() - 1, sb.length()).append(rightText);return sb.toString();}/*** 打印四列** @param leftText 左侧文字* @param middleText 中间文字* @param middleAndThirdText 中间与右侧中间的文字* @param rightText右侧文字* @return*/@SuppressLint("NewApi")public static String printFourData(String leftText, String middleText, String middleAndThirdText, String rightText) {StringBuilder sb = new StringBuilder();// 左边最多显示 LEFT_TEXT_MAX_LENGTH 个汉字 + 两个点if (leftText.length() > LEFT_TEXT_MAX_LENGTH) {leftText = leftText.substring(0, LEFT_TEXT_MAX_LENGTH) + "..";}int leftTextLength = getBytesLength(leftText);int middleTextLength = getBytesLength(middleText);int rightTextLength = getBytesLength(rightText);int middleAndThirdTextLength = getBytesLength(middleAndThirdText);sb.append(leftText);// 计算左侧文字和中间文字的空格长度int marginBetweenLeftAndMiddle = LEFT_LENGTH -leftTextLength -(middleTextLength > 1 ? middleTextLength / 2 : 1);for (int i = 0; i < marginBetweenLeftAndMiddle; i++) {sb.append(" ");}sb.append(middleText);//计算中间文字和第三列文字的空格长度int marginBetweenMiddleAndThirdText = MIDDLE_RIGHT_MIDDLE_LENGTH -(middleTextLength > 1 ? middleTextLength / 2 : 1) -(middleAndThirdTextLength > 1 ? middleAndThirdTextLength / 2 : 1);for (int i = 0; i < marginBetweenMiddleAndThirdText; i++) {sb.append(" ");}sb.append(middleAndThirdText);// 计算第三列文字文字和右侧文字的空格长度int marginBetweenThirdTextAndRight = MIDDLE_RIGHT_MIDDLE_RIGHT - (middleAndThirdTextLength > 1 ? middleAndThirdTextLength / 2 : 1) - rightTextLength;for (int i = 0; i < marginBetweenThirdTextAndRight; i++) {sb.append(" ");}// 打印的时候发现,最右边的文字总是偏右一个字符,所以需要删除一个空格// sb.delete(sb.length() - 1, sb.length()).append(rightText);sb.append(rightText);return sb.toString();}

2.4 设置对齐方式

指令:

ASCII码 ESC a n十进制码 27 97 n十六进制码 1B 61 n

n的取值,0左对齐,1中间对齐,2右对齐。

// 设置打印居中esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);public void addSelectJustification(EscCommand.JUSTIFICATION just) {byte[] command = new byte[]{27, 97, just.getValue()};this.addArrayToCommand(command);}public static enum JUSTIFICATION {LEFT(0),//左对齐CENTER(1),//居中RIGHT(2);//右对齐private final int value;private JUSTIFICATION(int value) {this.value = value;}public byte getValue() {return (byte)this.value;}}

2.5 字体倍高倍宽

指令:

ASCII码 ESC ! n十进制码 27 33 n十六进制码 1B 21 n

n的取值,0正常,16倍高,32倍宽,128下划线

// 设置为倍高倍宽esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.ON, EscCommand.ENABLE.ON, EscCommand.ENABLE.OFF);// 取消倍高倍宽esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);//SDK源码public void addSelectPrintModes(EscCommand.FONT font, EscCommand.ENABLE emphasized, EscCommand.ENABLE doubleheight, EscCommand.ENABLE doublewidth, EscCommand.ENABLE underline) {byte temp = 0;if (font == EscCommand.FONT.FONTB) {temp = 1;}if (emphasized == EscCommand.ENABLE.ON) {temp = (byte)(temp | 8);}if (doubleheight == EscCommand.ENABLE.ON) {temp = (byte)(temp | 16);}if (doublewidth == EscCommand.ENABLE.ON) {temp = (byte)(temp | 32);}if (underline == EscCommand.ENABLE.ON) {temp = (byte)(temp | 128);}byte[] command = new byte[]{27, 33, temp};this.addArrayToCommand(command);}

2.6 打印并走纸n行

指令:

ASCII码 ESC d n十进制码 27 100 n十六进制码 1B 64 n

//打印走纸多少行esc.addPrintAndFeedLines((byte) 3);//SDK源码public void addPrintAndFeedLines(byte n) {byte[] command = new byte[]{27, 100, n};this.addArrayToCommand(command);}

三、打印条码

3.1 条码高度指令

ASCII码 GS h n十进制码 29 104 n十六进制码 1D 68 n

n介于1到255之间,n默认值为162

public void addSetBarcodeHeight(byte height) {byte[] command = new byte[]{29, 104, height};this.addArrayToCommand(command);}

3.2 条码宽度指令

ASCII码 GS w n十进制码 29 119 n十六进制码 1D 77 n

n介于2到6之间,默认n=3

public void addSetBarcodeHeight(byte height) {byte[] command = new byte[]{29, 104, height};this.addArrayToCommand(command);}

3.3 打印条码

esc.addSetBarcodeHeight((byte) 80); //设置条码高度为80点esc.addSetBarcodeWidth((byte) 3); // 设置条码单元宽度为3esc.addCODE128(esc.genCode128("11080001"));public void addCODE128(String content) {byte[] command = new byte[]{29, 107, 73, (byte)content.length()};this.addArrayToCommand(command);this.addStrToCommand(content, command[3]);}

四、打印二维码

QRCode命令打印,此命令只在支持QRCode命令打印的机型才能使用。 在不支持二维码指令打印的机型上,则需要发送二维条码图片。

// 设置纠错等级esc.addSelectErrorCorrectionLevelForQRCode((byte) 0x31);// 设置qrcode模块大小esc.addSelectSizeOfModuleForQRCode((byte) 10);// 设置qrcode内容esc.addStoreQRCodeData("");// 打印QRCodeesc.addPrintQRCode();

五、打印图片

很多小票上面会附上二维码或者logo,当打印机不支持二维码指令时,可以打印二维码的图片。由于热敏打印机只能打印黑白两色,所以首先需要把图片转成纯黑白的,再调用图片打印指令进行打印。

5.1 图片分辨率调整

58mm的热敏打印机,可打印区域最大宽度时384个像素点。80mm打印机可打印区域最大宽度为576个像素点。如果分辨率过大,超出了打印机可打印的最大宽度,那么超出部分将无法打印。所以在打印之前,我们需要调整图片的分辨率。

Bitmap b = BitmapFactory.decodeResource(App.getContext().getResources(), R.drawable.gprinter);esc.addRastBitImage(b, 384, 0);

public void addRastBitImage(Bitmap bitmap, int nWidth, int nMode) {if (bitmap != null) {//因为横向每8个像素店组成一个字节,这里将位图宽度规范化为8的整数倍int width = (nWidth + 7) / 8 * 8;int height = bitmap.getHeight() * width / bitmap.getWidth();Bitmap grayBitmap = GpUtils.toGrayscale(bitmap);Bitmap rszBitmap = GpUtils.resizeImage(grayBitmap, width, height);byte[] src = GpUtils.bitmapToBWPix(rszBitmap);byte[] command = new byte[8];height = src.length / width;command[0] = 29;command[1] = 118;command[2] = 48;command[3] = (byte)(nMode & 1);command[4] = (byte)(width / 8 % 256);command[5] = (byte)(width / 8 / 256);command[6] = (byte)(height % 256);command[7] = (byte)(height / 256);this.addArrayToCommand(command);byte[] codecontent = GpUtils.pixToEscRastBitImageCmd(src);for(int k = 0; k < codecontent.length; ++k) {mand.add(codecontent[k]);}} else {Log.d("BMP", "bmp. null ");}}/*** 图片去色,返回灰度图片**/public static Bitmap toGrayscale(Bitmap bmpOriginal) {int height = bmpOriginal.getHeight();int width = bmpOriginal.getWidth();Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Config.RGB_565);Canvas c = new Canvas(bmpGrayscale);Paint paint = new Paint();ColorMatrix cm = new ColorMatrix();cm.setSaturation(0.0F);ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);paint.setColorFilter(f);c.drawBitmap(bmpOriginal, 0.0F, 0.0F, paint);return bmpGrayscale;}

github地址:/zoujin6649/PrinterDemo

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。