18、ESC/POS指令集在android设备上使用实例(通过socket)
网上关于通过android来操作打印机的例子太少了,为了方便更多的开发同仁,将近日所学分享一下。
我这边是通过android设备通过无线来对打印机(佳博58mm热敏式-58130iC)操作,实现餐厅小票的打印。写了一个简单的小demo,分享下。
前提:
1、android设备一个(coolPad8085N)
2、小票打印机(佳博 58mm热敏式打印机-58130IC)
这里将打印机IP设置为固定IP(这里略微复杂,是前辈设置过的,我没有具体操作,问了一下:打印机自检出的条子可以显示IP、通过自带或者官网的window管理软件设置)
3、无线路由器一个(从局域网口引出一根网线接到小票打印机网口)
4、android设备连接wifi到同一网络
(这样就保证了android和打印机在同一网络内,并且打印机的IP是固定的,开发人员是知道的,很变态)
流程:
1、android运行app,根据打印机的IP地址和端口号创建套接字socket,得到可写流outputStream
2、根据订单号,获取订单信息(demo是模拟的)
3、套入模板,打印小票
难点在于小票的排版的实现,我做了个工具库,如下:
1 package com; 2 3 4 5 public class printerCmdUtils { 6 7 public static final byte ESC = 27;//换码 8 public static final byte FS = 28;//文本分隔符 9 public static final byte GS = 29;//组分隔符 10 public static final byte DLE = 16;//数据连接换码 11 public static final byte EOT = 4;//传输结束 12 public static final byte ENQ = 5;//询问字符 13 public static final byte SP = 32;//空格 14 public static final byte HT = 9;//横向列表 15 public static final byte LF = 10;//打印并换行(水平定位) 16 public static final byte CR = 13;//归位键 17 public static final byte FF = 12;//走纸控制(打印并回到标准模式(在页模式下) ) 18 public static final byte CAN = 24;//作废(页模式下取消打印数据 ) 19 20 21 22 //------------------------打印机初始化----------------------------- 23 24 25 /** 26 * 打印机初始化 27 * @return 28 */ 29 public static byte[] init_printer() 30 { 31 byte[] result = new byte[2]; 32 result[0] = ESC; 33 result[1] = 64; 34 return result; 35 } 36 37 38 //------------------------换行----------------------------- 39 40 41 /** 42 * 换行 43 * @param lineNum要换几行 44 * @return 45 */ 46 public static byte[] nextLine(int lineNum) 47 { 48 byte[] result = new byte[lineNum]; 49 for(int i=0;i<lineNum;i++) 50 { 51 result[i] = LF; 52 } 53 54 return result; 55 } 56 57 58 //------------------------下划线----------------------------- 59 60 61 /** 62 * 绘制下划线(1点宽) 63 * @return 64 */ 65 public static byte[] underlineWithOneDotWidthOn() 66 { 67 byte[] result = new byte[3]; 68 result[0] = ESC; 69 result[1] = 45; 70 result[2] = 1; 71 return result; 72 } 73 74 75 /** 76 * 绘制下划线(2点宽) 77 * @return 78 */ 79 public static byte[] underlineWithTwoDotWidthOn() 80 { 81 byte[] result = new byte[3]; 82 result[0] = ESC; 83 result[1] = 45; 84 result[2] = 2; 85 return result; 86 } 87 88 89 /** 90 * 取消绘制下划线 91 * @return 92 */ 93 public static byte[] underlineOff() 94 { 95 byte[] result = new byte[3]; 96 result[0] = ESC; 97 result[1] = 45; 98 result[2] = 0; 99 return result; 100 } 101 102 103 //------------------------加粗----------------------------- 104 105 106 /** 107 * 选择加粗模式 108 * @return 109 */ 110 public static byte[] boldOn() 111 { 112 byte[] result = new byte[3]; 113 result[0] = ESC; 114 result[1] = 69; 115 result[2] = 0xF; 116 return result; 117 } 118 119 120 /** 121 * 取消加粗模式 122 * @return 123 */ 124 public static byte[] boldOff() 125 { 126 byte[] result = new byte[3]; 127 result[0] = ESC; 128 result[1] = 69; 129 result[2] = 0; 130 return result; 131 } 132 133 134 //------------------------对齐----------------------------- 135 136 137 /** 138 * 左对齐 139 * @return 140 */ 141 public static byte[] alignLeft() 142 { 143 byte[] result = new byte[3]; 144 result[0] = ESC; 145 result[1] = 97; 146 result[2] = 0; 147 return result; 148 } 149 150 151 /** 152 * 居中对齐 153 * @return 154 */ 155 public static byte[] alignCenter() 156 { 157 byte[] result = new byte[3]; 158 result[0] = ESC; 159 result[1] = 97; 160 result[2] = 1; 161 return result; 162 } 163 164 165 /** 166 * 右对齐 167 * @return 168 */ 169 public static byte[] alignRight() 170 { 171 byte[] result = new byte[3]; 172 result[0] = ESC; 173 result[1] = 97; 174 result[2] = 2; 175 return result; 176 } 177 178 179 /** 180 * 水平方向向右移动col列 181 * @param col 182 * @return 183 */ 184 public static byte[] set_HT_position( byte col ) 185 { 186 byte[] result = new byte[4]; 187 result[0] = ESC; 188 result[1] = 68; 189 result[2] = col; 190 result[3] = 0; 191 return result; 192 } 193 //------------------------字体变大----------------------------- 194 195 196 /** 197 * 字体变大为标准的n倍 198 * @param num 199 * @return 200 */ 201 public static byte[] fontSizeSetBig(int num) 202 { 203 byte realSize = 0; 204 switch (num) 205 { 206 case 1: 207 realSize = 0;break; 208 case 2: 209 realSize = 17;break; 210 case 3: 211 realSize = 34;break; 212 case 4: 213 realSize = 51;break; 214 case 5: 215 realSize = 68;break; 216 case 6: 217 realSize = 85;break; 218 case 7: 219 realSize = 102;break; 220 case 8: 221 realSize = 119;break; 222 } 223 byte[] result = new byte[3]; 224 result[0] = 29; 225 result[1] = 33; 226 result[2] = realSize; 227 return result; 228 } 229 230 231 //------------------------字体变小----------------------------- 232 233 234 /** 235 * 字体取消倍宽倍高 236 * @param num 237 * @return 238 */ 239 public static byte[] fontSizeSetSmall(int num) 240 { 241 byte[] result = new byte[3]; 242 result[0] = ESC; 243 result[1] = 33; 244 245 return result; 246 } 247 248 249 //------------------------切纸----------------------------- 250 251 252 /** 253 * 进纸并全部切割 254 * @return 255 */ 256 public static byte[] feedPaperCutAll() 257 { 258 byte[] result = new byte[4]; 259 result[0] = GS; 260 result[1] = 86; 261 result[2] = 65; 262 result[3] = 0; 263 return result; 264 } 265 266 267 /** 268 * 进纸并切割(左边留一点不切) 269 * @return 270 */ 271 public static byte[] feedPaperCutPartial() 272 { 273 byte[] result = new byte[4]; 274 result[0] = GS; 275 result[1] = 86; 276 result[2] = 66; 277 result[3] = 0; 278 return result; 279 } 280 281 282 //------------------------切纸----------------------------- 283 public static byte[] byteMerger(byte[] byte_1, byte[] byte_2){ 284 byte[] byte_3 = new byte[byte_1.length+byte_2.length]; 285 System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length); 286 System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length); 287 return byte_3; 288 } 289 290 291 public static byte[] byteMerger(byte[][] byteList){ 292 293 int length = 0; 294 for(int i=0;i<byteList.length;i++) 295 { 296 length += byteList[i].length; 297 } 298 byte[] result = new byte[length]; 299 300 int index = 0; 301 for(int i=0;i<byteList.length;i++) 302 { 303 byte[] nowByte = byteList[i]; 304 for(int k=0;k<byteList[i].length;k++) 305 { 306 result[index] = nowByte[k]; 307 index++; 308 } 309 } 310 for(int i =0;i<index;i++) 311 { 312 CommonUtils.LogWuwei("", "result["+i+"] is "+result[i]); 313 } 314 return result; 315 } 316 317 318 319 }
工具库包括字体加粗、字体放大缩小、切纸、换行等基本操作,还有就是对byte数组的拼接,byte数组的拼接有很多方式,只实现了一种方式
效果图:
简单的代码解析:
public byte[] clientPaper() { try { byte[] next2Line = printerCmdUtils.nextLine(2); byte[] title = "出餐单(午餐)**万通中心店".getBytes("gb2312"); byte[] boldOn = printerCmdUtils.boldOn(); byte[] fontSize2Big = printerCmdUtils.fontSizeSetBig(3); byte[] center= printerCmdUtils.alignCenter(); byte[] Focus = "网 507".getBytes("gb2312"); byte[] boldOff = printerCmdUtils.boldOff(); byte[] fontSize2Small = printerCmdUtils.fontSizeSetSmall(3); byte[] left= printerCmdUtils.alignLeft(); byte[] orderSerinum = "订单编号:11234".getBytes("gb2312"); boldOn = printerCmdUtils.boldOn(); byte[] fontSize1Big = printerCmdUtils.fontSizeSetBig(2); byte[] FocusOrderContent = "韭菜鸡蛋饺子-小份(单)".getBytes("gb2312"); boldOff = printerCmdUtils.boldOff(); byte[] fontSize1Small = printerCmdUtils.fontSizeSetSmall(2); next2Line = printerCmdUtils.nextLine(2); byte[] priceInfo = "应收:22元 优惠:2.5元 ".getBytes("gb2312"); byte[] nextLine = printerCmdUtils.nextLine(1); byte[] priceShouldPay = "实收:19.5元".getBytes("gb2312"); nextLine = printerCmdUtils.nextLine(1); byte[] takeTime = "取餐时间:2015-02-13 12:51:59".getBytes("gb2312"); nextLine = printerCmdUtils.nextLine(1); byte[] setOrderTime = "下单时间:2015-02-13 12:35:15".getBytes("gb2312"); byte[] tips_1 = "微信关注\"**\"自助下单每天免1元".getBytes("gb2312"); nextLine = printerCmdUtils.nextLine(1); byte[] tips_2 = "饭后点评再奖5毛".getBytes("gb2312"); nextLine = printerCmdUtils.nextLine(1); byte[] breakPartial = printerCmdUtils.feedPaperCutPartial(); byte[][] cmdBytes= { title,nextLine, center,boldOn,fontSize2Big,Focus,boldOff,fontSize2Small,next2Line, left,orderSerinum,nextLine, center,boldOn,fontSize1Big,FocusOrderContent,boldOff,fontSize1Small,nextLine, left,next2Line, priceInfo,nextLine, priceShouldPay,next2Line, takeTime,nextLine, setOrderTime,next2Line, center,tips_1,nextLine, center,tips_2,next2Line, breakPartial }; return printerCmdUtils.byteMerger(cmdBytes); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; }
字节码拼接过程如下:
1 public static byte[] byteMerger(byte[][] byteList){ 2 3 int length = 0; 4 for(int i=0;i<byteList.length;i++) 5 { 6 length += byteList[i].length; 7 } 8 byte[] result = new byte[length]; 9 10 int index = 0; 11 for(int i=0;i<byteList.length;i++) 12 { 13 byte[] nowByte = byteList[i]; 14 for(int k=0;k<byteList[i].length;k++) 15 { 16 result[index] = nowByte[k]; 17 index++; 18 } 19 } 20 for(int i =0;i<index;i++) 21 { 22 CommonUtils.LogWuwei("", "result["+i+"] is "+result[i]); 23 } 24 return result; 25 }
将上步得到的字节码通过可写流写入套接字,这时小票打印机就会打印对应的内容。
1、demo链接地址如下:
http://pan.baidu.com/s/1eQ9y8mQ
2、参考文章