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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yt454287063/article/details/80139058

事件背景

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


安装驱动和接口静态库

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


猜你喜欢

转载自blog.csdn.net/yt454287063/article/details/80139058