uniapp實現(xiàn)藍牙小票打印功能深度解析
一、項目背景及需求
近期開發(fā)的項目中新增了藍牙小票打印功能。由于之前對藍牙打印機了解不多,開發(fā)過程中遇到了一些挑戰(zhàn)。為了解決這個問題,我們決定封裝藍牙連接和打印模塊為通用組件,并編寫了一個打印實例。以下是項目需要實現(xiàn)的具體需求:

打印公司logo(本地圖片)
打印指定格式與排版的文本數(shù)據(jù)(包括直線、中英文)
打印簽名的圖片數(shù)據(jù)(通過接口傳回的網(wǎng)絡(luò)圖片地址)
二、藍牙連接與打印流程概述
為了實現(xiàn)上述功能,首先需要確保藍牙設(shè)備的連接。開發(fā)前,我們了解了低功耗藍牙連接的操作流程。在組件中,我們按照API指引,實現(xiàn)了從連接到打印的整個過程。父組件只需在`onPrint`方法中拼接指令,通過`bufferData`屬性將指令數(shù)據(jù)傳入組件內(nèi)部即可進行打印操作。提供了`onPrintSuccess`和`onPrintFail`兩個回調(diào),分別用于處理打印成功與失敗的情況。

三、組件內(nèi)部實現(xiàn)詳解
1. 打印按鈕觸發(fā)操作
點擊打印按鈕后,首先會打開藍牙適配器(`openBluetoothAdapter`),并獲取已連接的設(shè)備。如果沒有已連接的設(shè)備,則會彈出設(shè)備搜索框進行搜索。若設(shè)備已連接,則直接執(zhí)行打印方法。
2. 設(shè)備搜索與篩選
使用`isShowSearch`控制搜索設(shè)備彈框的顯示與隱藏。點擊開始搜索后,通過`onfindBlueDevices`監(jiān)聽新搜索到的設(shè)備。為了節(jié)省系統(tǒng)資源,在連接上設(shè)備或頁面銷毀時,會關(guān)閉搜索功能。由于添加了設(shè)備篩選條件(如rssi、設(shè)備名、設(shè)備ID等),因此需要對搜索到的設(shè)備進行篩選。

3. 設(shè)備連接
從設(shè)備列表中選擇要連接的設(shè)備,獲取其`deviceId`等信息。通過`createBLEConnection`創(chuàng)建藍牙連接。連接過程中,可以使用`onBLEConnectionStateChange`監(jiān)聽連接狀態(tài)的變化。連接成功后,關(guān)閉設(shè)備搜索功能。
四、組件中的關(guān)鍵模塊解析
blesdk:這是一個為了方便使用而創(chuàng)建的模塊,將uniapp藍牙相關(guān)的API統(tǒng)一放置在一個文件中,并將方法轉(zhuǎn)為異步。其中還包括添加CPCL指令的字符拼接方法。
gbk模塊:用于將數(shù)據(jù)轉(zhuǎn)碼為打印機能夠接受的格式。

五、總結(jié)與展望
通過本次開發(fā),我們成功實現(xiàn)了App端連接藍牙打印機并打印指定內(nèi)容的功能。從藍牙連接到打印指令的發(fā)送,每一步都經(jīng)過了嚴格的測試與優(yōu)化。未來,我們還將繼續(xù)優(yōu)化打印效果與效率,為用戶提供更好的體驗。我們也會關(guān)注藍牙技術(shù)的最新發(fā)展,以便將最新的技術(shù)應(yīng)用到項目中,提升產(chǎn)品的競爭力。藍牙設(shè)備連接與打印操作指南
一、連接設(shè)備并獲取服務(wù)
連接藍牙設(shè)備后,需要通過deviceId獲取設(shè)備服務(wù)。這個過程需要調(diào)用getBLEDeviceServices方法,但需要注意,獲取時應(yīng)當給這個方法設(shè)置一個延時,以防止獲取到的serviceId為空。
二、獲取設(shè)備服務(wù)并返回serviceId數(shù)組

成功獲取設(shè)備服務(wù)后,會返回一個servicesId數(shù)組。接著,我們需要使用deviceId和serviceId來進一步獲取特征值,調(diào)用getDeviceCharacteristics方法。
三、暫存特征值
獲取到特征值后,需要找一個變量將其暫存。因為后續(xù)向打印機發(fā)送數(shù)據(jù)時,特征值將會被用到。也應(yīng)關(guān)閉搜索彈框,以便進行下一步操作。
四、數(shù)據(jù)拼接與發(fā)送
在成功連接設(shè)備后,點擊打印按鈕,便可以開始拼接打印數(shù)據(jù)。如果檢測到已連接設(shè)備,就開始拼接數(shù)據(jù)并準備打印。這個任務(wù)交由父頁面的onPrint方法處理。拼接完成后,通過bufferData傳入。當bufferData數(shù)據(jù)更新后,將數(shù)據(jù)發(fā)送給設(shè)備。所需的參數(shù)包括opt中的參數(shù)、deviceId、serviceId、characteristicId以及需要寫入的數(shù)據(jù)。這些數(shù)據(jù)需轉(zhuǎn)成GBK格式。還有一個重要的回調(diào)是lasterSuccess,它會在數(shù)據(jù)全部發(fā)送成功后被觸發(fā)。由于安卓和iOS的分包發(fā)送長度不同,因此需要添加一個判斷。sendDataToDevice方法中封裝了分包發(fā)送的邏輯。

五、指令拼接方法與實際使用
在父頁面的onPrint方法中,我們會拼接bufferData數(shù)據(jù)。關(guān)于CPCL指令的拼接方法,被放在了@/components/kk-printer/utils/bluetoolth.js文件中。這只是組件示例展示的一部分常用指令拼接方法。要了解具體的指令封裝方法,可以查看項目中的@/components/kk-printer/utils/bluetoolth.js文件。
六、項目實際應(yīng)用
在實際項目中,首先需要在頁面引入并使用components文件夾中的kk-printer組件。在使用這個組件時,根據(jù)打印的需求,將不同的數(shù)據(jù)通過相應(yīng)的方法進行拼接。
使用addCPCLImageCmd時調(diào)整灰度值threshold的注意事項

在使用addCPCLImageCmd方法時,灰度值threshold的調(diào)整是關(guān)鍵。過高的灰度值會導(dǎo)致低于該值的圖像像素點被篩除,顯示為0,可能影響打印效果。正確設(shè)置灰度值閾限至關(guān)重要。
打印功能中的基礎(chǔ)操作
項目中包含了一些基礎(chǔ)的打印操作,如addBaseInfo用于打印基本信息,addTicketsInfo用于打印提單信息。這些功能主要涉及文本打印和排版,技術(shù)實現(xiàn)上并無難點。
數(shù)據(jù)(bufferData)拼接的要點解析
在向藍牙打印機發(fā)送數(shù)據(jù)打印時,需特別注意以下幾點:

1. 所有發(fā)送內(nèi)容應(yīng)轉(zhuǎn)換為二進制數(shù)據(jù)。由于藍牙打印的文本編碼采用GBK,因此中文內(nèi)容需先轉(zhuǎn)為GBK編碼,再轉(zhuǎn)為二進制數(shù)據(jù)發(fā)送。包括打印機指令也需以二進制形式發(fā)送。
2. 藍牙打印機對一次接收的二進制數(shù)據(jù)量有限制,建議每次發(fā)送20個字節(jié),采用遞歸分包發(fā)送以提高穩(wěn)定性。
3. 打印內(nèi)容發(fā)送完畢后,需發(fā)送打印指令以啟動打印任務(wù)。部分指令無需額外發(fā)送。
4. 在分包發(fā)送過程中,由于設(shè)備連接不穩(wěn)定,可能出現(xiàn)錯誤代碼10007或找不到特征值的情況。應(yīng)在失敗回調(diào)中記錄斷點,繼續(xù)發(fā)送后續(xù)數(shù)據(jù)包。
uni-app連接便攜式藍牙打印機:以芝柯HDT334為例

在uni-app中連接芝柯HDT334藍牙打印機時,主要采用CPCL打印模式。涉及的主要技術(shù)包括藍牙連接和CPCL指令集的使用,特別是定位畫線功能。
當打印的文字超出最大寬度時,需要動態(tài)換行。解決方法是在dom中創(chuàng)建一個隱藏的div,將文字放入其中,比較div的寬度與打印區(qū)域的最大寬度。若超出最大寬度,則需在固定位置截取文字,分兩行放置,并相應(yīng)調(diào)整文字下方的內(nèi)容位置。
uni-app藍牙連接與打印功能實現(xiàn)
在項目需求中實現(xiàn)了低耗藍牙打印功能。下面是實現(xiàn)該功能的主要步驟和所需的api。需要注意的是,對于不支持藍牙版本4.0以下的設(shè)備,需要尋找其他解決方案,因為低版本可能會出現(xiàn)一些不可預(yù)料的問題。在實現(xiàn)過程中,確實需要細心處理各種情況,確保打印任務(wù)的順利進行。

一、初始化藍牙模塊:uni.openBluetoothAdapter
在啟動藍牙功能之初,首先需要通過`uni.openBluetoothAdapter`來初始化藍牙模塊。這一步是后續(xù)所有操作的基礎(chǔ),只有完成了初始化,我們才能繼續(xù)執(zhí)行后續(xù)的搜索設(shè)備、連接等操作。
二、監(jiān)聽新設(shè)備:uni.onBluetoothDeviceFound
當周圍的藍牙設(shè)備被搜索到時,我們需要一個機制來監(jiān)聽這些新發(fā)現(xiàn)。通過`uni.onBluetoothDeviceFound`,我們可以實時獲取到尋找到新設(shè)備的通知,這樣我們就能及時對設(shè)備進行響應(yīng)和處理。
三、獲取藍牙適配器狀態(tài):uni.getBluetoothAdapterState

了解本機藍牙適配器的狀態(tài)是確保藍牙連接穩(wěn)定的關(guān)鍵。使用`uni.getBluetoothAdapterState`可以獲取到適配器的實時狀態(tài),從而確保藍牙設(shè)備是在可用和開啟的狀態(tài)下。
四、操作藍牙設(shè)備搜索與連接
1. 停止搜尋附近設(shè)備:uni.stopBluetoothDevicesDiscovery
當不再需要搜索附近的藍牙設(shè)備時,通過`uni.stopBluetoothDevicesDiscovery`來停止設(shè)備的搜尋,以節(jié)省資源和避免不必要的干擾。
2. 開始搜尋附近設(shè)備:uni.startBluetoothDevicesDiscovery

相對應(yīng)的,當我們需要搜索附近的藍牙設(shè)備時,會用到`uni.startBluetoothDevicesDiscovery`來啟動設(shè)備的搜索功能。
3. 創(chuàng)建藍牙連接:uni.createBLEConnection
找到目標設(shè)備后,我們需要建立連接。通過`uni.createBLEConnection`,我們可以初始化與設(shè)備的連接,為后續(xù)的數(shù)據(jù)傳輸打下基礎(chǔ)。
五、探索與交互:獲取服務(wù)、特征與寫入數(shù)據(jù)
1. 獲取藍牙設(shè)備服務(wù):uni.getBLEDeviceServices

在建立連接后,了解設(shè)備的服務(wù)是進一步交互的前提。使用`uni.getBLEDeviceServices`可以獲取到設(shè)備的服務(wù)列表。
2. 獲取服務(wù)中的特征值:uni.getBLEDeviceCharacteristics
特征值是藍牙設(shè)備服務(wù)的核心信息。通過`uni.getBLEDeviceCharacteristics`,我們可以獲取到某個服務(wù)中的所有特征值(characteristic)。
3. 向特征值中寫入數(shù)據(jù):uni.writeBLECharacteristicValue
在與低功耗藍牙設(shè)備交互時,我們有時需要向其特征值中寫入數(shù)據(jù)。`uni.writeBLECharacteristicValue`允許我們向設(shè)備寫入二進制數(shù)據(jù),實現(xiàn)數(shù)據(jù)的傳輸與交互。

注意事項與實際應(yīng)用
1. 藍牙連接的時間效性處理
藍牙連接有時會因為各種原因在一段時間后自動斷開。為了應(yīng)對這種情況,我們在需要打印的時候再進行設(shè)備連接,這樣可以在其他頁面上也使用打印功能,并成功保持連接。
2. 效果展示與輸出
通過效果圖和打印輸出的結(jié)果,我們可以直觀地看到藍牙設(shè)備的交互過程和結(jié)果,從而判斷操作的正確性和數(shù)據(jù)的準確性。
