测试设备:得力DL-720W条码标签打印机
效果图:![](https://img-blog.csdnimg.cn/direct/320c6129c67f4ecbb235567af667aa54.jpeg)
具体代码如下:
1、搜索连接蓝牙
connect.wxml
<view class="main">
<van-button block type="info" bindtap="startSearch" loading='{{isScanning}}'>开始搜索</van-button>
<scroll-view class="device-list" scroll-y scroll-with-animation>
<view class="connect-name">已发现{{list.length}}个外围设备</view>
<view
wx:for="{{list}}"
wx:for-item="item"
data-title="{{item.deviceId}}"
data-name="{{item.name}}"
data-advertisData="{{item.advertisServiceUUIDs}}"
data-item="{{item}}"
wx:key="{{item.deviceId}}"
bindtap="bindViewTap"
>
<view class="device-item">
<view class="name">{{item.name}}</view>
<view class="device-id">UUID: {{item.deviceId}}</view>
</view>
</view>
</scroll-view>
<view wx:if="{{lastDevice}}">
<view class="connect-name">最近连接的设备{{lastDevice.name}}</view>
<view class="btn-area">
<van-button block type="info" data-deviceId="{{lastDevice.deviceId}}" data-item="{{lastDevice}}" bindtap="createBLEConnectionWithDeviceId">直接连接</van-button>
</view>
</view>
</view>
connect.scss
.main{
padding: 20rpx;
.device-list{
height: 700rpx;
margin: 10rpx;
.device-item{
padding: 20rpx 0;
border-bottom: 2rpx solid #E6EBF1;
}
.name{
font-size: 32rpx;
}
.device-id{
font-size: 24rpx;
color: #666;
}
}
.connect-name{
text-align: center;
padding: 15rpx 0;
}
}
connect.js
let app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
list: [],
services: [],
serviceId: 0,
writeCharacter: false,
readCharacter: false,
notifyCharacter: false,
isScanning:false
},
// 开始搜索
startSearch: function () {
let that = this;
if (!wx.openBluetoothAdapter) {
wx.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
})
return
}
// 初始化蓝牙设备
wx.openBluetoothAdapter({
success: function (res) {
console.log('第一步,蓝牙初始化成功', res)
// 获取本机蓝牙适配器状态
wx.getBluetoothAdapterState({
success: function (res) {
// 蓝牙适配器是否可用
if (res.available) {
// 是否正在搜索设备
if (res.discovering) {
// 停止搜寻附近的蓝牙外围设备。若已经找到需要的蓝牙设备并不需要继续搜索时,建议调用该接口停止蓝牙搜索。
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
console.log(res)
}
})
}
that.checkPemission()
} else {
wx.showModal({
title: '提示',
content: '本机蓝牙不可用',
})
}
},
})
}, fail: function () {
wx.showModal({
title: '提示',
content: '蓝牙初始化失败,请打开蓝牙后重试',
})
}
})
},
checkPemission: function () { //android 6.0以上需授权地理位置权限
let that = this;
let platform = app.BLEInformation.platform;
if (platform == 'ios') {
app.globalData.platform = 'ios';
that.getBluetoothDevices()
} else if (platform == 'android') {
app.globalData.platform = 'android'
console.log(app.getSystem().substring(app.getSystem().length - (app.getSystem().length - 8), app.getSystem().length - (app.getSystem().length - 8) + 1))
if (app.getSystem().substring(app.getSystem().length - (app.getSystem().length - 8), app.getSystem().length - (app.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()
}
}
})
}else{
that.getBluetoothDevices()
}
}
},
getBluetoothDevices: function () { //获取蓝牙设备信息
let that = this;
wx.showLoading({ title: '正在加载'})
that.setData({
isScanning:true
})
// 开始搜寻附近的蓝牙外围设备。
wx.startBluetoothDevicesDiscovery({
success: function (res) {
console.log(res)
setTimeout(function () {
wx.getBluetoothDevices({
success: function (res) {
let devices = []
let num = 0
for (let i = 0; i < res.devices.length; ++i) {
if (res.devices[i].name != '未知设备') {
devices[num] = res.devices[i]
num++
}
}
that.setData({
list: devices,
isScanning:false
})
wx.hideLoading()
wx.stopPullDownRefresh()
},
})
}, 3000)
},
})
},
// 连接蓝牙设备
bindViewTap: function (e) {
// 先清除之前已连接蓝牙设备数据缓存
wx.removeStorageSync('bleItem');
wx.removeStorageSync('bleWriteInfo');
wx.removeStorageSync('bleNotifyInfo');
let that = this;
// 停止搜寻附近的蓝牙外围设备。若已经找到需要的蓝牙设备并不需要继续搜索时,建议调用该接口停止蓝牙搜索
wx.stopBluetoothDevicesDiscovery({
success: function (res) { console.log(res) },
})
that.setData({
serviceId: 0,
writeCharacter: false,
readCharacter: false,
notifyCharacter: false
})
wx.showLoading({ title: '正在连接' })
const { title,item } = e.currentTarget.dataset;
this._createBLEConnection(title,item)
},
// 连接蓝牙低功耗设备。
// 若小程序在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备,无需再次进行搜索操作。
_createBLEConnection(deviceId,item){
const that = this;
wx.createBLEConnection({
deviceId: deviceId,
success: function (res) {
console.log(res)
app.BLEInformation.deviceId = deviceId;
// 把已连接的蓝牙设备存入缓存
wx.setStorageSync('bleItem', item);
that.getSeviceId()
}, fail: function (e) {
console.log(e,'连接失败')
// wx.showModal({
// title: '提示',
// content: '连接失败',
// })
console.log(e)
}, complete: function (e) {
console.log(e)
wx.hideLoading()
}
})
},
// 获取蓝牙低功耗设备所有服务 (service)。
getSeviceId: function () {
let that = this
let platform = app.BLEInformation.platform;
wx.getBLEDeviceServices({
deviceId: app.BLEInformation.deviceId,
success: function (res) {
console.log(res)
that.setData({ services: res.services })
that.getCharacteristics()
}, fail: function (e) {
console.log(e)
}, complete: function (e) {
console.log(e)
}
})
},
getCharacteristics: function () {
let that = this;
let list = that.data.services;
let num = that.data.serviceId;
let write = that.data.writeCharacter;
let read = that.data.readCharacter;
let notify = that.data.notifyCharacter;
// 获取蓝牙低功耗设备某个服务中所有特征 (characteristic)。
wx.getBLEDeviceCharacteristics({
deviceId: app.BLEInformation.deviceId,
serviceId: list[num].uuid,
success: function (res) {
console.log(res)
for (let i = 0; i < res.characteristics.length; ++i) {
let properties = res.characteristics[i].properties;
let item = res.characteristics[i].uuid;
if (!notify) {
if (properties.notify) {
app.BLEInformation.notifyCharaterId = item
app.BLEInformation.notifyServiceId = list[num].uuid;
const bleNotifyInfo = {
notifyCharaterId: item,
notifyServiceId: list[num].uuid
}
wx.setStorageSync('bleNotifyInfo', bleNotifyInfo);
notify = true
}
}
if (!write) {
if (properties.write) {
app.BLEInformation.writeCharaterId = item;
app.BLEInformation.writeServiceId = list[num].uuid;
const bleWriteInfo = {
writeCharaterId: item,
writeServiceId: list[num].uuid
}
wx.setStorageSync('bleWriteInfo', bleWriteInfo);
write = true;
}
}
if (!read) {
if (properties.read) {
app.BLEInformation.readCharaterId = item;
app.BLEInformation.readServiceId = list[num].uuid;
read = true
}
}
}
if (!write || !notify || !read) {
num++
that.setData({
writeCharacter: write,
readCharacter: read,
notifyCharacter: notify,
serviceId: num
})
if(num == list.length){
wx.showModal({
title: '提示',
content: '找不到该读写的特征值',
})
}else{
that.getCharacteristics()
}
} else {
that.openControl()
}
}, fail: function (e) {
console.log(e)
}, complete: function (e) {
console.log('write:'+app.BLEInformation.writeCharaterId)
console.log('read:'+app.BLEInformation.readCharaterId)
console.log('notify:'+app.BLEInformation.notifyCharaterId)
}
})
},
openControl: function () {
wx.showToast({
title: '连接成功',
icon: 'success',
duration: 2000
})
wx.navigateBack({
delta: 1
})
},
createBLEConnectionWithDeviceId(e) {
// 小程序在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备
const device = this.data.lastDevice;
if (!device) { return }
const deviceId = device.deviceId;
console.log('createBLEConnectionWithDeviceId', deviceId)
wx.openBluetoothAdapter({
success: (res) => {
console.log('openBluetoothAdapter success', res)
this._createBLEConnection(deviceId, device)
},
fail: (res) => {
console.log('openBluetoothAdapter fail', res)
if (res.errCode === 10001) {
wx.showModal({
title: '错误',
content: '未找到蓝牙设备, 请打开蓝牙后重试。',
showCancel: false
})
wx.onBluetoothAdapterStateChange((res) => {
console.log('onBluetoothAdapterStateChange', res)
if (res.available) {
// 取消监听
wx.onBluetoothAdapterStateChange(() => {
});
this._createBLEConnection(deviceId, device)
}
})
}
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
app.BLEInformation.platform = app.getPlatform();
wx.setStorageSync('platform', app.getPlatform());
const lastDevice = wx.getStorageSync('bleItem');
this.setData({
lastDevice: lastDevice
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
let that = this
wx.startPullDownRefresh({})
that.startSearch()
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
效果图
2、打印功能(单独写在了mixins里)
send-command.js
/**
* 此Demo仅供参考,可打印数字,英文,符号,中文,条形码
* 小程序支持的蓝牙为低功耗蓝牙(BLE),数据量大需分包发送
*/
const app = getApp();
export default {
data: {
looptime: 0,
currentTime: 1,
lastData: 0,
buffSize: [],
buffIndex: 0,
printNum: [],
printNumIndex: 0,
printerNum: 1,
currentPrint: 1,
isReceiptSend: false,
isLabelSend: false,
canvasWidth: 180,
canvasHeight: 180,
imageSrc: '../../../images/mine/user-free.png',
isBleConnect: false // 是否已连接蓝牙设备
},
//准备发送,根据每次发送字节数来处理分包数量
prepareSend: function(buff) {
console.log(buff)
let that = this;
let time = that.data.oneTimeData;
let looptime = parseInt(buff.length / time);
let lastData = parseInt(buff.length % time);
console.log(looptime + '---' + lastData)
that.setData({
looptime: looptime + 1,
lastData: lastData,
currentTime: 1,
})
that.Send(buff)
},
//分包发送
Send: function(buff) {
let that = this;
let currentTime = that.data.currentTime;
let loopTime = that.data.looptime;
let lastData = that.data.lastData;
let onTimeData = that.data.oneTimeData;
let printNum = that.data.printerNum;
let currentPrint = that.data.currentPrint;
let buf;
let dataView;
if (currentTime < loopTime) {
buf = new ArrayBuffer(onTimeData)
dataView = new DataView(buf)
for (let i = 0; i < onTimeData; ++i) {
dataView.setUint8(i, buff[(currentTime - 1) * onTimeData + i])
}
} else {
buf = new ArrayBuffer(lastData)
dataView = new DataView(buf)
for (let i = 0; i < lastData; ++i) {
dataView.setUint8(i, buff[(currentTime - 1) * onTimeData + i])
}
}
const bleWriteInfo = wx.getStorageSync('bleWriteInfo');
console.log(bleWriteInfo,'bleWriteInfo=====')
wx.writeBLECharacteristicValue({
deviceId: this.data.bleInfo.deviceId,
serviceId: bleWriteInfo.writeServiceId,
characteristicId: bleWriteInfo.writeCharaterId,
value: buf,
success: function(res) {
console.log(res)
},
fail: function(e) {
console.log(e)
},
complete: function() {
currentTime++
if (currentTime <= loopTime) {
that.setData({
currentTime: currentTime
})
that.Send(buff)
} else {
wx.showToast({
title: '已打印第' + currentPrint + '张',
})
if (currentPrint == printNum) {
that.setData({
looptime: 0,
lastData: 0,
currentTime: 1,
isReceiptSend: false,
isLabelSend: false,
currentPrint: 1
})
} else {
currentPrint++
that.setData({
currentPrint: currentPrint,
currentTime: 1,
})
that.Send(buff)
}
}
}
})
},
// 启用蓝牙低功耗设备特征值变化时的 notify 功能,订阅特征
enableBle(deviceId){
const bleNotifyInfo = wx.getStorageSync('bleNotifyInfo');
wx.notifyBLECharacteristicValueChange({
deviceId: deviceId,
serviceId: bleNotifyInfo.notifyServiceId,
characteristicId: bleNotifyInfo.notifyCharaterId,
state: true,
success: function(res) {
wx.onBLECharacteristicValueChange(function(r) {
console.log(`characteristic ${r.characteristicId} has changed, now is ${r}`)
})
},
fail: function(e) {
console.log(e)
},
complete: function(e) {
console.log(e)
}
})
},
drawCanvas(){
let that = this;
let width;
let height;
wx.getImageInfo({
src: that.data.imageSrc,
success(res) {
width = res.width
height = res.height
that.setData({
canvasWidth: res.width,
canvasHeight: res.height
})
}
})
const ctx = wx.createCanvasContext('edit_area_canvas', this);
ctx.drawImage(this.data.imageSrc, 0, 0, width, height);
ctx.draw();
},
// 创建连接
_createBLEConnection(deviceId,item){
const that = this;
wx.createBLEConnection({
deviceId: deviceId,
success: function (res) {
console.log(res)
wx.setStorageSync('bleItem', item);
// that.getSeviceId(deviceId)
}, fail: function (e) {
console.log('createBLEConnection fail', res)
}, complete: function (e) {
wx.hideLoading()
}
})
},
// 创建蓝牙连接
// 小程序在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备
createBLEConnectionWithDeviceId() {
const device = this.data.bleInfo;
if (!device) { return; }
const deviceId = device.deviceId;
console.log('createBLEConnectionWithDeviceId', deviceId)
wx.openBluetoothAdapter({
success: (res) => {
console.log('openBluetoothAdapter success', res)
this._createBLEConnection(deviceId, device)
},
fail: (res) => {
console.log('openBluetoothAdapter fail', res)
if (res.errCode === 10001) {
wx.showModal({
title: '错误',
content: '未找到蓝牙设备, 请打开蓝牙后重试。',
showCancel: false
})
wx.onBluetoothAdapterStateChange((res) => {
console.log('onBluetoothAdapterStateChange', res)
// 蓝牙适配器是否可用
if (res.available) {
// 取消监听,否则stopBluetoothDevicesDiscovery后仍会继续触发onBluetoothAdapterStateChange,
// 导致再次调用startBluetoothDevicesDiscovery
wx.onBluetoothAdapterStateChange(() => {});
this._createBLEConnection(deviceId, device)
}
})
}
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function () {
this.enableBle()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function() {
let list = [];
let numList = [];
let j = 0;
for (let i = 20; i < 200; i += 10) {
list[j] = i;
j++
}
for (let i = 1; i < 10; i++) {
numList[i - 1] = i
}
this.setData({
buffSize: list,
oneTimeData: list[0],
printNum: numList,
printerNum: numList[0]
})
},
onShow() {
this.drawCanvas();
// 获取已经连接过得蓝牙设备
const bleInfo = wx.getStorageSync('bleItem');
this.setData({
bleInfo: bleInfo ? bleInfo : {}
})
// 如果已经有连接的蓝牙设备,直接连接
if(Object.keys(this.data.bleInfo).length !== 0){
this.setData({
isBleConnect: true
})
this.createBLEConnectionWithDeviceId()
// this.enableBle(this.data.bleInfo.deviceId);
}
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function() {
// 断开与蓝牙低功耗设备的连接
wx.closeBLEConnection({
deviceId: this.data.bleInfo.deviceId,
success: function(res) {
console.log("关闭蓝牙成功")
},
})
}
}
3、业务中打印逻辑
wxml
<van-button wx:if="{{detailBase.state <= 3}}" color="#0A7DFE" loading="{{btnLoading}}" block round bind:tap="labelPrint">打印</van-button>
js
import sendCommand from '@/mixins/modules/send-command.js';
let tsc = require('../../../utils/tsc.js');
Page({
mixins: [sendCommand],
// 标签打印
labelPrint(){
// 如果未连接打印机,跳转到连接打印机页面
if(Object.keys(this.data.bleInfo).length === 0){
wx.navigateTo({
url: '/pages/tabbar-pages/mine/bleConnect/bleConnect'
})
return;
}
let that = this;
let canvasWidth = that.data.canvasWidth;
let canvasHeight = that.data.canvasHeight;
let command = tsc.jpPrinter.createNew();
command.setSize(65, 48);
command.setGap(0);
command.setCls();
command.setText(220, 10, 'TSS24.BF2', 1, 1, '暂存单');
command.setBarCode(95, 50, '128', 65, 1, 2, 2, `${that.data.detailBase.id}`);
command.setText(190, 120, 'TSS24.BF2', 1, 1, `${that.data.detailBase.id}`);
command.setText(30, 160, 'TSS24.BF2', 1, 1, `姓名:${that.data.detailBase.name}`);
command.setText(240, 160, 'TSS24.BF2', 1, 1, `手机号:${that.data.detailBase.mobile}`);
that.data.goodsInfo.forEach((item,index)=>{
if(index < 3){
command.setText(30, 200 + index * 40, 'TSS24.BF2', 1, 1, `物品${index+1}:${item.goodsName}/${item.goodsAmount}/${item.goodsStatus}`);
}
})
// 获取 canvas 区域隐含的像素数据。
wx.canvasGetImageData({
canvasId: 'edit_area_canvas',
x: 0,
y: 0,
width: canvasWidth,
height: canvasHeight,
success: function(res) {
command.setBitmap(60, 0, 1, res)
},
complete: function() {
command.setPagePrint()
that.setData({ isLabelSend: true })
that.prepareSend(command.getData())
}
})
setTimeout(()=>{
that.onPrint()
},500)
}
})
打印需要的插件
encoding.js和encoding-indexes.js 下载地址text-encoding - npmPolyfill for the Encoding Living Standard's API.. Latest version: 0.7.0, last published: 6 years ago. Start using text-encoding in your project by running `npm i text-encoding`. There are 764 other projects in the npm registry using text-encoding.https://www.npmjs.com/package/text-encoding?activeTab=code
tsc.js 见下篇