<!-- 蓝牙打印页面 -->
<template>
<view style="height: 100vh; display: flex; flex-direction: column">
<view style="flex: 1; overflow-y: auto; padding-bottom: 20rpx">
<button class="button" hover-class="hover" @click="startSearch" :loading="isScanning">
搜索蓝牙设备
</button>
<text class=".td">(Android8.0+系统需开启定位)</text>
<view v-if="list.length > 0" style="text-align: center">
<view style="font-size: 18px">蓝牙设备列表</view>
<view style="color: #666; font-size: 10px">点击连接蓝牙设备</view>
</view>
<view v-if="deviceinfo.deviceId" class="linkcss">蓝牙设备已连接:{{ deviceinfo.name }}</view>
<scroll-view class="device_list" scroll-y scroll-with-animation>
<view :class="item.deviceId === deviceinfo.deviceId ? 'sign_step' : ''" v-for="item in list"
:data-title="item.deviceId" :data-name="item.name" :data-advertisData="item.advertisServiceUUIDs"
:key="item.deviceId" @click="bindViewTap" class="item" hover-class="item_hover">
<view>
<view style="font-size: 16px">{{ item.name }}</view>
<view style="font-size: 12px">{{ item.deviceId }}</view>
<view style="font-size: 10px; color: #666">信号强度: {{ item.RSSI }}dBm
</view>
</view>
</view>
</scroll-view>
</view>
<view class="btncss">
<u-button :disabled="!deviceinfo.deviceId||printing" :custom-style="{ width: '200rpx' }" type="primary"
@click="submitPrinte" :loading="printing">打 印</u-button>
</view>
</view>
</template>
<script>
function inArray(arr, key, val) {
for (let i = 0; i < arr.length; i++) {
if (arr[i][key] === val) {
return i;
}
}
return -1;
}
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
var hexArr = Array.prototype.map.call(new Uint8Array(buffer), function(bit) {
return ("00" + bit.toString(16)).slice(-2);
});
return hexArr.join("");
}
function convertToGrayscale(data) {
let g = 0;
for (let i = 0; i < data.length; i += 4) {
g = data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11;
data[i] = g;
data[i + 1] = g;
data[i + 2] = g;
}
return data;
}
function setPixel(data, offset, value) {
data[offset] = value;
data[offset + 1] = value;
data[offset + 2] = value;
}
function adjustPixel(data, offset, value) {
data[offset] += value;
}
// 彩色图转成单色图
function convertToMonoImage(width, height, data, shake) {
let g = 0;
let e = 0;
for (let i = 0; i < data.length; i += 4) {
data[i] = data[i] * 0.3 + data[i + 1] * 0.59 + data[i + 2] * 0.11;
}
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
let dataOffset = (width * y + x) * 4;
g = data[dataOffset];
if (g >= 150) {
// 灰色转黑白的阈值, 可以调整打印效果
e = g - 255;
setPixel(data, dataOffset, 255);
} else {
e = g;
setPixel(data, dataOffset, 0);
}
if (!shake) continue;
if (x < width - 1 && y < height - 1) {
//右边像素处理
data[(width * y + x + 1) * 4] += (7 * e) / 16;
//下
data[(width * (y + 1) + x) * 4] += (5 * e) / 16;
//右下
data[(width * (y + 1) + x + 1) * 4] += e / 16;
//左下
if (x > 0) {
data[(width * (y + 1) + x - 1) * 4] += (3 * e) / 16;
}
} else if (x == width - 1 && y < height - 1) {
//下方像素处理
data[(width * (y + 1) + x) * 4] += (5 * e) / 16;
} else if (x < width - 1 && y == height - 1) {
//右边像素处理
data[(width * y + x + 1) * 4] += (7 * e) / 16;
}
}
}
return data;
}
import esc from "./utils/esc.js";
import tsc from "./utils/tsc.js";
import encode from "./utils/encoding.js";
import {
get_tem_data
} from "./printe_template.js";
import {
getEdPrintDTODetail
} from "@/api/index.js";
export default {
data() {
return {
printing: false,
imageSrc: "./wechat.jpg",
jpgSrc: "./wechat.jpg",
canvasWidth: 100,
canvasHeight: 100,
looptime: 0,
currentTime: 1,
lastData: 0,
oneTimeData: 0,
buffSize: [],
buffIndex: 0, //发送字节数下标
printNum: [],
printNumIndex: 0,
printerNum: 1,
currentPrint: 1,
isLabelSend: false,
isQuery: false,
jpgWidth: 200,
jpgHeight: 200,
list: [],
services: [],
serviceId: 0,
writeCharacter: false,
readCharacter: false,
notifyCharacter: false,
isScanning: false,
isReceiptSend: false,
detail: {},
type: [],
detaillist: [],
eb_detail: {},
longitude: "",
latitude: "",
eb_id: "",
};
},
onLoad: async function(option) {
this.eb_id = option.id;
console.log('@@@@@@@@@@@onLoad', option)
this.get_loc();
},
computed: {
deviceinfo() {
console.log('computed', this.BLEInformation)
return this.BLEInformation;
},
},
onShow() {
var list = [];
var numList = [];
var j = 0;
for (var i = 20; i < 200; i += 10) {
list[j] = i;
j++;
}
for (var i = 1; i < 10; i++) {
numList[i - 1] = i;
}
this.buffSize = list;
this.oneTimeData = list[0];
this.printNum = numList;
this.printerNum = numList[0];
},
methods: {
closeBluetoothAdapter() {
wx.closeBluetoothAdapter({
success(res) {
console.log('closeBluetoothAdapter', res)
}
})
},
get_loc() {
wx.showLoading({
title: "正在获取经纬度",
icon: "loading",
});
var that = this;
uni.getLocation({
type: "wgs84",
success(res) {
wx.hideLoading();
getApp().globalData.location = res;
console.log("getLocation", res);
that.latitude = res.latitude;
that.longitude = res.longitude;
that.get_EdPrintDTODetail();
},
fail() {
wx.hideLoading();
that.$tip.toast("获取不到经纬度接口,但支持导出/打印单证");
that.get_EdPrintDTODetail();
},
});
},
gettype(val) {
let type = "";
if (val.indexOf("DB") !== -1) {
type = "transfer";
}
if (val.indexOf("HS") !== -1) {
type = "recovery";
}
return type;
},
getindex(val) {
return Number(val.replace(/[^\d]/g, ""));
},
async get_EdPrintDTODetail() {
this.printing = true
wx.showLoading({
title: "正在获取数据",
icon: "loading",
});
const that = this
const {
data
} = await getEdPrintDTODetail({
bizNo: this.eb_id,
longitude: this.longitude,
latitude: this.latitude,
}).finally((e) => {
console.log('getEdPrintDTODetail', e)
that.$u.toast(e)
});
wx.hideLoading();
if (data.code === 200) {
this.type = [];
this.detaillist = [];
this.eb_detail = data.data;
data.data.printCategoryPaperList.forEach((m) => {
let skuNameall = [];
let realNumall = 0;
let badBoxNumall = 0;
let stainedBoxNumall = 0;
const item_type = this.gettype(m.category);
const item_index = this.getindex(m.category) - 1;
const t_data = get_tem_data(item_type, item_index);
this.type.push(item_type);
let sku_detail = data.data[m.dataPrefix];
console.log("sku_detail", m, sku_detail);
sku_detail?.boxDetailPrintList?.forEach((m) => {
skuNameall = [...skuNameall, m.skuName];
realNumall += m.realNum;
badBoxNumall += m.badBoxNum;
stainedBoxNumall += m.stainedBoxNum;
});
sku_detail = {
...data.data[m.dataPrefix],
skuNameall: skuNameall.join("、"),
realNumall,
stainedBoxNumall,
badBoxNumall,
agentReceiveNo: sku_detail?.agentReceiveNo || "",
};
const item = {
detail: sku_detail, // 数据
t_detail: t_data, // 模板数据
};
this.detaillist.push(item);
console.log("this.detaillist", this.detaillist);
});
if (!this.deviceinfo.deviceId) { // 如果没有设备id就要去搜索设备
this.startSearch();
} else { // 有设备id需要验证下连接
wx.showLoading({
title: "正在连接蓝牙设备",
icon: "loading",
});
wx.createBLEConnection({
deviceId: that.BLEInformation.deviceId,
success: function(res) {
console.log("连接成功", res, that.BLEInformation);
// that.BLEInformation.deviceId = e.currentTarget.dataset.title;
// that.BLEInformation.name = e.currentTarget.dataset.name;
// console.log("createBLEConnection", res, e, that.BLEInformation);
wx.hideLoading();
that.getSeviceId();
},
fail: function(e) {
wx.hideLoading();
that.$u.toast('设备已断开')
that.BLEInformation.platform = ''
that.BLEInformation.deviceId = ''
that.BLEInformation.writeCharaterId = ''
that.BLEInformation.writeServiceId = ''
that.BLEInformation.notifyCharaterId = ''
that.BLEInformation.notifyServiceId = ''
that.BLEInformation.readCharaterId = ''
that.BLEInformation.readServiceId = ''
that.$forceUpdate()
that.startSearch();
},
complete: function(e) {
console.log(e);
},
});
}
} else {
this.printing = false
this.$u.toast(data.message);
setTimeout(function() {
uni.navigateBack(-1);
}, 1500);
}
},
receiptTest() {
//票据打印方法 ,t_data:模板数据
const that = this;
var canvasWidth = this.canvasWidth;
var canvasHeight = this.canvasHeight;
var command = esc.jpPrinter.createNew();
command.init(); //初始化打印机
command.setSelectJustification(1);
command.setCharacterSize(0);
command.setText("公司");
command.setPrint(); //打印并换行
that.prepareSend(command.getData()); //准备发送数据
},
startSearch() {
var that = this;
that.closeBluetoothAdapter()
wx.openBluetoothAdapter({
success: function(res) {
wx.getBluetoothAdapterState({
success: function(res) {
console.log("openBluetoothAdapter success", res);
if (res.available) {
if (res.discovering) {
// wx.stopBluetoothDevicesDiscovery({
// success: function(res) {
// console.log(res)
// }
// })
} else {
// that.startBluetoothDevicesDiscovery()
that.getBluetoothDevices();
}
// that.checkPemission()
} else {
wx.showModal({
title: "提示",
content: "本机蓝牙不可用",
showCancel: false,
});
}
},
});
},
fail: function(res) {
// if (res.errCode === 10001) {
// wx.onBluetoothAdapterStateChange(function (res) {
// console.log('onBluetoothAdapterStateChange', res)
// if (res.available) {
// this.startBluetoothDevicesDiscovery()
// }
// })
// }
console.log(res);
wx.showModal({
title: "提示",
content: "蓝牙初始化失败,请到设置打开蓝牙",
showCancel: false,
});
},
});
},
checkPemission() {
var that = this;
var platform = that.BLEInformation.platform;
if (platform == "ios") {
that.globalData.platform = "ios";
that.getBluetoothDevices();
} else if (platform == "android") {
that.globalData.platform = "android";
console.log(
that
.getSystem()
.substring(
that.getSystem().length - (that.getSystem().length - 8),
that.getSystem().length - (that.getSystem().length - 8) + 1
)
);
if (
that
.getSystem()
.substring(
that.getSystem().length - (that.getSystem().length - 8),
that.getSystem().length - (that.getSystem().length - 8) + 1
) > 5
) {
wx.getSetting({
success: function(res) {
console.log(res);
if (!res.authSetting["scope.userLocation"]) {
wx.authorize({
scope: "scope.userLocation",
complete: function(res) {
that.getBluetoothDevices();
},
});
} else {
that.getBluetoothDevices();
}
},
});
}
}
},
getBluetoothDevices() {
var that = this;
console.log("start search");
wx.showLoading({
title: "正在搜索",
icon: "loading",
});
that.isScanning = true;
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
success: function(res) {
console.log(res);
setTimeout(function() {
wx.getBluetoothDevices({
success: function(res) {
console.log("###getBluetoothDevices", res);
var devices = [];
var num = 0;
for (var i = 0; i < res.devices.length; ++i) {
if (res.devices[i].name != "未知设备") {
devices[num] = res.devices[i];
num++;
}
}
that.list = devices;
that.isScanning = false;
that.printing = false
wx.hideLoading();
wx.stopPullDownRefresh();
wx.stopBluetoothDevicesDiscovery({
success: function(res) {
console.log("停止搜索蓝牙");
},
});
},
});
}, 5000);
},
});
},
bindViewTap(e) {
console.log("bindViewTap", e);
var that = this;
wx.stopBluetoothDevicesDiscovery({
success: function(res) {
console.log(res);
},
});
that.serviceId = 0;
that.writeCharacter = false;
that.readCharacter = false;
that.notifyCharacter = false;
console.log(e);
wx.showLoading({
title: "正在连接",
});
wx.createBLEConnection({
deviceId: e.currentTarget.dataset.title,
success: function(res) {
console.log("连接成功", res, e, that.BLEInformation);
that.BLEInformation.deviceId = e.currentTarget.dataset.title;
that.BLEInformation.name = e.currentTarget.dataset.name;
console.log("createBLEConnection", res, e, that.BLEInformation);
that.getSeviceId();
},
fail: function(e) {
wx.showModal({
title: "提示",
content: "连接失败",
showCancel: false,
});
console.log("连接失败", e);
wx.hideLoading();
that.closeBluetoothAdapter()
},
complete: function(e) {
console.log(e);
},
});
},
getSeviceId() {
var that = this;
var platform = that.BLEInformation.platform;
console.log(that.BLEInformation.deviceId);
wx.getBLEDeviceServices({
deviceId: that.BLEInformation.deviceId,
success: function(res) {
console.log("getSeviceId", res);
// var realId = ''
// if (platform == 'android') {
// // for(var i=0;i<res.services.length;++i){
// // var item = res.services[i].uuid
// // if (item == "0000FEE7-0000-1000-8000-00805F9B34FB"){
// realId = "0000FEE7-0000-1000-8000-00805F9B34FB"
// // break;
// // }
// // }
// } else if (platform == 'ios') {
// // for(var i=0;i<res.services.length;++i){
// // var item = res.services[i].uuid
// // if (item == "49535343-FE7D-4AE5-8FA9-9FAFD205E455"){
// realId = "49535343-FE7D-4AE5-8FA9-9FAFD205E455"
// // break
// // }
// // }
// }
// that.BLEInformation.serviceId = realId
that.services = res.services;
that.getCharacteristics();
},
fail: function(e) {
console.log(e);
},
complete: function(e) {
console.log(e);
},
});
},
getCharacteristics() {
var that = this;
var list = that.services;
var num = that.serviceId;
var write = that.writeCharacter;
var read = that.readCharacter;
var notify = that.notifyCharacter;
wx.getBLEDeviceCharacteristics({
deviceId: that.BLEInformation.deviceId,
serviceId: list[num].uuid,
success: function(res) {
console.log("getCharacteristics", res);
for (var i = 0; i < res.characteristics.length; ++i) {
var properties = res.characteristics[i].properties;
var item = res.characteristics[i].uuid;
if (!notify) {
if (properties.notify) {
that.BLEInformation.notifyCharaterId = item;
that.BLEInformation.notifyServiceId = list[num].uuid;
notify = true;
}
}
if (!write) {
if (properties.write) {
that.BLEInformation.writeCharaterId = item;
that.BLEInformation.writeServiceId = list[num].uuid;
write = true;
}
}
if (!read) {
if (properties.read) {
that.BLEInformation.readCharaterId = item;
that.BLEInformation.readServiceId = list[num].uuid;
read = true;
}
}
}
if (!write || !notify || !read) {
num++;
that.writeCharacter = write;
that.readCharacter = read;
that.notifyCharacter = notify;
that.serviceId = num;
if (num == list.length) {
wx.showModal({
title: "提示",
content: "找不到该读写的特征值",
showCancel: false,
});
} else {
that.getCharacteristics();
}
} else {
that.openControl();
}
},
fail: function(e) {
console.log(e);
},
complete: function(e) {
console.log("write:" + that.BLEInformation.writeCharaterId);
console.log("read:" + that.BLEInformation.readCharaterId);
console.log("notify:" + that.BLEInformation.notifyCharaterId);
},
});
},
openControl() {
// 连接成功后打印
console.log(this.BLEInformation);
wx.hideLoading();
const that = this;
wx.showModal({
title: "提示",
content: "蓝牙设备连接成功,是否确认打印",
success(res) {
if (res.confirm) {
that.submitPrinte();
} else if (res.cancel) {
that.printing = false
}
},
});
},
submitPrinte() {
console.log("this.detaillist", this.detaillist);
// if (this.eb_detail) {
this.receiptTest();
// } else {
// this.get_loc()
// }
},
prepareSend(buff) {
//准备发送,根据每次发送字节数来处理分包数量
//console.log(buff)
var that = this;
var time = this.oneTimeData;
var looptime = parseInt(buff.length / time);
var lastData = parseInt(buff.length % time);
//console.log(looptime + "---" + lastData)
that.looptime = looptime + 1;
that.lastData = lastData;
that.currentTime = 1;
that.Send(buff);
},
Send(buff) {
this.printing = true
//分包发送
var that = this;
var currentTime = this.currentTime;
var loopTime = this.looptime;
var lastData = this.lastData;
var onTimeData = this.oneTimeData;
var printNum = this.printerNum;
var currentPrint = this.currentPrint;
var buf;
var dataView;
if (currentTime < loopTime) {
buf = new ArrayBuffer(onTimeData);
dataView = new DataView(buf);
for (var i = 0; i < onTimeData; ++i) {
dataView.setUint8(i, buff[(currentTime - 1) * onTimeData + i]);
}
} else {
buf = new ArrayBuffer(lastData);
dataView = new DataView(buf);
for (var i = 0; i < lastData; ++i) {
dataView.setUint8(i, buff[(currentTime - 1) * onTimeData + i]);
}
}
console.log(
"第" + currentTime + "次发送数据大小为:" + buf.byteLength,
this.BLEInformation
);
setTimeout(() => {
wx.writeBLECharacteristicValue({
deviceId: this.BLEInformation.deviceId,
serviceId: this.BLEInformation.writeServiceId,
characteristicId: this.BLEInformation.writeCharaterId,
value: buf,
success: function(res) {
if (currentTime <= loopTime) {
// wx.showLoading({
// title: '传输中...',
// })
} else {
wx.showToast({
title: "已打印第" + currentPrint + "张成功",
});
}
//console.log(res)
},
fail: function(e) {
console.log("失败原因", e);
if ([10003, 10006, 10000, 10001, 10002].includes(e.errCode)) {
wx.showToast({
title: "打印失败,蓝牙已断开连接",
icon: "none",
});
that.closeBluetoothAdapter()
that.BLEInformation.platform = ''
that.BLEInformation.deviceId = ''
that.BLEInformation.writeCharaterId = ''
that.BLEInformation.writeServiceId = ''
that.BLEInformation.notifyCharaterId = ''
that.BLEInformation.notifyServiceId = ''
that.BLEInformation.readCharaterId = ''
that.BLEInformation.readServiceId = ''
that.$forceUpdate()
} else {
wx.showToast({
title: "打印失败",
icon: "none",
});
}
that.printing = false
//console.log(e)
},
complete: function() {
currentTime++;
if (currentTime <= loopTime) {
that.currentTime = currentTime;
that.Send(buff);
} else {
if (currentPrint == printNum) {
console.log('that.looptime', that.looptime)
const num = that.looptime
setTimeout(() => {
that.printing = false
}, num * 80)
that.looptime = 0;
that.lastData = 0;
that.currentTime = 1;
that.isReceiptSend = false;
that.currentPrint = 1;
} else {
currentPrint++;
that.currentPrint = currentPrint;
that.currentTime = 1;
that.Send(buff);
}
}
},
});
}, 50);
},
},
};
</script>
<style scoped lang="scss">
.btncss {
background-color: white;
padding-inline: 20rpx;
width: 100%;
padding-top: 30rpx;
padding-bottom: 50rpx;
box-shadow: 2px 2px 4px 4px rgba(223, 223, 223, 0.5);
z-index: 9999;
}
.linkcss {
border: 2px solid #54bec2;
padding: 10px;
margin: 10px;
}
.button {
margin-top: 20px;
margin-bottom: 20px;
width: 70%;
background-color: #54bec2;
color: white;
border-radius: 98rpx;
background: bg_red;
}
/* 按下变颜色 */
.hover {
background: #dcdcdc;
}
.device_list {
height: auto;
margin-left: 20rpx;
margin-right: 20rpx;
margin-top: 10px;
margin-bottom: 20px;
/* border: 1px solid #EEE; */
width: auto;
}
.td {
display: flex;
align-items: center;
justify-content: center;
margin-top: 10px;
}
/* .item {
padding-top: 10px;
padding-bottom: 10px;
height: 130rpx;
width: 100%;
} */
.item {
display: block;
background-color: white;
border-radius: 18rpx;
margin-bottom: 16rpx;
padding: 8px;
}
.item_hover {
background-color: rgba(0, 0, 0, 0.1);
}
.block {
display: block;
color: #ffffff;
padding: 5px;
}
.button::after {
border-width: 0px;
}
.sign_step>view::after {
// 对钩的三角行底色
position: absolute;
right: 0;
top: 0;
width: 0;
height: 0;
content: "";
border: 16px solid;
border-color: #70cad3 #70cad3 transparent transparent;
border-bottom-right-radius: 2px;
}
.sign_step {
position: relative;
border: 2px solid #54bec2;
}
.sign_step>view::before {
// 对钩样式
position: absolute;
right: 2px;
top: 4px;
z-index: 1;
width: 10px;
height: 5px;
content: "";
background: transparent;
border: 2px solid white;
border-top: none;
border-right: none;
-webkit-transform: rotate(-55deg);
-ms-transform: rotate(-55deg);
transform: rotate(-55deg);
}
/* pages/bleConnect/bleConnect.wxss */
</style>
微信小程序(uni-app)中使用便捷式蓝牙打印机(完整代码)
于 2024-03-19 16:53:57 首次发布