熱敏印表機實現列印小票
阿新 • • 發佈:2019-02-12
最近公司需要用熱敏印表機POS88V實現列印小票。本文采用Kotlin 語言來實現
首先看看SP-POS88Ⅴ系列開發手冊.pdf。你會發現這文件只有一堆的指令說明,而且是無序的。按道理應該先初始化裝置,所以找到初始化印表機地方
ESC @
[名稱] 初始化印表機
[格式] ASCII ESC @
Hex 1B 40
Decimal 27 64
[描述] 清除列印緩衝區資料,列印模式被設為上電時的預設值模式。
[註釋] · DIP開關的設定不進行再次檢測。
· 接收緩衝區內容保留。
· 巨集定義保留。
· flash點陣圖資料不擦除。
· flash使用者資料不擦除。
· 維護計數器值不擦除。
· 由GS ( E 指定的設定值不擦除。
它支援3指令格式,分別是ASCII ,Hex ,Decimal 。 我喜歡用hex ,所以建個HexCommands 類維護各種指令
/**
* 採用16進制定義指令
*/
enum class HexCommands(vararg parameters: Int) {
/**
* 初始化印表機
*/
INIT_PRINTER(0x1B, 0x40),
/**
* 選擇標準模式
*/
STANDARD_MODE(0x1B, 0x53),
/**
* 進紙並且半切紙
*/
FEED_AND_CUT(0x1D , 0x56, 65),
/**
* 設定絕對列印位置
*/
PRINT_ABSOLUTE_LOCATION(0x1B, 0x24),
/**
* 選擇/取消加粗模式
*/
TEXT_BOLD(0x1B, 0x45),
/**
* 選擇字元對齊模式
*/
TEXT_ALIGNMENT(0x1B, 0x61);
val hexValues = parameters
}
建立連線
如何建立連線呢?我這裡採用網路方式,用socket 很方便實現
class PosPrinter {
var encoding: String = "GBK"
private lateinit var client: Socket
private lateinit var writer: PrintWriter
@Throws(IOException::class, UnsupportedEncodingException::class)
fun connect(ip: String, port: Int = 9100, timeout: Long = 1, timeUnit: TimeUnit = TimeUnit.SECONDS) {
client = Socket()
client.connect(InetSocketAddress(ip, port), TimeUnit.MILLISECONDS.convert(timeout, timeUnit).toInt())
writer = PrintWriter(BufferedWriter(OutputStreamWriter(client.getOutputStream(), encoding)))
}
@Throws(IOException::class)
fun disconnect() {
writer.close()
client.close()
}
private fun write(hexCommands: HexCommands, vararg moreHexValues: Int) {
hexCommands.hexValues.forEach {
writer.write(it)
}
moreHexValues.forEach {
writer.write(it)
}
writer.flush()
}
fun initPosPrinter(): PosPrinter {
write(HexCommands.INIT_PRINTER)
return this
}
fun selectStandardMode(): PosPrinter {
write(HexCommands.STANDARD_MODE)
return this
}
fun printText(text: String): PosPrinter {
writer.write(text)
writer.flush()
return this
}
fun printLine(line: Int = 1): PosPrinter {
for (i in 0 until line) {
writer.write("\n")
writer.flush()
}
return this
}
fun printTextLine(text: String, line: Int = 1): PosPrinter {
printLine(line)
printText(text)
return this
}
fun innerPrint(function: PosPrinter.() -> PosPrinter): PosPrinter {
function(this)
return this
}
/**
* 列印空白(size個漢字的位置)
*/
fun printWordSpace(size: Int): PosPrinter {
for (i in 0 until size) {
writer.write(" ")
}
writer.flush()
return this
}
/**
* 選擇字元對齊模式
*/
fun setTextBold(isBold: Boolean = false): PosPrinter {
write(HexCommands.TEXT_BOLD, if (isBold) 1 else 0)
return this
}
/**
* 選擇字元對齊模式
*/
fun setTextAlignment(@TextAlignment textAlignment: Long): PosPrinter {
write(HexCommands.TEXT_ALIGNMENT, textAlignment.toInt())
return this
}
/**
* 設定絕對列印位置
*/
fun setTextAbsoluteLocation(@IntRange(from = 0, to = 255) offsetX: Int,
@IntRange(from = 0, to = 255) offsetY: Int = 1): PosPrinter {
write(HexCommands.PRINT_ABSOLUTE_LOCATION, offsetX, offsetY)
return this
}
fun feedAndCut(length: Int = 100): PosPrinter {
write(HexCommands.FEED_AND_CUT, length)
return this
}
companion object {
/**
* Align to the start of the paragraph, e.g. ALIGN_LEFT.
*
* Use with [.setTextAlignment]
*/
const val TEXT_ALIGNMENT_TEXT_START = 0L
/**
* Center the paragraph, e.g. ALIGN_CENTER.
*
* Use with [.setTextAlignment]
*/
const val TEXT_ALIGNMENT_CENTER = 1L
/**
* Align to the end of the paragraph, e.g. ALIGN_RIGHT.
*
* Use with [.setTextAlignment]
*/
const val TEXT_ALIGNMENT_TEXT_END = 2L
@IntDef(TEXT_ALIGNMENT_TEXT_START, TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_TEXT_END)
@Retention(AnnotationRetention.SOURCE)
annotation class TextAlignment
}
}
安卓裝置上列印小票
//訂單菜品集合
private var goodsBean: MutableList<GoodsBean>? = null
private var posPrinter: PosPrinter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
doAsync {
//初始化訂單資料
initData()
posPrinter = PosPrinter()
posPrinter!!.connect("192.168.2.150")
posPrinter!!.initPosPrinter()
.selectStandardMode()
.setTextBold(true)
.setTextAlignment(PosPrinter.TEXT_ALIGNMENT_CENTER)
.printText("*** 天龍店鋪 ***")
.printLine()
.setTextBold(false)
.setTextAlignment(PosPrinter.TEXT_ALIGNMENT_TEXT_START)
.printTextLine("訂單編號:1005199")
.printTextLine("交易機臺:test")
.printTextLine("交易時間:2016/2/19 12:34:53")
.printTextLine("支付方式:微信支付")
.printLine(2)
.printText("商品")
.setTextAbsoluteLocation(20)
.printText("單價")
.printWordSpace(3)
.printText("數量")
.printWordSpace(3)
.printText("小計")
.printTextLine("----------------------------------------------")
.innerPrint({
for (foods in goodsBean!!) {
printTextLine(foods.name)
setTextAbsoluteLocation(20)
printText(foods.price)
printWordSpace(3)
printText(foods.number)
printWordSpace(3)
printText(foods.sum)
}
this
})
.printTextLine("----------------------------------------------")
.printLine()
.printText("總計(人民幣):")
.printText("80.00")
.printLine()
.feedAndCut(50)
}
}
private fun initData() {
goodsBean = ArrayList()
(0..1).map { GoodsBean("測試商品" + it, "10.00", "2", "20.00") }
.forEach { goodsBean!!.add(it) }
}
data class GoodsBean(val name: String, val price: String, val number: String, val sum: String)