热敏打印机编程

在刚接触热敏打印机的时候,觉得这玩儿意还挺神奇的,这么小个东西,完全摆脱了我之前对打印机笨笨的映像,更神奇的是这东西不需要墨,于是去度娘了下,才发现跟普通的喷墨打印机有本质不同,它是通过打印头加热,使得纸上显示想要的图案,因此这个纸也不一般,表层有特殊的化学涂料,所以以后去超时,饭店吃饭,可不要随随便便的把各种小票放嘴里,其连接方式又可分为网络,蓝牙,USB,串口等等,作为码农来说连接方式与我何干,我只关心如何按照指令打印出我想要的东西,下面逐一介绍。

  1.指令集

  几乎看到的所有的热敏打印机都支持EPSON的ESC POS指令,因此首先可以去度娘上找一份热敏打印机指令集,阅读一番

  2.打印纸宽度

  目前市面上主要有两种宽度的打印机,58mm和80mm,这是指打印纸的宽度,其中80mm对应384pt,80mm对应586pt

  2.打印方式

  (1) 位图模式打印,通过文档发现支持位图打印模式,可以打印图片,就意味着我们可以通过随意定制html模板,然后填充数据,最后渲染成图片,对于打印机来说,就是打印图片,一个接口就可以搞定所有问题,这里只是提供一种思路,具体细节实现不在这里发散,感兴趣可以私信我,通过我们的实践,这种打印方式打印出来的效果最好,字体不受打印机限制,可以打印的特别清楚,这也是最为推荐的一种方式,有几个坑需要注意:

  a.通过渲染成图片打印并不适应于串口打印机,原因是渲染成图片数据量较大,而串口的传输速度明显不能满足,实测完美支持网口和USB打印机,没有测过蓝牙打印机

  b.谨防打印机内存溢出,不停的打印乱码,当图片很长的时候,需要进行截断打印,例如一张图片是576*10240,可以截成10章576*1024

  (2) 通过指令集进行打印,按照指令集文档进行打印,这种打印的优点就是数据量小,非常适合串口打印机,缺点是格式受限制,字体受限制,打出来的小票没有图片打印方式好看,下面是我们在打印过程中的一些常用命令的实现

printerprotocal.h

 1 #ifndef PRINTERPROTOCAL_H
 2 #define PRINTERPROTOCAL_H
 3 #include <vector>
 4 #include <string>
 5 #define SERIAL_SIZE 8
 6 class PrinterProtocal {
 7  private:
 8   std::vector<std::string> data_;
 9   std::string tmp_data_;
10   PrinterProtocal &writeString(std::string str);
11   PrinterProtocal &writeByte(std::initializer_list<uint8_t>);
12  public:
13   PrinterProtocal();
14   enum CharacterSet {
15     USA,
16     FRANCE,
17     GERMANY,
18     UK,
19     DENMARK,
20     SWEDEN,
21     ITALY,
22     SPAIN,
23     JAPAN,
24     NORWAY,
25     DENMARK2,
26     SPAIN2,
27     LATINAMERICA,
28     KOREA,
29     Slovenia,
30     Chinese
31   };
32
33   enum CodeTable {
34     PC437,
35     PC850,
36     CHINESE = 30
37   };
38
39   enum AlignMode {
40     LEFT,
41     MIDDLE,
42     RIGHT
43   };
44
45   enum PrintReadable {
46     NONE,
47     ABOVE,
48     BELOW,
49     BOTH
50   };
51
52   enum BarcodeType {
53     UPCA,
54     UPCE,
55     EAN13,
56     EAN8,
57     CODE39,
58     I25,
59     CODEBAR,
60     CODE93,
61     CODE128,
62     CODE11,
63     MSI
64   };
65
66
67   PrinterProtocal &write(std::string str, int32_t size = 0, char ch = ‘ ‘);
68   PrinterProtocal &init();
69   PrinterProtocal &reset();
70   PrinterProtocal &setFontSize(uint8_t);
71   PrinterProtocal &setControlParameter(uint8_t heatingDots = 20,
72                                        uint8_t heatingTime = 255, uint8_t heatingInterval = 250);
73   PrinterProtocal &setSleepTime(uint8_t seconds = 0);
74   PrinterProtocal &setStatus(bool state = true);
75   PrinterProtocal &setPrintDensity(uint8_t printDensity = 14,
76                                    uint8_t printBreakTime = 4);
77
78   PrinterProtocal &setDoubleWidth(bool state = false);
79   PrinterProtocal &setBold(bool state = false);
80   PrinterProtocal &setReverse(bool state = false);
81   PrinterProtocal &setUpDown(bool state = false);
82   PrinterProtocal &setUnderline(bool state = false);
83   PrinterProtocal &setKeyPanel(bool state = false);
84
85   PrinterProtocal &setCharacterSet(CharacterSet set = USA);
86   PrinterProtocal &setCodeTable(CodeTable table = PC437);
87   PrinterProtocal &feed();
88   PrinterProtocal &feed(uint8_t lines);
89   PrinterProtocal &setLineSpacing(uint8_t spacing = 32);
90   PrinterProtocal &setAlign(AlignMode align = LEFT);
91   PrinterProtocal &setLeftBlankCharNums(uint8_t space = 0);
92   PrinterProtocal &setMarginBottom(uint8_t lines = 100);
93   std::vector<std::string> getResult();
94   PrinterProtocal &done();
95 };
96
97 #endif // PRINTERPROTOCAL_H

printerprotocal.cpp

  1 #include "printerprotocal.h"
  2 #include <unistd.h>
  3 #include "base/string_helper.h"
  4 PrinterProtocal::PrinterProtocal() {
  5   reset();
  6 }
  7
  8
  9 // write single byte
 10 PrinterProtocal &PrinterProtocal::writeByte(std::initializer_list<uint8_t>
 11     params) {
 12   //先清理
 13   if ((params.size() + tmp_data_.size()) > SERIAL_SIZE) {
 14     done();
 15   }
 16   for (auto ch : params) {
 17     tmp_data_.push_back(ch);
 18   }
 19   return *this;
 20 }
 21
 22 // write a string
 23 PrinterProtocal &PrinterProtocal::writeString(std::string str) {
 24   for (auto ch : str) {
 25     if (tmp_data_.size() >= SERIAL_SIZE) {
 26       done();
 27     }
 28     tmp_data_.push_back(ch);
 29   }
 30   return *this;
 31 }
 32 //输入str,如果长度小于size,不足的部分用空格填充
 33 PrinterProtocal &PrinterProtocal::write(std::string str, int32_t size,
 34                                         char ch) {
 35   std::string gbk_str = StringHelper::GetGBK(str);
 36   while (static_cast<int>(gbk_str.size()) < size) {
 37     gbk_str.push_back(ch);
 38   }
 39   writeString(gbk_str);
 40   return *this;
 41 }
 42 PrinterProtocal &PrinterProtocal::done() {
 43   if (tmp_data_.size() > 0) {
 44     data_.push_back(tmp_data_);
 45     tmp_data_.clear();
 46   }
 47   return *this;
 48 }
 49
 50 // initialize the printer
 51 PrinterProtocal &PrinterProtocal::init() {
 52   writeByte({27, 64}).done();
 53   return *this;
 54 }
 55
 56 // reset the printer
 57 PrinterProtocal &PrinterProtocal::reset() {
 58   data_.clear();
 59   return *this;
 60 }
 61
 62 // sets the printer online (true) or ofline (false)
 63 PrinterProtocal &PrinterProtocal::setStatus(bool state) {
 64   writeByte({27, 61, (uint8_t)state}).done();
 65   return *this;
 66 }
 67
 68 // set control parameters: heatingDots, heatingTime, heatingInterval
 69 PrinterProtocal &PrinterProtocal::setControlParameter(uint8_t heatingDots,
 70     uint8_t heatingTime, uint8_t heatingInterval) {
 71   writeByte({27, 55, heatingDots, heatingTime, heatingInterval}).done();
 72   return *this;
 73 }
 74
 75
 76 //width,height均表示倍数
 77 PrinterProtocal &PrinterProtocal::setFontSize(uint8_t size) {
 78   //低4位表示高度,高4位表示宽度
 79   uint8_t ret = (0x0f & (2 * size)) | (0xf0 & (16 * size));
 80   writeByte({29, 33, ret}).done();
 81   return *this;
 82 }
 83
 84 // set the used character set
 85 PrinterProtocal &PrinterProtocal::setCharacterSet(CharacterSet set) {
 86   writeByte({27, 82, (uint8_t)set}).done();
 87   return *this;
 88 }
 89
 90 // set the used code table
 91 PrinterProtocal &PrinterProtocal::setCodeTable(CodeTable table) {
 92   writeByte({27, 116, (uint8_t)table}).done();
 93   return *this;
 94 }
 95
 96 //打印并换行
 97 PrinterProtocal &PrinterProtocal::feed() {
 98   writeByte({10}).done();
 99   return *this;
100 }
101
102 //打印并换lines行
103 PrinterProtocal &PrinterProtocal::feed(uint8_t lines) {
104   writeByte({27, 74, lines}).done();
105   return *this;
106 }
107
108 //设置行间距
109 PrinterProtocal &PrinterProtocal::setLineSpacing(uint8_t spacing) {
110   writeByte({27, 51, spacing}).done();
111   return *this;
112 }
113
114 // set Align Mode: LEFT, MIDDLE, RIGHT
115 PrinterProtocal &PrinterProtocal::setAlign(AlignMode align) {
116   writeByte({27, 97, (uint8_t)align}).done();
117   return *this;
118 }
119
120 //设置左边空白间距
121 PrinterProtocal &PrinterProtocal::setLeftBlankCharNums(uint8_t space) {
122   if (space >= 47) {
123     space = 47;
124   }
125   writeByte({29, 76, space}).done();
126   return *this;
127 }
128
129
130
131 // set Bold Mode: on=true, off=false
132 PrinterProtocal &PrinterProtocal::setBold(bool state) {
133   writeByte({27, 69, (uint8_t)state}).done();
134   return *this;
135 }
136 //设定/解除反白打印模式
137 // set Reverse printing Mode
138 PrinterProtocal &PrinterProtocal::setReverse(bool state) {
139   writeByte({29, 66, (uint8_t)state}).done();
140   return *this;
141 }
142 //设置/解除颠倒打印模式
143 // set Up/Down Mode
144 PrinterProtocal &PrinterProtocal::setUpDown(bool state) {
145   writeByte({27, 123, (uint8_t)state}).done();
146   return *this;
147 }
148
149 //设置/取消汉字字符下划线模式
150 PrinterProtocal &PrinterProtocal::setUnderline(bool state) {
151   writeByte({28, 45, (uint8_t)state}).done();
152   return *this;
153 }
154
155 // enable / disable the key on the frontpanel
156 //激活/禁止面板按键
157 PrinterProtocal &PrinterProtocal::setKeyPanel(bool state) {
158   writeByte({27, 99, 53, (uint8_t)state}).done();
159   return *this;
160 }
161
162 PrinterProtocal &PrinterProtocal::setMarginBottom(uint8_t lines) {
163   writeByte({27, 74, lines}).done();
164   return *this;
165 }
166
167 std::vector<std::string> PrinterProtocal::getResult() {
168   return data_;
169 }

热敏打印机指令集中很多不一定用得到,而且感觉国内生产的这些打印机,对个别指令支持并不是特别好,要想做到完全兼容,还需要个性化的去适配。

 

时间: 2024-10-05 04:45:05

热敏打印机编程的相关文章

异常笔记--java编程思想

开一个新的系列,主要记一些琐碎的重要的知识点,把书读薄才是目的...特点: 代码少,概念多... 1. 基本概念 异常是在当前环境下无法获得必要的信息来解决这个问题,所以就需要从当前环境跳出,就是抛出异常.抛出异常后发生的几件事: 1.在堆上创建异常对象. 2.当前的执行路径中止                                          3. 当前环境抛出异常对象的引用.                                         4. 异常处理机制接

iOS开发——网络编程OC篇&amp;Socket编程

Socket编程 一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程师所研究的对象: 传输层.会话层.表示层和应用层则被称作主机层,是用户所面向和关心的内容. http协议   对应于应用层 tcp协议    对应于传输层 ip协议     对应于网络层 三者本质上没有可比性.  何况HTTP协议是基于TCP连接的. TCP/IP是传输层协议,主要

C#网络编程技术FastSocket实战项目演练

一.FastSocket课程介绍 .NET框架虽然微软提供了socket通信的类库,但是还有很多事情要自己处理,比如TCP协议需要处理分包.组包.粘包.维护连接列表等,UDP协议需要处理丢包.乱序,而且对于多连接并发,还要自己处理多线程等等.本期分享课程阿笨给大家带来的是来源于github开源Socket通信中间件:FastSocket,目的就是把大家从繁琐的网络编程技术中彻底地解放和释放出来. 阿笨只想安安静静的学习下网络编程技术Socket后,将学习的成果直接灵活的运用到自己的实际项目中去.

轻松学习C语言编程的秘诀:总结+灵感

目前在准备一套C语言的学习教程,所以我这里就以C语言编程的学习来讲.注意,讲的是"轻松学习",那种不注重方法,拼命玩命的方式也有其效果,但不是我提倡的.我讲究的是在方式方法对头.适合你.减轻你学习负担和心里压力的前提下,才适当的抓紧时间. 因此,探索一种很好的学习方法就是我所研究的主要内容. 众所周知,学习C语言并非易事,要学好它更是难上加难.这和你期末考试背会几个题目的答案考上满分没多大关系,也就是说你考试满分也说明不了你学好.学精通了C语言.那么怎么才算学精通C语言?闭着眼睛对自己

《Java编程思想》第十三章 字符串

<Java编程思想>读书笔记 1.String作为方法的参数时,会复制一份引用,而该引用所指的对象其实一直待在单一的物理位置,从未动过. 2.显式地创建StringBuilder允许预先为他指定大小.如果知道字符串多长,可以预先指定StringBuilder的大小避免多次重新分配的冲突. 1 /** 2 * @author zlz099: 3 * @version 创建时间:2017年9月1日 下午4:03:59 4 */ 5 public class UsingStringBuilder {

Linux Socket编程-(转自吴秦(Tyler))

"一切皆Socket!" 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. --有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket?那什么是socket?socket的类型有哪些?还有socket的基本函数,这些都是本文想介绍的.本文的主要内容如下: 1.网络中进程之间如何通信?

团队编程项目作业

团队名称: 简单 队长 学号:2015035107224 姓名:张志鹏 成员 学号:2015035107071 姓名:邱阳阳 学号:2015035107044 姓名:刘孝东 学号:2015035107007 姓名:孙弘原 学号:2015035107005 姓名:刘文帅 学号:2015035107009 姓名:杨琳 团队编程项目作业名称:爬取豆瓣电影TOP250 选择该团队编程项目原因:感觉项目有意思

团队项目编程作业

团队名称: 简单 队长 学号:2015035107224 姓名:张志鹏 成员 学号:2015035107071 姓名:邱阳阳 学号:2015035107044 姓名:刘孝东 学号:2015035107007 姓名:孙弘原 学号:2015035107005 姓名:刘文帅 学号:2015035107009 姓名:杨琳 团队编程项目作业名称:爬取豆瓣电影TOP250 选择该团队编程项目原因:我爱学习

python基础--接口与归一化设计、封装、异常、网络编程

1 接口与归一化设计 1.1 归一化概念: 归一化的好处: 1.归一化让使用者无需关心对象的类是什么,只需要知道这些对象都具备某些功能就可以了,这极大降低了使用者的使用难度. 2.归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合 继承的两种用途 一:继承基类的方法,并且做出自己改变或者扩展(代码重用):实践中,继承的这种用途意义并不很大,甚至常常是有害的.因为它使得子类与基类出现强耦合. 二:声明某个子类兼容于某基类,定义一个接口类(模仿java的Interface),接口类中