微信小程序小票打印功能(以及中文亂碼的解決)

因為業(yè)務需求,需要實現(xiàn)微信小程序連接熱敏打印機打印小票鄙皇。首先我要先知道微信小程序有沒有藍牙操作相關的API先巴,然后就是如何藍牙連接打印機短绸,發(fā)送打印指令了车吹。

通過查看小程序文檔,我看到微信小程序是支持藍牙操作的

小程序文檔

但是我看到它有兩個醋闭,低功耗藍牙窄驹,藍牙。藍牙我們知道证逻,低功耗藍牙是什么東西乐埠,網(wǎng)上查了下,解釋如下:
以前可能有藍牙1.0囚企、藍牙2.0丈咐、藍牙3.0、藍牙4.0之類的以數(shù)字結尾的藍牙版本號龙宏,而實際上棵逊,在最新的標準中,已經(jīng)不再使用數(shù)字版本號作為藍牙版本的區(qū)分了银酗,取而代之的是經(jīng)典藍牙與低功耗藍牙(BLE)這兩種區(qū)別
低功耗藍牙(Bluetooth Low Energy辆影,或稱Bluetooth LEBLE黍特,舊商標Bluetooth Smart)也稱低功耗藍牙蛙讥,是藍牙技術聯(lián)盟設計和銷售的一種個人局域網(wǎng)技術,旨在用于醫(yī)療保健灭衷、運動健身次慢、信標、安防翔曲、家庭娛樂等領域的新興應用迫像。相較經(jīng)典藍牙,低功耗藍牙旨在保持同等通信范圍的同時顯著降低功耗和成本.

我要打印肯定要與打印機進行數(shù)據(jù)通信的瞳遍,通過文檔我看到侵蒙,只有低功耗藍牙里面有一個寫和讀的方法,那么微信就限定我只能通過低功耗藍牙相關api進行與打印機相關交互傅蹂,同時也限定了我的打印機也要支持低功耗藍牙連接纷闺,幸運的是我的打印機是支持的。
接下來看怎么寫代碼了份蝴,官方給了我們一個藍牙操作的demo,那我就直接在demo上改了犁功。



點上面就能打開示例代碼了。


demo顯示界面

上面是demo界面婚夫,點擊開始掃描就能收到周圍的藍牙了浸卦,我的打印機藍牙也在搜索結果的列表里,我試了下案糙,能夠連接到我的打印機限嫌。
接下來我打印一段文字試試靴庆。
在index.js里面我改寫了這個方法,我打印了一個hello world.
writeBLECharacteristicValue() {
    let str = "hello world";
    let dataBuffer = new ArrayBuffer(100)
    let dataView = new DataView(dataBuffer)
     for (var i = 0; i < str.length; i++) {
      dataView.setUint8(i, str.charAt(i).charCodeAt())
    }
    wx.writeBLECharacteristicValue({
      deviceId: this._deviceId,
      serviceId: this._serviceId,
      characteristicId: this._characteristicId,
      value: dataBuffer,
      success: function(res) {
        console.log('發(fā)送的數(shù)據(jù):' + that.writeDatas)
        console.log('message發(fā)送成功')
      },
      fail: function(res) {
        console.log("data:" + res)
      },
      complete: function(res) {
        console.log("data:" + res)
      }
    })
}

打印結果:


打印結果

看到了打印成功,接下來我試了下中文

writeBLECharacteristicValue() {
    let str = "你好 世界";
    let dataBuffer = new ArrayBuffer(100)
    let dataView = new DataView(dataBuffer)
     for (var i = 0; i < str.length; i++) {
      dataView.setUint8(i, str.charAt(i).charCodeAt())
    }
    wx.writeBLECharacteristicValue({
      deviceId: this._deviceId,
      serviceId: this._serviceId,
      characteristicId: this._characteristicId,
      value: dataBuffer,
      success: function(res) {
        console.log('message發(fā)送成功')
      },
      fail: function(res) {
        console.log("data:" + res)
      },
      complete: function(res) {
        console.log("data:" + res)
      }
    })
}

打印結果:


這打的是什么鬼怒医,亂碼了炉抒。初步推斷可能是編碼問題,網(wǎng)上也收到了相關問題的一些解答稚叹。
小程序丨【已解決】藍牙打印機打印中文亂碼

說是我的中文編碼不對焰薄,應該轉成gbk,然后再轉成16進制扒袖,最后發(fā)送給打印機塞茅,說是這么說,但是代碼怎么寫季率,這片文章沒說野瘦。我記得js是沒有轉gbk的方法的,只能看看別人怎么搞得飒泻,還真找到一個人寫的鞭光。
小程序藍牙打印

趕緊放到我的代碼里試了一下,運行后發(fā)現(xiàn)了一個問題:

這個gbk轉換的代碼怎么來的,通篇就這個一句話刹孔,并沒有講怎么來的髓霞,我推測他可能引入了一個庫gbk相關的,于是接著搜索,還真有相關的庫http://www.vuln.cn/2901
下載下來

下載后,打開這個庫
庫文件內(nèi)容

這個該怎么放到小程序里面用呢,在下載頁面我們看到了它的用法介紹

這個寫法小程序里不能用啊,不支持這種使用方式啊秸谢。小程序只支持下面這樣的

function send0X0A() {
  const buffer = new ArrayBuffer(1)
  const dataView = new DataView(buffer)
  dataView.setUint8(0, 0x0a)
  return buffer;
}

定義方法的地方模塊導出
module.exports = {
  hexStringToArrayBuffer: hexStringToArrayBuffer,
  hexStringToBuff: hexStringToBuff,
  send0X0A: send0X0A
}

使用的地方要引用一下
var util = require('../../utils/util.js');

沒辦法估蹄,只能修改庫轧叽,一頓操作猛如虎,搞成了下面這樣的



這里我只導出了一個編碼的方法,調用的地方是這樣使用的

const gbk = require('./gbk.js');
const hexStringToBuff = str => { //str='中國:WXHSH'
  const buffer = new ArrayBuffer((sumStrLength(str)) * 4)
  const dataView = new DataView(buffer)
  var data = str.toString();
  var p = 0; //ArrayBuffer 偏移量
  for (var i = 0; i < data.length; i++) {
    if (isCN(data[i])) { //是中文
      //調用GBK 轉碼
      var t = gbk.encode(data[i]);
      for (var j = 0; j < 2; j++) {
        var code = t[j * 2] + t[j * 2 + 1];
        var temp = parseInt(code, 16)
        dataView.setUint8(p++, temp)
      }
    } else {
      var temp = data.charCodeAt(i);
      dataView.setUint8(p++, temp)
    }
  }
  return buffer;
}
}

運行結果:圖我就不截了,直接說結果垢村,結果就是啥也沒打印出來,這是怎么回事呢侵佃,調試下看看。



發(fā)現(xiàn)問題了,一個中文是占兩個字節(jié)的%C4%C3,按照上面那個哥們的寫法我只分割了%C,4%烙常,這是什么鬼蚕脏,應該是%C4秦驯,%C3译隘,才對,兩個各代表一個字節(jié)碼編號厅目。于是改了下代碼:

const hexStringToBuff = str => { //str='中國:WXHSH'
  const buffer = new ArrayBuffer((sumStrLength(str)) * 4)
  const dataView = new DataView(buffer)
  var data = str.toString();
  var p = 0; //ArrayBuffer 偏移量
  for (var i = 0; i < data.length; i++) {
    if (isCN(data[i])) { //是中文
      //調用GBK 轉碼
      var t = gbk.encode(data[i]);
      for (var j = 0; j < 2; j++) {
        //var code = t[j * 2] + t[j * 2 + 1];
        var code = t[j * 3 + 1] + t[j * 3 + 2];
        var temp = parseInt(code, 16)
        dataView.setUint8(p++, temp)
      }
    } else {
      var temp = data.charCodeAt(i);
      dataView.setUint8(p++, temp)
    }
  }
  return buffer;
}

再次調試運行下看看:



嗯這下 算分割對了深啤,但是打印機還是沒反應诱桂,在看代碼發(fā)現(xiàn)temp = NaN,這是怎么回事呢访诱,于是網(wǎng)上搜索gbk轉16進制九榔,總共發(fā)現(xiàn)這兩個可用的方法

function toUnicode(s) {
  var str = "";
  for (var i = 0; i < s.length; i++) {
    str += "\\u" + s.charCodeAt(i).toString(16) + "\t";
  }
  return str;
}

function strToHexCharCode(str) {
  if (str === "")
    return "";
  var hexCharCode = [];
  hexCharCode.push("0x");
  for (var i = 0; i < str.length; i++) {
    hexCharCode.push((str.charCodeAt(i)).toString(16));
  }
  return hexCharCode.join("");
}

調用其中一個看一下



哎呀,這回好像temp有值了切威,還是16進制的缰冤,趕緊通過斷點怀薛,看看打印機反應,乖乖有反應了,不截圖了呐能,直接說結果吧摆出,亂碼 亂碼 亂碼,這就奇了怪了,都轉好了,怎么還打印不出來呢。網(wǎng)上一頓搜也沒什么結果泌射, 靜下心來想一想豺裆,之前我們App是有打印功能的躺酒,那App傳輸?shù)臄?shù)據(jù)是什么樣的呢,對比下我傳的有什么不一樣么?



這個是android程序累颂,它是通過getBytes()獲取文本字節(jié)流。運行程序,查看打印結果

我發(fā)現(xiàn) android 轉出來的都是負的整數(shù)悦荒,不像我傳的0x...... ,看來還是我的數(shù)據(jù)轉換的不對嘹吨,再看一眼調試頁面搬味。



C4 E3,貌似是十六進制數(shù)據(jù),%號什么鬼躺苦,它不可能轉成整型身腻,temp 一直是NaN,得 我去掉%號試試产还。

呀嘿匹厘,temp有值了,跟Android的數(shù)據(jù)差不多脐区,都是整數(shù)愈诚。過掉斷點看看。

哈哈,出來了炕柔,這一刻的心情你懂的酌泰。

到此 小程序藍牙打印算是流程搞通了,網(wǎng)上資料有時候不太全匕累,有時還有錯誤陵刹,這就需要我們大膽猜測勇敢驗證,最后福利來了欢嘿,我把完整demo貢獻上衰琐。
https://github.com/lerpo/bluethooth.git

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市炼蹦,隨后出現(xiàn)的幾起案子羡宙,更是在濱河造成了極大的恐慌,老刑警劉巖掐隐,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狗热,死亡現(xiàn)場離奇詭異,居然都是意外死亡虑省,警方通過查閱死者的電腦和手機匿刮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來探颈,“玉大人僻焚,你說我怎么就攤上這事∠ダ蓿” “怎么了虑啤?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長架馋。 經(jīng)常有香客問我狞山,道長,這世上最難降的妖魔是什么叉寂? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任萍启,我火速辦了婚禮,結果婚禮上屏鳍,老公的妹妹穿的比我還像新娘勘纯。我一直安慰自己,他們只是感情好钓瞭,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布驳遵。 她就那樣靜靜地躺著,像睡著了一般山涡。 火紅的嫁衣襯著肌膚如雪堤结。 梳的紋絲不亂的頭發(fā)上唆迁,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機與錄音竞穷,去河邊找鬼唐责。 笑死,一個胖子當著我的面吹牛瘾带,可吹牛的內(nèi)容都是我干的鼠哥。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼看政,長吁一口氣:“原來是場噩夢啊……” “哼肴盏!你這毒婦竟也來了?” 一聲冷哼從身側響起帽衙,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤菜皂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后厉萝,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恍飘,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年谴垫,在試婚紗的時候發(fā)現(xiàn)自己被綠了章母。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡翩剪,死狀恐怖乳怎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情前弯,我是刑警寧澤蚪缀,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站恕出,受9級特大地震影響询枚,放射性物質發(fā)生泄漏。R本人自食惡果不足惜浙巫,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一金蜀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧的畴,春花似錦渊抄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至渣慕,卻和暖如春嘶炭,著一層夾襖步出監(jiān)牢的瞬間谓娃,已是汗流浹背蜀铲。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留弥姻,地道東北人强经。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓睡陪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親匿情。 傳聞我的和親對象是個殘疾皇子兰迫,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 每天堅持記錄自己的成長汁果,是特別美好的一件事。這樣的一天下來玲躯,是充實的据德,對今天有一個很好的梳理,同時跷车,對明天又多了...
    陸寧閱讀 421評論 0 0
  • 賀變麗 焦點解決初級10期 洛陽 堅持分享第49天 2018--07--30 這兩天約練了兩次(第1...
    hebl閱讀 1,014評論 0 1
  • 1960年初秋午后棘利,陽光暖洋洋的灑下來。 敬禮老漢看著坑里那碎金似的太陽的倒影隨著輕風吹拂朽缴,微微的搖蕩起來善玫。搖起了...
    小揚少爺閱讀 388評論 2 6
  • “外面沒有別人,只有自己”這是張德芬說的一句話密强,說的挺好的茅郎。 當你在和世界上事物有聯(lián)系時,你和他們相處的狀態(tài)或渤,很多...
    莉萍LP閱讀 163評論 0 0
  • 守規(guī)則只洒!想起旅游的一件事:導游每次都把集合時間說好幾遍!但是總有以各種理由遲到的劳坑!有次游西湖毕谴,導游說好一點二十集合...
    Sabrinazou閱讀 170評論 0 1