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

您所在的位置:网站首页 的中国结 使用TSC打印机打印条码 (1)

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

2024-06-04 08:20| 来源: 网络整理| 查看: 265

事件背景

最近客户有要求,要把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 width和Label 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: * * English: * inch * Metric: * mm * */ public enum TSCSystem { English, Metric }

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

package com.Aperture.TSPL; public class SIZE { private double mWidth, mHeight; private TSCSystem mTscSystem = TSCSystem.English; /** * @param Width Label 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 mGap Label 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 { @Override public 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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3