蓝牙打印
## 关于uni-app框架
这里就不多说什么了 官网的文档写的很清楚
app连接低功耗蓝牙打印
-
**蓝牙打印机型号很多 这里就介绍两种型号 佳博,斑马 **
-
1,先初始化蓝牙设置
-
//蓝牙模式
-
var encode = require("./encoding.js")
// var app = getApp();
var jpPrinter = {
createNew: function () {
var jpPrinter = {};
var data = [];var bar = [“UPC-A”, “UPC-E”, “EAN13”, “EAN8”, “CODE39”, “ITF”, “CODABAR”, “CODE93”, “CODE128”];
jpPrinter.name = “账单模式”;
jpPrinter.init = function () { //初始化打印机
data.push(27)
data.push(64)
};jpPrinter.setText = function (content) { //设置文本内容
var code = new encode.TextEncoder(
‘gb18030’, {
NONSTANDARD_allowLegacyEncoding: true
}).encode(content)
for (var i = 0; i < code.length; ++i) {
data.push(code[i])
}
}jpPrinter.setUnderlineMode = function (n) { // 选择/取消下划线模式
data.push(28)
data.push(45)
data.push(n)
// 0,48 取消下划线模式
// 1,49 选择下划线模式(1 点宽)
// 2,50 选择下划线模式(2 点宽)
}jpPrinter.setBarcodeWidth = function (width) { //设置条码宽度
data.push(29)
data.push(119)
if (width > 6) {
width = 6;
}
if (width < 2) {
width = 1;
}
data.push(width)
}jpPrinter.setBarcodeHeight = function (height) { //设置条码高度
data.push(29)
data.push(104)
data.push(height)
}jpPrinter.setBarcodeContent = function (content) {
var code = new encode.TextEncoder(
‘gb18030’, {
NONSTANDARD_allowLegacyEncoding: true
}).encode(content)
// var ty = 73;
data.push(29)
data.push(107)
// switch (t) {
// case bar[0]:
// ty = 65;
// break;
// case bar[1]:
// ty = 66;
// break;
// case bar[2]:
// ty = 67;
// break;
// case bar[3]:
// ty = 68;
// break;
// case bar[4]:
// ty = 69;
// break;
// case bar[5]:
// ty = 70;
// break;
// case bar[6]:
// ty = 71;
// break;
// case bar[7]:
// ty = 72;
// break;
// case bar[8]:
// ty = 73;
// break;
// }
data.push(2) // 固定 打印JAN13(EAN13)的条码类型
for (var i = 0; i < code.length; ++i) {
data.push(code[i])
}
data.push(0)}
jpPrinter.setSelectSizeOfModuleForQRCode = function (n) { //设置二维码大小
data.push(29)
data.push(40)
data.push(107)
data.push(3)
data.push(0)
data.push(49)
data.push(67)
if (n > 15) {
n = 15
}
if (n < 1) {
n = 1
}
data.push(n)
}jpPrinter.setSelectErrorCorrectionLevelForQRCode = function (n) { //设置纠错等级
/*
n 功能 纠错能力
48 选择纠错等级 L 7
49 选择纠错等级 M 15
50 选择纠错等级 Q 25
51 选择纠错等级 H 30
*/
data.push(29)
data.push(40)
data.push(107)
data.push(3)
data.push(0)
data.push(49)
data.push(69)
data.push(n)
}jpPrinter.setStoreQRCodeData = function (content) { //设置二维码内容
var code = new encode.TextEncoder(
‘gb18030’, {
NONSTANDARD_allowLegacyEncoding: true
}).encode(content)
data.push(29)
data.push(40)
data.push(107)
data.push(parseInt((code.length + 3) % 256))
data.push(parseInt((code.length + 3) / 256))
data.push(49)
data.push(80)
data.push(48)for (var i = 0; i < code.length; ++i) {
data.push(code[i])
}
}jpPrinter.setPrintQRCode = function () { //打印二维码
data.push(29)
data.push(40)
data.push(107)
data.push(3)
data.push(0)
data.push(49)
data.push(81)
data.push(48)
}jpPrinter.setHorTab = function () { //移动打印位置到下一个水平定位点的位置
data.push(9)
}jpPrinter.setAbsolutePrintPosition = function(where) { //设置绝对打印位置
data.push(27)
data.push(36)
data.push(parseInt(where % 256))
data.push(parseInt(where / 256))
}jpPrinter.setRelativePrintPositon = function (where) { //设置相对横向打印位置
data.push(27)
data.push(92)
data.push(parseInt(where % 256))
data.push(parseInt(where / 256))
}jpPrinter.setSelectJustification = function (which) { //对齐方式
/*
0, 48 左对齐
1, 49 中间对齐
2, 50 右对齐
*/
data.push(27)
data.push(97)
data.push(which)
}jpPrinter.setFontSize=function(n){//设置字体大小
data.push(29)
data.push(33)
data.push(n)
// data.push( 10001000 )
}jpPrinter.bold = function (n) {//加粗
data.push(27)
data.push(69)
data.push(0) // 写死为0,都不加粗
// data.push(n)
}jpPrinter.rowSpace = function (n) { //设置行间距
return
// data.push(27)
// data.push(51)
// data.push(n)
}jpPrinter.setLeftMargin = function (n) { //设置左边距
data.push(29)
data.push(76)
data.push(parseInt(n % 256))
data.push(parseInt(n / 256))
}jpPrinter.setPrintingAreaWidth = function (width) { //设置打印区域宽度
data.push(29)
data.push(87)
data.push(parseInt(width % 256))
data.push(parseInt(width / 256))
}jpPrinter.setSound = function (n, t) { //设置蜂鸣器
data.push(27)
data.push(66)
if (n < 0) {
n = 1;
} else if (n > 9) {
n = 9;
}if (t < 0) {
t = 1;
} else if (t > 9) {
t = 9;
}
data.push(n)
data.push(t)
}jpPrinter.setBitmap = function (res) { //参数,画布的参数
console.log(res)
var width = parseInt((res.width + 7) / 8 * 8 / 8)
var height = res.height;
var time = 1;
var temp = res.data.length - width * 32;
var point_list = []
console.log(width + “–” + height)
data.push(29)
data.push(118)
data.push(48)
data.push(0)
data.push((parseInt((res.width + 7) / 8) * 8) / 8)
data.push(0)
data.push(parseInt(res.height % 256))
data.push(parseInt(res.height / 256))
console.log(res.data.length)
console.log(“temp=” + temp)
for (var i = 0; i < height; ++i) {
for (var j = 0; j < width; ++j) {
for (var k = 0; k < 32; k += 4) {
var po = {}
if (res.data[temp] == 0 && res.data[temp + 1] == 0 && res.data[temp + 2] == 0 && res.data[temp + 3] == 0) {
po.point = 0;
} else {
po.point = 1;
}
point_list.push(po)
temp += 4
}
}
time++
temp = res.data.length - width * 32 * time
}
for (var i = 0; i < point_list.length; i += 8) {
var p = point_list[i].point * 128 + point_list[i + 1].point * 64 + point_list[i + 2].point * 32 + point_list[i + 3].point * 16 + point_list[i + 4].point * 8 + point_list[i + 5].point * 4 + point_list[i + 6].point * 2 + point_list[i + 7].point
data.push§
}
}jpPrinter.setPrint = function () { //打印并换行
data.push(10)
}jpPrinter.setPrintAndFeed = function (feed) { //打印并走纸feed个单位
data.push(27)
data.push(74)
data.push(feed)
}jpPrinter.setPrintAndFeedRow = function (row) { //打印并走纸row行
data.push(27)
data.push(100)
data.push(row)
}jpPrinter.getData = function () { //获取打印数据
return data;
};return jpPrinter;
},
Query: function () {
var queryStatus = {};
var buf;
var dateView;
queryStatus.getRealtimeStatusTransmission = function (n) { //查询打印机实时状态
/*
n = 1:传送打印机状态
n = 2:传送脱机状态
n = 3:传送错误状态
n = 4:传送纸传感器状态
*/
buf = new ArrayBuffer(3)
dateView = new DataView(buf)
dateView.setUint8(0, 16)
dateView.setUint8(1, 4)
dateView.setUint8(2, n)
queryStatus.query(buf)
}
queryStatus.query = function (buf) {
wx.writeBLECharacteristicValue({
deviceId: app.BLEInformation.deviceId,
serviceId: app.BLEInformation.writeServiceId,
characteristicId: app.BLEInformation.writeCharaterId,
value: buf,
success: function (res) {
},
complete: function (res) {
console.log(res)
buf = null
dateView = null;
}
})
}
return queryStatus;
}
};
module.exports.jpPrinter = jpPrinter;
4. 调用方法 // 普通蓝牙 打印方法 ///
print: function(mac_address, string) {
if (!mac_address) {
this.$api.msg(‘请先连接蓝牙打印机’);
return;
}
this.$store.state.main = plus.android.runtimeMainActivity();
this.$store.state.BluetoothAdapter = plus.android.importClass('android.bluetooth.BluetoothAdapter');
var UUID = plus.android.importClass('java.util.UUID');
this.$store.state.uuid = UUID.fromString('00001101-0000-1000-8000-00805F9B34FB');
this.$store.state.BAdapter = this.$store.state.BluetoothAdapter.getDefaultAdapter();
this.$store.state.device = this.$store.state.BAdapter.getRemoteDevice(mac_address);
plus.android.importClass(this.$store.state.device);
this.$store.state.bluetoothSocket = this.$store.state.device.createInsecureRfcommSocketToServiceRecord(this.$store.state.uuid);
plus.android.importClass(this.$store.state.bluetoothSocket);
if (!this.$store.state.bluetoothSocket.isConnected()) {
console.log('检测到设备未连接,尝试连接....');
this.$store.state.bluetoothSocket.connect();
}
console.log('设备已连接');
if (this.$store.state.bluetoothSocket.isConnected()) {
this.$store.state.mac_address = mac_address;
var outputStream = this.$store.state.bluetoothSocket.getOutputStream();
plus.android.importClass(outputStream);
string = string ? string : '连接成功\r\n';
var bytes = plus.android.invoke(string, 'getBytes', 'gbk');
console.log(bytes);
outputStream.write(bytes);
outputStream.flush();
this.$store.state.device = null; //这里关键
this.$store.state.bluetoothSocket.close(); //必须关闭蓝牙连接否则意外断开的话打印错误
}
},
senBlData(deviceId, serviceId, characteristicId, uint8Array) {
// console.log('************deviceId = [' + deviceId + '] serviceId = [' + serviceId + '] characteristics=[' +
// characteristicId + "]")
var that = this
var uint8Buf = Array.from(uint8Array);
function split_array(datas, size) {
var result = [];
var j = 0
for (var i = 0; i < datas.length; i += size) {
result[j] = datas.slice(i, i + size)
j++
}
// console.log(result)
return result
}
var sendloop = split_array(uint8Buf, 20);
// console.log(sendloop.length)
function realWriteData(sendloop, i) {
var data = sendloop[i]
if (typeof(data) == "undefined") {
return
}
// console.log("第【" + i + "】次写数据" + data)
var buffer = new ArrayBuffer(data.length)
var dataView = new DataView(buffer)
for (var j = 0; j < data.length; j++) {
dataView.setUint8(j, data[j]);
}
uni.writeBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
value: buffer,
success(res) {
if(i == sendloop.length - 1){
that.closeBLEConnection(deviceId)
}
setTimeout(()=>{
realWriteData(sendloop, i + 1);
},20)
},
fail: (res) => {
console.log(res)
}
})
}
var i = 0;
realWriteData(sendloop, i);
},
//连接低功耗蓝牙设备
createBLEConnection(deviceId) {
uni.showLoading({
title: '连接设备中...'
});
return new Promise((resolve, reject) => {
uni.openBluetoothAdapter({
success: (res) => {
console.log(res)
setTimeout(()=> {
uni.startBluetoothDevicesDiscovery({
success: (res_t) => {
// console.log(res_t)
// 设置定时器counter,防止设备关闭时连接不上,一直在连接状态,,,
let num = 0
let firstTime = true // 防止下面 多次进入 uni.createBLEConnection.
let counter = setInterval(()=>{
num++
if(num == 10){
this.$api.msg('连接失败,请检查设备是否开启')
clearInterval(counter)
this.stopBluetoothDevicesDiscovery()
resolve('fail')
}
},1000)
uni.onBluetoothDeviceFound((res_p) => {
// console.log(res_p);
res_p.devices.forEach((item) => {
if (item.name) {
if(item.deviceId === deviceId && firstTime){
firstTime = false
console.log(item.deviceId)
clearInterval(counter)
this.stopBluetoothDevicesDiscovery()
uni.createBLEConnection({
deviceId: deviceId,
timeout: 10000, //超时时间,单位ms
success: (res) => {
// console.log(res)
// 此处有个bug,uniapp 的 bug。在蓝牙设备关闭的状态下进行连接,到了指定的超时时间,也还是会返回 createBLEConnection:ok ,
// 导致我后续无法判断,所以在这里 '多此一举',加一段 getBLEDeviceServices 的代码,可以分清楚连接状态。
// 后面 uniapp 修复了这个bug后,可以优化回来。zz
setTimeout(()=>{
uni.getBLEDeviceServices({
deviceId: deviceId,
success: (response) => {
// console.log(response)
let that = this
let once = true
for (let i = 0; i < response.services.length; i++) {
uni.getBLEDeviceCharacteristics({
deviceId: deviceId,
serviceId: response.services[i].uuid,
success: (res) => {
// console.log(res)
for (let j = 0; j < res.characteristics.length; j++) {
if (res.characteristics[j].properties.write && once) { // 循环 特征值 找到一个可写的即可。然后设备id,服务id,特征值存入本地。
console.log(res.characteristics[j].uuid)
once = false
uni.setStorageSync('deviceId',deviceId)
uni.setStorageSync('serviceId',response.services[i].uuid)
uni.setStorageSync('characteristicId',res.characteristics[j].uuid)
resolve('success')
uni.hideLoading()
return
}
}
}
})
}
},
fail: (response) => {
this.$api.msg('连接失败,请检查设备是否开启')
resolve('fail')
console.log(response)
}
})
},2000)
},
fail:(res) => {
console.log(res)
if(res.errCode == -1){
this.$api.msg('蓝牙设备已经处于连接状态')
}
if(res.errCode == 10002){
this.$api.msg('连接失败,请检查设备是否开启')
}
resolve('fail')
}
})
}
}
})
});
},
fail: (res_t) => {
console.log(res_t);
resolve('fail')
}
});
}, 300);
},
fail: (res) => {
console.log(res)
this.$api.msg('请先打开手机蓝牙功能再操作')
resolve('fail')
}
})
})
},
//断开与低功耗蓝牙设备的连接
closeBLEConnection(deviceId){
uni.closeBLEConnection({
deviceId,
success(res) {
console.log(res)
}
})
},
//关闭蓝牙模块
closeBluetoothAdapter() {
uni.closeBluetoothAdapter({
success:(res)=> {
console.log(res)
},
fail:(res)=> {
console.log(res)
}
})
},
//停止搜索蓝牙设备
stopBluetoothDevicesDiscovery() {
uni.stopBluetoothDevicesDiscovery({
success: e => {
console.log(e);
},
fail: e => {
console.log(e);
}
});
},
//打印样式
printByNormalBlu_Sale(){
let currentTime = formatterTime(new Date().getTime(), “yyyy-MM-dd hh:mm:ss”)
let message = this.mData.salesOrder.message.substr(0,21)
var head;
var height = 0;
var textSize = 30;
var lineSize = 15;
var barCodeHight = 50;
var string = “ENCODING GB18030\r\n”
string += “CENTER\r\n”
string += “SETMAG 1 1\r\n”
string += "TEXT GBUNSG24.CPF 0 0 " + height + " " + this.$store.state.loginProvider.userInfo.appPrintName + “\r\n”;
height += 35;
string += "TEXT GBUNSG24.CPF 0 0 " + height + " " + name + “\r\n”;
height += 35;
string += “LEFT\r\n”
string += “SETMAG 0 0\r\n”
string += “TEXT GBUNSG24.CPF 0 0 " + height + " 客户名称:” + this.mData.salesOrder.customerName + “\r\n”
height += textSize;
string += “TEXT GBUNSG24.CPF 0 0 " + height + " 客户地址:” + this.mData.salesOrder.addressDesc + “\r\n”
height += textSize;
string += “TEXT GBUNSG24.CPF 0 0 " + height + " 销售单号:” + this.mData.salesOrder.documentNum + “\r\n”
height += textSize;
string += “TEXT GBUNSG24.CPF 0 0 " + height + " 打印时间:” + currentTime + “\r\n”
height += textSize;
string += “TEXT GBUNSG24.CPF 0 0 " + height + " 联系人:” + this.mData.salesOrder.customerLinkman + “\r\n”
string += “TEXT GBUNSG24.CPF 0 300 " + height + " 电话:” + this.mData.salesOrder.customerHandset + “\r\n”
height += textSize;
string += “TEXT GBUNSG24.CPF 0 0 " + height + " 仓库:” + this.mData.salesOrder.warehouseName + “\r\n”
height += textSize;
string += “TEXT GBUNSG24.CPF 0 0 " + height + " 备注:” + message + “\r\n”
height += textSize;
string += “LINE 0 " + height + " 580 " + (height) + " 1\r\n”
height += lineSize;
string += “TEXT GBUNSG24.CPF 0 40 " + height + " 规格\r\n”
string += “TEXT GBUNSG24.CPF 0 140 " + height + " 数量\r\n”
string += “TEXT GBUNSG24.CPF 0 280 " + height + " 单价\r\n”
string += “TEXT GBUNSG24.CPF 0 440 " + height + " 金额(元)\r\n”