2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 使用TSC打印机打印条码 (1)

使用TSC打印机打印条码 (1)

时间:2021-01-11 23:53:35

相关推荐

使用TSC打印机打印条码 (1)

事件背景

最近客户有要求,要把WIFI排插的MAC地址打印成二维码。公司使用的是一台TSC的打印机。而WIFI设备的MAC地址会由它自己通过UDP广播出来。而且还要求要做一个界面。这就很头疼了。用C做好像很麻烦的样子,所以我决定使用我第二熟悉的Java来做,刚好IDEA也有做GUI的功能。这里做一下记录。

安装驱动和接口静态库

在网上寻找驱动,这个很简单,就不用说了吧,先让自己的电脑的打印机列表里出现这个打印机,而且可以打印测试页。去这里寻找DLL下载下来,这里我直接给个链接吧=====》Windows TSC DLL打开压缩包,会发现有两个文件夹,一个是X86,另一个是X64;将X86里的东西拷贝到C:\Windows\System32下,将X64里的东西拷贝到C:\Windows\SysWOW64下;安装JDK环境。

创建TSPL命令的类

的在读了TSPL指令集后,首创建我需要的类。

首先TSPL的用户指南在这里下载=====》这里

首先,我需要设定我的标签大小。

SIZE

这里我就不把内容贴上来了。

简单说说,最主要的就是标签的长宽,文档中是使用Label widthLabel length来表示的。那么就来吧。

package com.Aperture.TSPL;public class SIZE {private double mWidth, mHeight;public SIZE(double Width, double Height) {this.mWidth = Width;this.mHeight = Height;}}

还可以注意到一个事情,文档中出现了两种单位,一种是mm,另一种是inch,这里新建一个枚举类,想了半天也想不到什么好名字,就用TSCSystem吧:

package com.Aperture.TSPL;/*** The TSC unit:* <dl>* <dt>English:</dt>* <dd>inch</dd>* <dt>Metric:</dt>* <dd>mm</dd>* </dl>*/public enum TSCSystem {English, Metric}

我手里的标签长宽很奇怪,不是整数值,把游标卡尺的单位转换到Inch后发现居然是个整数,那我就用Inch来做默认单位吧:

package com.Aperture.TSPL;public class SIZE {private double mWidth, mHeight;private TSCSystem mTscSystem = TSCSystem.English;/*** @param WidthLabel width* @param Height Label length* @param tscSystem Length unit. See {@link TSCSystem}.*/public SIZE(double Width, double Height, TSCSystem tscSystem) {this.mWidth = Width;this.mHeight = Height;this.mTscSystem = tscSystem;}/*** This command defines the label width and length.** @param Width Label width (inch)* @param Height Label length (inch)*/public SIZE(double Width, double Height) {this.mWidth = Width;this.mHeight = Height;}}

需要将其转换为TSPL指令,所以再来一个方法:

/*** @return TSPL command.*/public String getCOMMAND() {switch (mTscSystem) {case English:return "SIZE " + String.valueOf(mWidth) + ',' + String.valueOf(mHeight);case Metric:return "SIZE " + String.valueOf(mWidth) + " mm" + ',' + String.valueOf(mHeight) + " mm";default:return null;}}

GAP

这个就是标签与标签之间的距离。

参照上一个很容易就能写出:

package com.Aperture.TSPL;public class GAP {private final double mGap;private final double mOffset;private TSCSystem mTscSystem = TSCSystem.English;/*** Defines the gap distance between two labels.** @param mGapLabel GAP* @param mOffset Gap offset* @param tscSystem Length unit. See {@link TSCSystem}.*/public GAP(double mGap, double mOffset, TSCSystem tscSystem) {this.mGap = mGap;this.mOffset = mOffset;this.mTscSystem = tscSystem;}/*** Defines the gap distance between two labels.** @param mGap Label GAP (inch)* @param mOffset Gap offset (inch)*/public GAP(double mGap, double mOffset) {this.mGap = mGap;this.mOffset = mOffset;}/*** Defines the gap distance between two labels.** @param mGap Label GAP (inch)*/public GAP(double mGap) {this.mGap = mGap;this.mOffset = 0;}/*** @return TSPL command.*/public String getCOMMAND() {switch (mTscSystem) {case English:return "SIZE " + String.valueOf(mGap) + ',' + String.valueOf(mOffset);case Metric:return "SIZE " + String.valueOf(mGap) + " mm" + ',' + String.valueOf(mOffset) + " mm";default:return null;}}}

TEXT

这是比较复杂的一个,因为可变参数很多。

package com.Aperture.TSPL;public class TEXT {//TEXT x,y, " font ",rotation,x-multiplication,y-multiplication,[alignment,] " content "private Integer mX;private Integer mY;private String mFont;private Integer mRotation;private Integer mXMultiplication, mYMultiplication;private Integer mAlignment = null;private String mContent;public TEXT(int x, int y, String font, int rotation, int x_multiplication, int y_multiplication, String content) {mX = x;mY = y;mFont = font;this.mRotation = rotation;this.mXMultiplication = x_multiplication;this.mYMultiplication = y_multiplication;this.mContent = content;}public TEXT(int x, int y, String font, int rotation, int x_multiplication, int y_multiplication, int alignment, String content) {mX = x;mY = y;mFont = font;this.mRotation = rotation;this.mXMultiplication = x_multiplication;this.mYMultiplication = y_multiplication;this.mAlignment = alignment;this.mContent = content;}public String getCOMMAND() {if (mAlignment == null) {return "TEXT " +mX +mY +" \"" + mFont + "\"" +mRotation +mXMultiplication +mYMultiplication +"\"" + mContent + "\"";}return "TEXT " +mX + ',' +mY + ',' +" \"" + mFont + "\"" + ',' +mRotation + ',' +mXMultiplication + ',' +mYMultiplication + ',' +mAlignment + ',' +"\"" + mContent + "\"";}}

QRCODE

这个居然比TEXT简单。

package com.Aperture.TSPL;public class QRCODE {private double mX;private double mY;private char mEccLevel;private double mCellWidth;private char mMode;private int mRotation;private String mModule;private String mMask;private String mData;public QRCODE(double x, double mY, char eccLevel, double cellWidth, char mode, int rotation, String module, String mask, String Data) {this.mX = x;this.mY = mY;this.mEccLevel = eccLevel;this.mCellWidth = cellWidth;this.mMode = mode;this.mRotation = rotation;this.mModule = module;this.mMask = mask;this.mData = Data;}public String getCOMMAND() {return "QRCODE " + mX + "," + mY + "," + mEccLevel + "," + mCellWidth + "," + mMode + "," + mRotation + "," + mModule + "," + mMask + ",\"" + mData + '\"';}}

其他

剩下的东西都放在这里吧,GUI没什么好讲的。

客户还有提到需要一个SN码,SN码要和MAC对应,完了还要做在报表里。通过不断的+1即可解决这个问题。读取UDP广播的话,这种东西最好不要做在主线程中,以免卡住界面。本来想用Thread的,但是这个线程一直读取UDP的时候会让我的CPU风扇狂转不止。所以我查到了定时任务TimerTask

class UdpReceive extends TimerTask {@Overridepublic void run() {DatagramSocket socket;try {socket = new DatagramSocket(8080);} catch (SocketException e) {stateTextArea1.append("\tUdpReceive: 8080 已被占用!" + '\n');stateTextArea1.append(e.getMessage() + '\n');return;}DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);try {socket.receive(packet);} catch (IOException e) {stateTextArea1.append(e.getMessage() + '\n');return;}byte[] packetData = packet.getData();String data = new String(packetData, 0, packet.getLength()).replaceAll("\r\n", "");stateTextArea1.append("\tUdpReceive: 获得数据: " + '\"' + data + '\"' + '\n');macTextField.setText(data.split(",")[2]);socket.close();if (MAC_Records.contains(data)) {snTextField.setText(SN_Records.get(MAC_Records.indexOf(data)));stateTextArea1.append("\tUdpReceive: " + data + "已存在于记录中;SN :" +SN_Records.get(MAC_Records.indexOf(data)) + '\n');} else {snTextField.setText("000" + todayRecordName + String.valueOf(100000 + Number).substring(1));Number++;MAC_Records.add(data);SN_Records.add(snTextField.getText());if (SaveNewData()) {stateTextArea1.append("\tUdpReceive: 保存记录成功." + '\n');}//PrintLabel("000" + todayRecordName + String.valueOf(100000 + MAC_Records.size())// .substring(1), data);PrintLabel(SN_Records.get(MAC_Records.indexOf(data)), data);mTable.updateUI();}}}

通过调用

new Timer().schedule(new UdpReceive(), delay, period);

来启用这个定时线程。

避免UDP广播多次调用打印,所以,我使用暴力一点的方法,直接把所有的MAC全部存起来,每一个新的MAC都做一个判断,只有接收到的MAC是新的设备的时候才调用打印机。打印部分的的流程如下:

private void PrintLabel(String snData, String macData) {stateTextArea1.append("\t\tPrintLabel: 打印 QRCODE " + macData + '\n');TscLibDll.INSTANCE.openport("TSC TTP-342M Pro");TscLibDll.INSTANCE.clearbuffer();TscLibDll.INSTANCE.setup("83.4", "29", "2", "8","0", "2.54", "0");TscLibDll.INSTANCE.sendcommand(new DIRECTION(1).getCOMMAND());TscLibDll.INSTANCE.sendcommand(new SHIFT(10, -20).getCOMMAND());TscLibDll.INSTANCE.sendcommand(new QRCODE(690, 40, 'L', 10, 'A',0, "M2", "S7", macData).getCOMMAND());TscLibDll.INSTANCE.sendcommand(new BARCODE(70, 135, "128", 50, 0,0, 3, 7, 0, snData).getCOMMAND());TscLibDll.INSTANCE.sendcommand(new TEXT(90, 185, "3", 0, 1,1, 0, "SN: " + snData).getCOMMAND());TscLibDll.INSTANCE.printlabel("1", "1");TscLibDll.INSTANCE.closeport();}

总结起来就是

TscLibDll.INSTANCE.openport();// 打开端口TscLibDll.INSTANCE.setup(); // 设置条码大小TscLibDll.INSTANCE.sendcommand(); // 发送TSPL指令TscLibDll.INSTANCE.printlabel(); // 打印TscLibDll.INSTANCE.closeport();// 关闭端口

而每打印的时候发去的指令它都会存下来,所以要打印新的东西就要清除缓存,再加上

TscLibDll.INSTANCE.clearbuffer(); // 清除缓存

就完美了。

两个项目的所有代码我都放在Github上====》Godenfreemans的GitHub

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