2024-09-12 01:32:00 by wst
小程序uniapp为我们提供了一套统一的接口让我们连接蓝牙打印机。
目前的开发场景:手机连接蓝牙打印机,然后把结账小票打出来。
系统:deepin(Linux)
工具:uniapp
IDE:VSCode
语言:Vue3
src
├── App.vue
├── components
│ └── zwy-popup
│ └── zwy-popup.vue
├── config.js
├── main.js
├── manifest.json
├── pages
│ ├── data
│ │ ├── data.vue
│ │ └── order.vue
│ ├── login
│ │ └── login.vue
│ ├── mall
│ │ ├── mall.vue
│ │ ├── order_food.vue
│ │ └── pay_bill.vue
│ ├── manage
│ │ ├── dish-class.vue
│ │ ├── dish-clear.vue
│ │ ├── dish-combo.vue
│ │ ├── dish-list.vue
│ │ ├── manage.vue
│ │ └── table-list.vue
│ ├── protocol
│ │ └── protocol.vue
│ ├── receipt
│ │ ├── printpage.vue
│ │ └── receipt.vue
│ └── register
│ ├── changepwd.vue
│ └── register.vue
├── pages.json
├── shime-uni.d.ts
├── static
│ ├── libs
│ │ ├── BluetoothTool.js
│ │ ├── encoding-indexes.js
│ │ ├── encoding.js
│ │ ├── esc.js
│ │ ├── myprinter.js
│ │ └── tsc.js
│ ├── logo.png
│ └── tabbar
│ ├── data-color.png
│ ├── data.png
│ ├── mall-color.png
│ ├── mall.png
│ ├── mg-color.png
│ └── mg.png
├── styles
│ └── manage.scss
├── uni.scss
└── utils
├── date.js
├── login.js
└── print.js
大家主要关注调用文件printpage.vue和库static/libs下的文件。
printpage.vue
<template>
<view>
<scroll-view
scroll-y
class="box"
>
<view class="item" v-for="item in blueDeviceList" @click="connect(item)">
<view>
<text>id: {{ item.deviceId }}</text>
</view>
<view>
<text style="color: darkslateblue;font-weight: 700;">name: {{ item.name }}</text>
</view>
</view>
</scroll-view>
<button @click="initBlue">1 初始化蓝牙</button>
<button @click="discovery">2 搜索附近蓝牙设备</button>
<button @click="getServices">3 获取蓝牙服务</button>
<button @click="sendData">4 打印测试数据</button>
<button @click="destroyed" type="warn" plain> 断开蓝牙</button>
<button @click="return_my" type="primary">返回</button>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { print_content } from '@/static/libs/myprinter.js'
import { BASE_URL } from '../../config';
import { senBlData,check_print } from '../../utils/print';
// 搜索到的蓝牙设备列表
const blueDeviceList = ref([])
// 蓝牙设备的id
const deviceId = ref('')
// 蓝牙设备的服务列表
const myServices = ref([])
// 打印内容
var ticket = ref("");
// 【4】获取数据
function getData(){
uni.request({
url:BASE_URL+'/admin/data/print/test',
data:{},
success:(success)=>{
console.log("res:", success.data)
ticket.value = success.data.data.content
},
})
}
// 【1】初始化蓝牙
function initBlue() {
uni.openBluetoothAdapter({
success(res) {
console.log('初始化蓝牙成功')
console.log(res)
uni.showToast({
title: '初始化蓝牙成功',
icon: 'none'
})
},
fail(err) {
console.log('初始化蓝牙失败')
console.error(err)
}
})
}
function destroyed() {
console.log("destroyed----------")
console.log("deviceId:", deviceId.value)
if(deviceId.value == ''){
deviceId.value = uni.getStorageSync('deviceId')
}
if (deviceId.value != '') {
uni.closeBLEConnection({
deviceId: deviceId.value,
success(res) {
console.log(res)
uni.showToast({
title: '蓝牙已断开',
icon: 'none'
})
}
})
}
}
/**返回我的页面 */
function return_my(){
var url = '/pages/my/my';
var current = uni.getStorageSync('current') || ''
console.log("current:", current)
if(current){
uni.navigateTo({
url: current,
})
} else {
uni.switchTab({
url:url,
})
}
}
// 【2】开始搜寻附近设备
function discovery() {
uni.startBluetoothDevicesDiscovery({
success(res) {
console.log('开始搜索')
uni.showToast({
title: '搜索中。。。\n请在列表中选择您的设备',
icon: 'none',
duration: 3000
})
// 开启监听回调
uni.onBluetoothDeviceFound(found)
},
fail(err) {
console.log('搜索失败')
console.error(err)
}
})
}
// 【3】找到新设备就触发该方法
function found(res) {
console.log(res)
blueDeviceList.value.push(res.devices[0])
}
// 【4】连接设备
function connect(data) {
console.log(data)
deviceId.value = data.deviceId // 将获取到的设备ID存起来
uni.setStorageSync('deviceId', data.deviceId)
uni.createBLEConnection({
deviceId: deviceId.value,
success(res) {
console.log('连接成功')
console.log(res)
// 停止搜索
stopDiscovery()
uni.showToast({
title: '连接成功'
})
},
fail(err) {
console.log('连接失败')
console.error(err)
uni.showToast({
title: '连接成功',
icon: 'error'
})
}
})
}
// 【5】停止搜索
function stopDiscovery() {
uni.stopBluetoothDevicesDiscovery({
success(res) {
console.log('停止成功')
console.log(res)
},
fail(err) {
console.log('停止失败')
console.error(err)
}
})
}
// 【3】获取服务
function getServices() {
// 如果是自动链接的话,uni.getBLEDeviceServices方法建议使用setTimeout延迟1秒后再执行
uni.getBLEDeviceServices({
deviceId: deviceId.value,
success(res) {
console.log(res) // 可以在res里判断有没有硬件佬给你的服务
uni.showToast({
title: '获取服务成功'
})
},
fail(err) {
console.error(err)
uni.showToast({
title: '获取服务失败',
icon: 'error'
})
},
complete(res) {
console.log("当前蓝牙设备的服务:", res)
for (var s = 0; s < res.services.length; s++) {
console.log("服务" + s + ":", res.services[s].uuid)
let serviceId = res.services[s].uuid
uni.getBLEDeviceCharacteristics({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId: deviceId.value,
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
serviceId: serviceId,
success(res) {
var re = JSON.parse(JSON.stringify(res))
console.log('遍历:deviceId = [' + deviceId.value + '] serviceId = [' + serviceId + ']')
for (var c = 0; c < re.characteristics.length; c++) {
if (re.characteristics[c].properties.write == true) {
let uuid = re.characteristics[c].uuid
console.log('可用: deviceId = [' + deviceId.value + '] serviceId = [' + serviceId + '] characteristics=[' +
uuid + "]")
myServices.value.push({
serviceId: serviceId,
characteristicId: uuid
})
console.log("处理后的服务列表:", JSON.stringify(myServices.value))
uni.setStorageSync("myServices", myServices.value)
}
}
}
})
}
}
})
}
// 【5】发送数据
function sendData(){
check_print()
var command = ""
command += "------内容开始------" + "\r\n";
command += 'hello' + "\r\n"; // 打印内容
command += "------内容结束------\r\n"
command += "\r\n\r\n" // 打印页低
// var new_content = ticket.value+"\r\n\r\n"
senBlData(deviceId.value, myServices.value[0].serviceId, myServices.value[0].characteristicId,print_content(command))
uni.showToast({
title: '发送成功',
icon: 'none'
})
}
// 硬件提供的服务id,开发中需要问硬件佬获取该id
const serviceId = ref('0000FFE0-0000-1000-8000-00805F9B34FB')
const characteristicId = ref('0000FFE1-0000-1000-8000-00805F9B34FB')
// 【8】开启消息监听
function notify() {
uni.notifyBLECharacteristicValueChange({
deviceId: deviceId.value, // 设备id
serviceId: myServices.value[0].serviceId, // 监听指定的服务
characteristicId: myServices.value[0].characteristicId, // 监听对应的特征值
state:true,
success(res) {
console.log(res)
listenValueChange()
uni.showToast({
title: '已开启监听'
})
},
fail(err) {
console.error(err)
uni.showToast({
title: '监听失败',
icon: 'error'
})
}
})
}
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('')
}
// 将16进制的内容转成我们看得懂的字符串内容
function hexCharCodeToStr(hexCharCodeStr) {
var trimedStr = hexCharCodeStr.trim();
var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
var len = rawStr.length;
if (len % 2 !== 0) {
alert("存在非法字符!");
return "";
}
var curCharCode;
var resultStr = [];
for (var i = 0; i < len; i = i + 2) {
curCharCode = parseInt(rawStr.substr(i, 2), 16);
resultStr.push(String.fromCharCode(curCharCode));
}
return resultStr.join("");
}
// 监听到的内容
const message = ref('')
const messageHex = ref('') // 十六进制
// 【9】监听消息变化
function listenValueChange() {
uni.onBLECharacteristicValueChange(res => {
console.log(res)
let resHex = ab2hex(res.value)
console.log(resHex)
messageHex.value = resHex
let result = hexCharCodeToStr(resHex)
console.log(String(result))
message.value = String(result)
})
}
// 【11】读取数据
function read() {
uni.readBLECharacteristicValue({
deviceId: deviceId.value,
serviceId: serviceId.value,
characteristicId: characteristicId.value,
success(res) {
console.log(res)
uni.showToast({
title: 'read指令发送成功'
})
},
fail(err) {
console.error(err)
uni.showToast({
title: 'read指令发送失败',
icon: 'error'
})
}
})
}
</script>
<style>
.box {
width: 98%;
height: 400rpx;
box-sizing: border-box;
margin: 0 auto 20rpx;
border: 2px solid dodgerblue;
}
.item {
box-sizing: border-box;
padding: 10rpx;
border-bottom: 1px solid #ccc;
}
button {
margin: 10rpx;
}
</style>
库文件static/libs太多了,大家可以关注这个公众号,回复uniapp-print获取。
以上就是怎么在手机端连接蓝牙打印机、打印小票的过程。对了,截图如下:
如有问题,欢迎留言!