乐虎游戏|乐虎国际登录|欢迎你

Atitit.收银系统pos 以及打印功能的行业标准

日期:2020-04-15编辑作者:计算机资讯

ag线上开户 1

OG视讯直播,Atitit.收银系统pos 以及打印功能的行业标准

之前公司有个面向商户的项目,需要连接商户打印机打印小票的功能。于是对这方面进行了学习研究,最后“顺利”的完成了项目需求。这里主要是对项目中用到的知识点进行一些总结。这篇文章主要包含的相关知识有:Socketmg4355娱乐城,mg电子游戏娱乐场,CoreBluetooth网口小票打印机蓝牙小票打印机ESC/POS打印命令集ag线上开户,图片打印等。

AG视讯厅, 

整个打印流程大致分可以为三个步骤,①链接打印机;②编辑排版打印内容;③发送数据给打印机;

 

①和③根据不同的打印机类型,我们要采取不同的链接方式。网口打印机通过Socket进行链接,蓝牙打印机自然是通过蓝牙进行链接。②编辑排版打印内容,需要通过ESC/POS打印命令集来做,以下会进行相关的介绍。

mg4355娱乐线路检测,1. ESC指令序列 Escape指令序列不同于ESC/POS指令 1

其实,步骤②编辑排版打印内容,放到后台做是更加合理的,这样Android和iOS两端就避免了都要写编辑排版的代码,而且也能避免排版上的差异。我们公司也是这样做的,所以步骤②就可以改为从后台获取要打印的数据。

2. 打印标准OPOS POSPrinter 与 CashDrawer 驱动1

简介

WPSON StandardCode for Printer 是EPSON公司自己制定的针式打印机的标准化指令集,现在已成为针式打印机控制语言事实上的工业标准。ESC/POS打印命令集是ESC打印控制命令的简化版本,现在大多数票据打印都采用ESC/POS指令集。其显著特征是:其中很大一部分指令都是以ESC控制符开始的一串代码。

打印机的型号种类有很多,不同的厂家也对其产品做了相应的定制。但是,ESC/POS指令集基本都会支持。关于指令的详细内容,网上有很多文档,另外每个品牌的官网,也会有对应的打印机指令文档提供下载。我们可以下载下来研究。这里简单介绍几种常用的指令:

3. 命令集2

指令介绍

说明:一般打印机接受指令都支持三种格式:ASCII、十进制、十六进制。

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

说明:清除打印缓冲区,删除用户自定义字符,打印模式被设为上电时的默认值模式。

代码:

//重置打印机- resetPrinter { Byte reset[] = {0x1B,0x40}; [self.printData appendBytes:reset length:1];}

注意:经笔者测试发现,使用初始化命令,之后的一条命令可能会失效,目前未找到原因,可能是打印机问题。另外,由于此命令会清除缓冲区,频繁调用可能会导致数据丢失,因此尽量少用此命令。

ASCII 十进制 十六进制
LF 10 0A

说明:将打印缓冲区中的数据打印出来,并且按照当前行间距,把打印纸向前推进一行。

代码:

//打印机并换行- printAndNewline { Byte next[] = {0x0A}; [self.printData appendBytes:next length:1];}
ASCII 十进制 十六进制
LESC J n 27 74 n 1B 4A n

说明:打印缓冲区数据并走纸[ n × 纵向或横向移动单位] 英寸。0 ≤n ≤ 255。最大走纸距离是956 mm(不同品牌打印机数值不同)。如果超出这个距离,取最大距离。

代码:

//打印缓冲区数据,并往前走纸n点行- printAndGoNPointLine:n { Byte line[] = {0x1B, 0x4A, n}; [self.printData appendBytes:line length:3];}

注意:这里是走纸点行数,要与字符行数区分

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

说明:打印缓冲区里的数据并向前走纸n行。0 ≤n ≤ 255。该命令不影响由ESC 2 或ESC 3设置的行间距。 最大走纸距离为1016 mm,当所设的值大于1016 mm时,取最大值。

代码:

//打印缓冲区数据,并往前走纸n行- printAndGoNLine:n { Byte line[] = {0x1B, 0x64, n}; [self.printData appendBytes:line length:3];}

注意:这里是走纸字符行数,要与点行数区分。只有设置了行距后,此命令才有效。使用此命令前,要先使用换行指令,否则设置无效

ASCII 十进制 十六进制
ESC 2 27 50 1B 32

说明:选择约3.75mm 行间距。约34个点。

代码:

//设置默认行间距- printDefaultLineSpace { Byte defaultLineSpace[] = {0x1B,0x32}; [self.printData appendBytes:defaultLineSpace length:2];}
ASCII 十进制 十六进制
ESC 3 n 27 51 n 1B 33 n

说明:设置行间距为[ n × 纵向或横向移动单位] 英寸。

代码:

//设置行间距为n个点- printLineSpace:n { Byte lineSpace[] = {0x1B,0x33,n}; [self.printData appendBytes:lineSpace length:3];}

注意:使用此命令前,要先使用换行指令,否则设置无效

ASCII 十进制 十六进制
ESC SP n 27 32 n 1B 20 n

说明:设置字符的右间距为[n×横向移动单位或纵向移动单位]英寸。0 ≤ n ≤255。最大右间距是31.91毫米(255/203 英寸)。任何超过这个值的设置都自动转换为最大右间距。

代码:

//字符右间距- printCharRightSpace:n { Byte line[] = {0x1B, 0x20, n}; [self.printData appendBytes:line length:3];}

注意:此命令对汉字无效

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

说明:n = 0或48 为左对齐;n = 1或49为中间对齐;n = 2或50位右对齐。

代码:

//设置对齐方式- setAlignment:(MNAlignmentType)alignmentType { Byte align[] = {0x1B,0x61,alignmentType}; [self.printData appendBytes:align length:3];}
ASCII 十进制 十六进制
GS ! n 29 33 n 1D 21 n

说明:用0 到2 位选择字符高度,4 到7 位选择字符宽度。ag线上开户 2

代码:

//字符放大倍数typedef enum: UInt8 { MNPrintFont_1 = 0x00, MNPrintFont_2 = 0x11, MNPrintFont_3 = 0x22, MNPrintFont_4 = 0x33, MNPrintFont_5 = 0x44, MNPrintFont_6 = 0x55, MNPrintFont_7 = 0x66, MNPrintFont_8 = 0x77,} MNPrintFont;//设置字体大小-printCharSize:(MNPrintFont)printFont { Byte font[] = {0x1D,0x21,printFont}; [self.printData appendBytes:font length:3];};
ASCII 十进制 十六进制
GS V m 29 86 m 1D 56 m
ASCII 十进制 十六进制
GS V m n 29 86 m n 1D 56 m n

说明:

  • m=0,1,49 ;0 表示全切, 1表示半切,当打印机没有半切功能时,全切;
  • m=66, 0≤n≤255 ;当m=66时, n表示走纸到+[n*0.125mm] 位置切纸

代码:

//切纸模式typedef enum :UInt8 { MNCutPaperModelFull = 0x00, MNCutPaperModelHalf = 0x01, MNCutPaperModelFeedPaperHalf = 0x66}MNCutPaperModel;- printCutPaper:(MNCutPaperModel)model Num:n { if (model == MNCutPaperModelFull) { Byte cut[] = {0x1D, 0x56, model, n}; [self.printData appendBytes:cut length:4]; } else { Byte cut[] = {0x1D, 0x56, model}; [self.printData appendBytes:cut length:3]; }}

注意这条指令需要打印机支持切纸

ASCII 十进制 十六进制
ESC p m t1 t2 27 112 m t1 t2 1B 70 m t1 t2

说明:

  • m = 0, 1, 48, 49 ; 0 ≤ t1 ≤ 255, 0 ≤ t2 ≤ 255 ;
  • 输出由t1和t2设定的钱箱开启脉冲到由m指定的引脚:
M 十进制
0, 48 钱箱插座的引脚 2
1, 49 钱箱插座的引脚 5

代码:

//产生钱箱控制脉冲,一般一个打印机连接一个钱箱,这里默认写死了-printOpenCashDrawer { Byte open[] = {0x1B, 0x70, 0x00, 0x80, 0xFF}; [self.printData appendBytes:open length:5];}

注意这条指令需要打印机连接钱箱

4. Java框架jpos3

打印内容

说明:这里只要将打印内容通过kCFStringEncodingGB_18030_2000编码,然后发送给打印机

代码:

- printWithContent:(NSString *)content { NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000); NSData *data = [content dataUsingEncoding:enc]; [self.printData appendData:data];}

以上只是部分指令,可根据需求,参考指令集文档再做相应的添加。这里要提一下的是,小票打印多用于订单详情类信息,为了是排版更美观,这里用的比较多的是制表符/t来使每一列对齐,可以直接这样使用[self.printManager printWithContent:@"t"];

5. jpos.JposException: Service does not exist in loaded JCL registry3

图片打印

关于图片打印,这里介绍两种打印指令:

ag线上开户 3位图模式.pngag线上开户 4光栅位图.png

因为小票打印机多为热敏打印机,或针式打印机,且颜色只有黑白两色。因此,要打印图片,首先要获取图片的像素数据,然后将图片进行黑白二值化处理,之后拼接打印数据,黑色为打印的点,白色为不打印的点。如此逐行打印图片数据。

-scaleImageWithImage:image width:(NSInteger)width height:(NSInteger)height{ CGSize size; size.width = width; size.height = height; UIGraphicsBeginImageContext; [image drawInRect:CGRectMake(0, 0, width, height)]; UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return scaledImage;}
  • 获取图像像素可以参考Getting the pixel data from a CGImage object;
-(CGContextRef)CreateARGBBitmapContextWithCGImageRef:(CGImageRef)inImage{ CGContextRef context = NULL; CGColorSpaceRef colorSpace; void * bitmapData; int bitmapByteCount; int bitmapBytesPerRow; // Get image width, height. We'll use the entire image. size_t pixelsWide = CGImageGetWidth; size_t pixelsHigh = CGImageGetHeight; // Declare the number of bytes per row. Each pixel in the bitmap in this // example is represented by 4 bytes; 8 bits each of red, green, blue, and // alpha. bitmapBytesPerRow = (pixelsWide * 4); bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); // Use the generic RGB color space. colorSpace =CGColorSpaceCreateDeviceRGB(); if (colorSpace == NULL) { return NULL; } // Allocate memory for image data. This is the destination in memory // where any drawing to the bitmap context will be rendered. bitmapData = malloc( bitmapByteCount ); if (bitmapData == NULL) { CGColorSpaceRelease( colorSpace ); return NULL; } // Create the bitmap context. We want pre-multiplied ARGB, 8-bits // per component. Regardless of what the source image format is // (CMYK, Grayscale, and so on) it will be converted over to the format // specified here by CGBitmapContextCreate. context = CGBitmapContextCreate (bitmapData, pixelsWide, pixelsHigh, 8, // bits per component bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedFirst); if (context == NULL) { free (bitmapData); } // Make sure and release colorspace before returning CGColorSpaceRelease( colorSpace ); return context;}
  • 根据像素信息将图片进行黑白化处理,并逐行拼接打印信息
typedef enum { ALPHA = 0, BLUE = 1, GREEN = 2, RED = 3} PIXELS;-  imageToThermalData:image { CGImageRef imageRef = image.CGImage; // Create a bitmap context to draw the uiimage into CGContextRef context = [self CreateARGBBitmapContextWithCGImageRef:imageRef]; if { return NULL; } size_t width = CGImageGetWidth; size_t height = CGImageGetHeight; CGRect rect = CGRectMake(0, 0, width, height); // Draw image into the context to get the raw image data CGContextDrawImage(context, rect, imageRef); // Get a pointer to the data uint32_t *bitmapData = (uint32_t *)CGBitmapContextGetData; if(bitmapData) { uint8_t *m_imageData = (uint8_t *) malloc(width * height/8 + 8*height/8); memset(m_imageData, 0, width * height/8 + 8*height/8); int result_index = 0; for(int y = 0;  < height;) { m_imageData[result_index++] = 27; m_imageData[result_index++] = 51; m_imageData[result_index++] = 0; m_imageData[result_index++] = 27; m_imageData[result_index++] = 42; m_imageData[result_index++] = 33; m_imageData[result_index++] = width%256; m_imageData[result_index++] = width/256; for(int x = 0; x < width; x++) { int value = 0; for (int temp_y = 0 ; temp_y < 8; ++temp_y) { uint8_t *rgbaPixel = (uint8_t *) &bitmapData[ * width + x]; uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE]; if (gray < 127) { value += 1<<&255; } } m_imageData[result_index++] = value; value = 0; for (int temp_y = 8 ; temp_y < 16; ++temp_y) { uint8_t *rgbaPixel = (uint8_t *) &bitmapData[ * width + x]; uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE]; if (gray < 127) { value += 1<<(7-temp_y%8)&255; } } m_imageData[result_index++] = value; value = 0; for (int temp_y = 16 ; temp_y < 24; ++temp_y) { uint8_t *rgbaPixel = (uint8_t *) &bitmapData[ * width + x]; uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE]; if (gray < 127) { value += 1<<(7-temp_y%8)&255; } } m_imageData[result_index++] = value; } m_imageData[result_index++] = 13; m_imageData[result_index++] = 10; y += 24; } NSMutableData *data = [[NSMutableData alloc] initWithCapacity:0]; [data appendBytes:m_imageData length:result_index]; free(bitmapData); return data; } else { NSLog(@"Error getting bitmap pixel datan"); } CGContextRelease; return nil ;}

#pragma mark ********************另一种打印图片的方式****************************typedef struct ARGBPixel { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; } ARGBPixel ;#pragma mark 获取打印图片数据-getDataForPrintWith:(UIImage *)image{ CGImageRef cgImage = [image CGImage]; size_t width = CGImageGetWidth; size_t height = CGImageGetHeight; NSData* bitmapData = [self getBitmapImageDataWith:cgImage]; const char * bytes = bitmapData.bytes; NSMutableData * data = [[NSMutableData alloc] init]; //横向点数计算需要除以8 NSInteger w8 = width / 8; //如果有余数,点数+1 NSInteger remain8 = width % 8; if (remain8 > 0) { w8 = w8 + 1; } /** 根据公式计算出 打印指令需要的参数 指令:十六进制码 1D 76 30 m xL xH yL yH d1...dk m为模式,如果是58毫秒打印机,m=1即可 xL 为宽度/256的余数,由于横向点数计算为像素数/8,因此需要 xL = width/ xH 为宽度/256的整数 yL 为高度/256的余数 yH 为高度/256的整数 **/ NSInteger xL = w8 % 256; NSInteger xH = width / ; NSInteger yL = height % 256; NSInteger yH = height / 256; Byte cmd[] = {0x1d,0x76,0x30,0,xL,xH,yL,yH}; [data appendBytes:cmd length:8]; for (int h = 0; h < height; h++) { for (int w = 0; w < w8; w++) { u_int8_t n = 0; for (int i=0; i<8; i++) { int x = i + w * 8; u_int8_t ch; if (x < width) { int pindex = h * width + x; ch = bytes[pindex]; } else{ ch = 0x00; } n = n << 1; n = n | ch; } [data appendBytes:&n length:1]; } } return data;}#pragma mark 获取图片点阵图数据-getBitmapImageDataWith:(CGImageRef)cgImage{ size_t width = CGImageGetWidth; size_t height = CGImageGetHeight; NSInteger psize = sizeof(ARGBPixel); ARGBPixel * pixels = malloc(width * height * psize); NSMutableData* data = [[NSMutableData alloc] init]; [self ManipulateImagePixelDataWithCGImageRef:cgImage imageData:pixels]; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int pIndex = (w + (h * (u_int32_t)width)); ARGBPixel pixel = pixels[pIndex]; if ((0.3*pixel.red + 0.59*pixel.green + 0.11*pixel.blue) <= 127) { //打印黑 u_int8_t ch = 0x01; [data appendBytes:&ch length:1]; } else{ //打印白 u_int8_t ch = 0x00; [data appendBytes:&ch length:1]; } } } return data;}// 获取像素信息-ManipulateImagePixelDataWithCGImageRef:(CGImageRef)inImage imageData:oimageData{ // Create the bitmap context CGContextRef cgctx = [self CreateARGBBitmapContextWithCGImageRef:inImage]; if (cgctx == NULL) { // error creating context return; } // Get image width, height. We'll use the entire image. size_t w = CGImageGetWidth; size_t h = CGImageGetHeight; CGRect rect = {{0,0},{w,h}}; // Draw the image to the bitmap context. Once we draw, the memory // allocated for the context for rendering will then contain the // raw image data in the specified color space. CGContextDrawImage(cgctx, rect, inImage); // Now we can get a pointer to the image data associated with the bitmap // context. void *data = CGBitmapContextGetData; if (data != NULL) { CGContextRelease; memcpy(oimageData, data, w * h * sizeof * 4); free; return; } // When finished, release the context CGContextRelease; // Free image data memory for the context if  { free; } return;}

//打印图片- printWithImage:(UIImage *)image width:width height:height { UIImage * printImage = [self scaleImageWithImage:image width:width height:height]; NSData *data = [self imageToThermalData:printImage]; [self.printData appendData:data];}

由于打印图片是根据像素点来逐行打印,因此数据量会远高于普通文字,这就造成了打印图片的速度回比文字慢,尤其是蓝牙打印机。解决方法可以从两个方面入手,1、增加每次发送的数据量(主要针对蓝牙打印机);2、减少图片的数据量。

5.1.1. (JCL) Jar Class Loader 3

本文由乐虎游戏发布于计算机资讯,转载请注明出处:Atitit.收银系统pos 以及打印功能的行业标准

关键词:

计算机在iOS开垦中应用Protobuf

Protobuf简介 protocolbuffer 是google的一种数据交换的格式,它独立于语言,独立于平台。google提供了多种语言的实现:j...

详细>>

深入剖析Objective-C中的Swizzle

method_name是函数的选择器,method_type是参数和返回值类型编码的c字符串,method_imp是指向实际函数的函数指针。可以通过下...

详细>>

计算机iOS-ReactiveCocoa学习笔记1

①. 简化响应式函数的模式 在Swift中,我们有几种响应式的开发模式:target-action、代理、通知中心、KVO等。以上每个...

详细>>

自个儿的局地iOS进级路上的素材采取

其实就是我个人在具备初级开发能力后,进一步的提升技术能力和知识面的途径。 ** 本文摘自同行说用户“星空”分...

详细>>