iOS套接字連接小票打印機

KriThomason 7年前發布 | 16K 次閱讀 Socket iOS開發 移動開發

最近在開發iOS連接打印機打印小票的功能,找了很多資料,本身相關資料就少,而且還全都是c#,java的.項目是用swift寫的(OC思路差不多),現整理如下.

準備工作:Xcode7.1,swift2.0,佳博GP80106 wifi打印機(根據打印機的不同,有些指令可能會有差異,但基本相同,用的都是ESC/POS指令)

前提:在同一個局域網下,設置好打印機,設置好host,port

一. Socket連接打印機

使用CocoaAsyncSocket,wifi連接打印機.具體連接方法不是本文主要內容,可參考CocoaAsyncSocket的使用

https://github.com/robbiehanson/CocoaAsyncSocket

這個是OC庫,所以要將AsyncSocket.h 包含到橋接文件中PrijectName-Bridging-Header.h

//ViewController.swift
import AsyncSocke
var asyncSocket:AsyncSocket?
//...
//假設已經連接成功

二. 編寫之前,先來看看socket是如何發送指令的:

asyncSocket.writeData(data: NSData!, withTimeout: NSTimeInterval, tag: Int)

它是將所有指令數據寫入到一個數據對象中,再發送到連接的設備(打印機),那么首先創建一個NSData對象,來儲存指令

let sendData = NSMutableData(capacity: 0)!
asyncSocket.writeData(sendData, withTimeout: -1, tag: 0)

最后將指令發送,因此在這里,關鍵就是構建sendData對象

先來創建一個通用方法,將每一條指令都寫入sendData中(如果現在不知道怎么回事,看下去就明白了)

func addBytesCommand(command:UnsafePointer, length:Int){
      self.sendData.appendBytes(command, length: length)
}

三. 舉幾個例子,來演示一下如何發送指令

根據編程手冊,"橫向和縱向移動單位"在很多設置間距的地方有使用到,那么先來解決這條指令.

1. GS P x y設置橫向和縱向移動單位

[格式]

ASCII碼 GS P x y
十六進制碼 1D 50 x y
十進制碼 29 80 x y

[范圍] 0≤x≤255 0≤y≤255

[描述] ?分別將橫向移動單位近似設置成25.4/ x mm(1/ x英寸)縱向移動單位設置成25.4/ y mm(1/ y英寸)。

  • 當x和y為0時,x和y被設置成默認值,默認值x=200,y=200。

先來解釋一下,GS, P就是ASCII碼,下面對應的是十六進制和十進制,這里使用十六進制

func printDotDistance(x:UInt8, y:UInt8){
       var char:[UInt8] = [0x1D,0x50]
       char.append(x)
       char.append(y)
      //步驟2中創建的通用數據寫入方法
       addBytesCommand(char, length: char.count)
}

直接使用指令中參數有時會讓你不知所云,當我們將這個接口提供給別人用的時候,他們或許并不知道x,y是什么意思.所以很有必要將參數設置成大家都明白的意思(之后也會看到其他方法),改動如下

/**
設置橫向和縱向移動單位
- parameter horizontal: 橫向移動單位
- parameter vertical:  縱向移動單位
*/

func printDotDistance(w w:Float, h:Float){
       var char = [0x1D,0x50]
       char.append(Int(25.4/w))
       char.append(Int(25.4/h))
       addBytesCommand(char, length: char.count)
}

w,h是我希望設置的左右或上下移動的單位距離,單位mm.根據0≤x≤255,0≤y≤255和"移動單位近似設置成25.4/ x mm" 的規定,上述方法中w,h也是有范圍的,不要越界了,不然指令無效,會變成默認設置

下面再來看一條

2.GS L nL nH 設置左邊距

[格式]

ASCII碼 GS L nL nH
十六進制碼 1D 4C nL nH
十進制碼 29 76 nL nH

[范圍] 0≤nL≤255,0≤nH≤255

[描述] ?用nL和nH設置左邊距;

?左邊距設置為[( nL + nH × 256)×橫向移動單位]]英寸。

[默認值] nL = 0, nH = 0

這里用到了剛才設置的"橫向移動單位",我先調用以下方法,就將橫向縱向移動單位設置成了0.1mm

printDotDistance(w: 0.1, h: 0.1)

和指令一一樣,如果直接將nL,nH設置成參數,使用者不易讀,因此參數需要轉換下.很容易發現,nL就是模(余數),nH就是商

/**
設置左邊距
- parameter margin: 做邊距,單位mm
*/
func printLeftMargin(margin:CGFloat){
       var char:[UInt8] = [0x1D,0x4C]
       char.append(UInt8(margin%256))
       char.append(UInt8(margin/256))
       addBytesCommand(char, length: char.count)
}

3.文字打印

/**

添加文字

- parameter text: 字符串

*/

func printAddText(text:String){

//文字編碼轉為GB_18030_2000

let gbkeEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(CFStringEncodings.GB_18030_2000.rawValue))
let data = text.dataUsingEncoding(gbkeEncoding)!
let size = data.length
let textData = malloc(size)
data.getBytes(textData, length:size)
addBytesCommand(textData, length: size)
free(textData)
}

4.打印圖片

我用了其中轉圖片的方法,使用OC寫的,因為項目急,直接用了.等有時間,轉成swift,再帖上來.

選擇位圖模式:ESC * m nL nH d1... dk

ASCII碼 ESC * m nL nH d1...dk
十六進制碼 1B 2A m nL nH d1...dk
十進制碼 27 42 m nL nH d1...dk

[范圍] m = 0, 1, 32, 33,0≤nL≤255,0≤nH≤3,0≤d≤255

/**
選擇位圖模式
- parameter bitmap:    位圖
*/

func printBitmapModel(bitmap:UIImage){
let data = IGThermalSupport.imageToThermalData(bitmap)//ThermalPrinterKit這個庫中的方法
let size = data.length
let picData = malloc(size)
data.getBytes(picData, length:size)
addBytesCommand(picData, length: size)
free(picData)
}

打印二維碼,可以先生成二維碼圖片,再使用上面的方法寫入數據.

5.打印小票

最后別忘了使用

asyncSocket.writeData(sendData, withTimeout: -1, tag: 0)

將數據發送給打印機

四.注意點

  1. 為了方便使用,可以將socket連接、打印機管理方法分別封裝,再封裝一個小票管理類直接使用.
  2. ESC/POS指令中所有參數都是UInt8類型的,有時候可能是參數類型錯誤,將類型強轉為UInt8(para)試試,可能就成功了
  3. 第一次開發打印機,如果有錯誤,歡迎指正交流.

 

 

來自:http://www.jianshu.com/p/52bdd2e41b11

 

 本文由用戶 KriThomason 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!