微信小程序-蓝牙打印机demo
对于蓝牙有写入数据的话,需要时低功耗的蓝牙。向低功耗蓝牙设备特征值中写入二进制数据。注意:必须设备的特征值支持 write 才可以成功调用。
https://developers.weixin.qq.com/miniprogram/dev/api/device/bluetooth-ble/wx.writeBLECharacteristicValue.html
先搜索蓝牙设备
wxml
<button class="btn" type="primary" bindtap="startSearch" loading='{{isScanning}}'> 开始搜索 </button>
<view wx:for="{{list}}" wx:for-item="item"
data-title="{{item.deviceId}}"
data-name="{{item.name}}"
data-advertisData="{{item.advertisServiceUUIDs}}"
wx:key="{{item.deviceId}}"
bindtap="bindViewTap">
<view class="item">
<div class="deviceId block">{{item.deviceId}}</div>
<div class="name block">{{item.name}}</div>
</view>
</view>
js
app.BLEInformation.platform = getApp().getPlatform()
data: {
list: [],
services: [],
serviceId: 0,
writeCharacter: false,
readCharacter: false,
notifyCharacter: false,
isScanning:false
},
startSearch: function () {
var that = this
wx.openBluetoothAdapter({
success: function (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以上需授权地理位置权限
var that = this
var 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()
}
}
})
}
}
},
getBluetoothDevices: function () { //获取蓝牙设备信息
var that = this
console.log("start search")
wx.showLoading({
title: '正在加载',
})
that.setData({
isScanning:true
})
wx.startBluetoothDevicesDiscovery({
success: function (res) {
console.log(res)
setTimeout(function () {
wx.getBluetoothDevices({
success: function (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.setData({
list: devices,
isScanning:false
})
wx.hideLoading()
wx.stopPullDownRefresh()
},
})
}, 3000)
},
})
},
bindViewTap: function (e) {
var that = this
wx.stopBluetoothDevicesDiscovery({
success: function (res) { console.log(res) },
})
that.setData({
serviceId: 0,
writeCharacter: false,
readCharacter: false,
notifyCharacter: false
})
console.log(e.currentTarget.dataset.title)
wx.showLoading({
title: '正在连接',
})
wx.createBLEConnection({
deviceId: e.currentTarget.dataset.title,
success: function (res) {
console.log(res)
app.BLEInformation.deviceId = e.currentTarget.dataset.title
that.getSeviceId()
}, fail: function (e) {
wx.showModal({
title: '提示',
content: '连接失败',
})
console.log(e)
wx.hideLoading()
}, complete: function (e) {
console.log(e)
}
})
},
getSeviceId: function () {
var that = this
var platform = app.BLEInformation.platform
console.log(app.BLEInformation.deviceId)
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 () {
var that = this
var list = that.data.services
var num = that.data.serviceId
var write = that.data.writeCharacter
var read = that.data.readCharacter
var notify = that.data.notifyCharacter
wx.getBLEDeviceCharacteristics({
deviceId: app.BLEInformation.deviceId,
serviceId: list[num].uuid,
success: function (res) {
console.log(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) {
app.BLEInformation.notifyCharaterId = item
app.BLEInformation.notifyServiceId = list[num].uuid
notify = true
}
}
if (!write) {
if (properties.write) {
app.BLEInformation.writeCharaterId = item
app.BLEInformation.writeServiceId = list[num].uuid
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.navigateTo({
url: '../startPrint/startPrint',
})
},
然后打印
下面就是startPrint的代码
wxml
<view class="body">
<textarea class="input" bindinput="inputEvent" />
<button type="primary" bindtap="sendData">发送(票据可使用)</button>
<button type='primary' bindtap='labelTest' loading='{{isLabelSend}}' disabled='{{isLabelSend}}'>标签测试</button>
</view>
下面是 js 的代码,首先是设置变量
data: {
sendContent: "",
looptime: 0,
currentTime: 1,
lastData: 0,
oneTimeData: 0,
returnResult: "returnResult",
canvasWidth: 80,
canvasHeight: 80,
buffSize: [],
buffIndex: 0,
printNum: [],
printNumIndex: 0,
printerNum: 1,
currentPrint: 1,
isReceiptSend: false,
isLabelSend: false
},
command.setCls() ,需要设置这个,不然内容和上一次重复
onLoad: function(options) {
var that = this;
wx.notifyBLECharacteristicValueChange({
deviceId: app.BLEInformation.deviceId,
serviceId: app.BLEInformation.notifyServiceId,
characteristicId: app.BLEInformation.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('fail', e)
},
complete: function(e) {
console.log('complete', e)
}
})
},
inputEvent: function(e) {
this.setData({
sendContent: e.detail.value
})
console.log('sendContent: ', this.sendContent)
},
sendData: function() {
var data = this.data.sendContent + "\n"
var that = this;
var command = tsc.jpPrinter.createNew()
command.setGap(0)
command.setCls()
command.setText(60, 90, "TSS24.BF2", 1, 1, data)
command.setPagePrint()
that.prepareSend(command.getData())
},
labelTest: function() {
var that = this;
var canvasWidth = that.data.canvasWidth
var canvasHeight = that.data.canvasHeight
var command = tsc.jpPrinter.createNew()
command.setSize(48, 40)
command.setGap(0)
command.setCls() //需要设置这个,不然内容和上一次重复
command.setQR(1, 120, "L", 5, "A", "airenao.com")
command.setText(60, 90, "TSS24.BF2", 1, 1, "成都爱热闹")
command.setText(170, 50, "TSS24.BF2", 1, 1, "小程序测试")
command.setText(170, 90, "TSS24.BF2", 1, 1, "测试数字12345678")
command.setText(170, 120, "TSS24.BF2", 1, 1, "测试英文abcdefg")
command.setText(170, 150, "TSS24.BF2", 1, 1, "测试符号/*-+!@#$")
wx.canvasGetImageData({
canvasId: 'edit_area_canvas',
x: 0,
y: 0,
width: canvasWidth,
height: canvasHeight,
success: function(res) {
command.setBitmap(60, 0, 0, res)
},
complete: function() {
command.setPagePrint()
that.setData({
isLabelSend: true
})
that.prepareSend(command.getData())
}
})
},
准备发送内容, printNum 这个是需要打印多少份,buff 是每次打印多少字节数
prepareSend: function(buff) {
console.log('buff', buff)
var that = this
var time = that.data.oneTimeData
var looptime = parseInt(buff.length / time);
var lastData = parseInt(buff.length % time);
console.log(looptime + "---" + lastData)
that.setData({
looptime: looptime + 1,
lastData: lastData,
currentTime: 1,
})
that.Send(buff)
},
queryStatus: function() { //查询打印机状态
var command = esc.jpPrinter.Query();
command.getRealtimeStatusTransmission(1);
this.setData({
returnResult: "查询成功"
})
},
Send: function(buff) { //分包发送
var that = this
var currentTime = that.data.currentTime
var loopTime = that.data.looptime
var lastData = that.data.lastData
var onTimeData = that.data.oneTimeData
var printNum = that.data.printerNum //打印多少份
var currentPrint = that.data.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)
wx.writeBLECharacteristicValue({
deviceId: app.BLEInformation.deviceId,
serviceId: app.BLEInformation.writeServiceId,
characteristicId: app.BLEInformation.writeCharaterId,
value: buf,
success: function(res) {
console.log('写入成功', res)
},
fail: function(e) {
console.fail('写入失败', 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,
})
console.log("开始打印")
that.Send(buff)
}
}
}
})
},
最后的成品样子
作者:叉叉敌
博客:https://chasays.github.io/
微信公众号:Chasays, 欢迎关注一起吹牛逼,也可以加个人微信号「xxd_0225」互吹。
本博客大多为学习笔记或读书笔记,本文如对您有帮助,还请多推荐下此文,如有错误欢迎指正,相互学习,共同进步。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了