斑马打印中文和特殊符号
国内的斑马打印机一般自带了宋体,打印中文是没有问题,但是发现不能打印类似这样的C₁₂H₁₆Cl₂N₂
化学式下标。
还有看惯了手机和电脑上的黑体,宋体有点不习惯,本文也教你如何上传思源黑体(英语:Source Han Sans,Google公司则称Noto Sans CJK)是Adobe与Google所合作开发的开源字体家族,属于无衬线黑体。
查字体里的字符
在将字体下载到打印机之前,可以通过Windows的“字符映射表”工具,选中对应的字体,输入字符的Unicode编码
比如下标1₁
的Unicode码是U+2081
,如上图所示,该字体中没有对应的字符编码,离它最近的是U+20A9
。
再看另一个有该字符的字体
打印机安卓系统集成
打印机可以采用USB,蓝牙,网络连接到安卓系统。从官网下载打印机的安卓开发SDK,下面共享一段打印机发现的代码:
package com.zhaoxinsoft.lab.doamin.setting
import android.content.Context
import com.zebra.sdk.btleComm.BluetoothLeDiscoverer
import com.zebra.sdk.printer.discovery.BluetoothDiscoverer
import com.zebra.sdk.printer.discovery.DiscoveredPrinter
import com.zebra.sdk.printer.discovery.DiscoveryHandler
import com.zebra.sdk.printer.discovery.NetworkDiscoverer
import com.zebra.sdk.printer.discovery.UsbDiscoverer
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
class ZebraPrinterDiscover(private val context: Context) {
enum class PrinterType {
USB, BLUETOOTH, NETWORK, BLUETOOTH_LE
}
/**
* 按指定类型查找打印机,此函数应当在Dispatchers.IO中调用
* @param type 打印机类型
*/
suspend fun discover(type: PrinterType): Result<List<DiscoveredPrinter>> =
suspendCancellableCoroutine { continuation ->
val printers = mutableListOf<DiscoveredPrinter>()
val handler = object : DiscoveryHandler {
override fun foundPrinter(printer: DiscoveredPrinter) {
printers.add(printer)
}
override fun discoveryFinished() {
if (continuation.isCancelled) return
continuation.resume(Result.success(printers))
}
override fun discoveryError(message: String) {
if (continuation.isCancelled) return
continuation.resume(Result.failure(Exception(message)))
}
}
when (type) {
PrinterType.USB -> UsbDiscoverer.findPrinters(context, handler)
PrinterType.BLUETOOTH -> BluetoothDiscoverer.findPrinters(context, handler)
PrinterType.NETWORK -> NetworkDiscoverer.findPrinters(handler)
else -> BluetoothLeDiscoverer.findPrinters(context, handler)
}
continuation.invokeOnCancellation {
continuation.resume(Result.failure(Exception("Cancelled")))
}
}
}
字体下载
字体准备
斑马打印机支持TTF字体,但是网上下载的很多TTF字体都是可变TTF(一个文件包含多种粗细的),例如这里下载的这个简体版的NotoSansSC[wght].ttf
安装fonttools
工具可以提取其中一种需要的粗细
pip install fonttools
输入以下命令导出变体表
ttx -t fvar "NotoSansSC[wght].ttf"
得到NotoSansSC[wght].ttx
文件,是一个XML文件,里面指明了字体文件里包含哪些粗细,数字越大越粗。这里我们选择400
fonttools varLib.instancer "NotoSansSC[wght].ttf" wght=400 -o "NOTOSC_400.ttf"
提取到可变字体的一种,这个文件就可以用来传给打印机了。
下载字体
这里所说的下载和斑马文档里面的关于字体Download其实说把字体下载到打印机里面去的意思。其实说上传可能好理解一些。
使用指令下载字体文件,这里以kotlin举例
// 上传 NOTOSC_400.ttf
val file = Helper.getFileFromAssets(context, "zebra/NOTOSC_400.ttf")
val zpl = "~DYE:NTSANSSC.TTF,B,T,10238812,,"
// 注意:字体文件名最好不要超过8个字,否则会出奇怪问题,后面数字是文件大小,再有两个逗号不能省
conn.sendAndWaitForResponse(
zpl.toByteArray(), 0, 0, null
)
_printer?.sendFileContents(file.absolutePath) { writen, total ->
Log.d(TAG, "NTSANSSC.TTF Uploading $writen/$total")
}
其实用Windows的打印机属性窗口也可以,先用“发送命令”,注意那串数字是字体文件的大小
再用“发送文件”,把选择文件传上去就行。
ZPL打印标签
话不多说了,直接看例子,下面是安卓开发里面kotlin的例子
val zpl = """
^XA
^MMT
^PW839
^LL655
^LS0
^CWR,E:NTSANSSC.TTF
^CWL,E:NTSANS_L.TTF
^SEE:GB18030.DAT^CI26
^FT1,100^ARN,73,74^FB838,1,0,C^^FD乙二胺盐^FS
^FPH,6^FT0,200^ALN,66,65^FB839,1,35,C^^FDC₁₂H₁₆Cl₂N₂^FS
^BY6,3,257^FT84,525^BCN,,N,N,,A
^FD40050010000003^FS
^FT0,620^ALN,56,56^FB838,1,30,C^FD40050010000003^FS
^PQ1,,,Y
^XZ
"""
_printer?.connection?.write(zpl.toByteArray(Charset.forName("GB18030")))
注意ZPL里面需要用^SEE:GB18030.DAT^CI26
加载编码文件,然后指令发出的时候也要用GB18030
进行编码。
下面是python的例子
# -*- coding: utf-8 -*-
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.1.29', 9100))
zpl = '''
^XA
^MMT
^PW839
^LL655
^LS0
^CWR,E:NTSANSSC.TTF
^CWL,E:NTSANS_L.TTF
^SEE:GB18030.DAT^CI26
^FT1,100^ARN,73,74^FB838,1,0,C^FD乙二胺盐^FS
^FPH,6^FT0,200^ALN,66,65^FB839,1,35,C^FDC₁₂H₁₆Cl₂^FS
^BY6,3,257^FT84,525^BCN,,N,N,,A
^FD40050010000003^FS
^FT0,620^ALN,56,56^FB838,1,30,C^FD40050010000003^FS
^PQ1,,,Y
^XZ
'''
s.send(zpl.encode(encoding='gb18030'))
s.close()
最后附上打印效果
常用ZPL指令备忘录
^XA^HWE:*.TTF^XZ
输出TTF字体文件列表,结果不打印在纸上^XA^IDE:MIC000.TTF^XZ
删除指定文件~JR
开机重置用于重置打印机的所有内部软件,执行开机自检 (POST),清除缓存和 DRAM,并重置通信参数和默认值。发出 ~JR 命令所实现的功能与手动开机重置实现 的功能相同。(遇到指令总也不听使唤的时候有奇效)