This commit is contained in:
2026-06-02 15:28:25 +08:00
commit b271b84f70
249 changed files with 42240 additions and 0 deletions
+339
View File
@@ -0,0 +1,339 @@
<template>
<view class="container">
<view class="status-bar">
<text>打印机: {{ printerConnected ? '已连接' : '未连接' }}</text>
<text v-if="lastPrinterMac && !printerConnected">上次设备: {{ lastPrinterMac }}</text>
</view>
<view class="status-bar">
<text>电子秤: {{ scaleConnected ? '已连接' : '未连接' }}</text>
<text>重量: {{ weightValue }} g</text>
</view>
<button type="primary" @click="initAndAutoConnect">启动蓝牙并自动连接</button>
<button @click="manualScanPrinter">手动扫描打印机</button>
<button @click="manualScanScale">手动扫描电子秤</button>
<button @click="printTest">打印测试</button>
<button @click="disconnectAll">断开所有连接</button>
</view>
</template>
<script>
import bluetoothManager from '@/utils/BluetoothManager.js';
export default {
data() {
return {
// 打印机相关
printerDeviceId: null,
printerConnected: false,
lastPrinterMac: '',
// 电子秤相关
scaleDeviceId: null,
scaleConnected: false,
weightValue: '--',
// UUID 配置(请替换为实际值)
printerServiceUUID: '0000EEE2-0000-1000-8000-00805F9B34FB',
printerWriteUUID: '0000EEE3-0000-1000-8000-00805F9B34FB',
scaleServiceUUID: 'FFF0',
scaleNotifyUUID: 'FFF1',
};
},
onLoad() {
const config = uni.getStorageSync('bleDeviceConfig');
if (config && config.deviceId) {
this.printerServiceUUID = config.serviceId;
this.printerWriteUUID = config.writeCharId;
this.lastPrinterMac = config.deviceId;
// 如果配置了 notify UUID,也可用于电子秤等
this.initAndAutoConnect();
} else {
// 没有配置,引导用户去配置页面
uni.showModal({
title: '未配置设备',
content: '请先配置蓝牙设备',
success: () => {
uni.navigateTo({ url: '/pages/testpages/bleconfig' });
},
});
}
},
onUnload() {
// 页面卸载时释放所有连接(可选,也可保持连接)
bluetoothManager.closeAll();
},
methods: {
/**
* 初始化蓝牙并自动连接上次的打印机
*/
async initAndAutoConnect() {
try {
await bluetoothManager.init();
console.log('蓝牙初始化成功');
// 设置全局回调
bluetoothManager.setConnectionChangeCallback(this.onConnectionChange);
bluetoothManager.setDataReceivedCallback(this.onDataReceived);
if (this.lastPrinterMac) {
uni.showLoading({ title: '正在连接上次打印机...' });
try {
const info = await bluetoothManager.connectKnownDevice(
this.lastPrinterMac,
this.printerServiceUUID,
this.printerWriteUUID
);
this.printerDeviceId = this.lastPrinterMac;
this.printerConnected = true;
uni.hideLoading();
uni.showToast({ title: '打印机已自动连接', icon: 'success' });
} catch (err) {
uni.hideLoading();
console.error('自动连接失败', err);
uni.showModal({
title: '连接失败',
content: `上次使用的打印机 (${this.lastPrinterMac}) 未找到,是否重新扫描?`,
success: (res) => {
if (res.confirm) this.manualScanPrinter();
},
});
}
}
} catch (err) {
console.error('蓝牙初始化失败', err);
uni.showToast({ title: '请打开蓝牙并授权', icon: 'none' });
}
},
/**
* 手动扫描打印机(用于首次或自动连接失败后的补救)
*/
async manualScanPrinter() {
try {
await bluetoothManager.init();
bluetoothManager.setDeviceFoundCallback(this.onPrinterFound);
await bluetoothManager.stopScan();
await bluetoothManager.startScan([this.printerServiceUUID]);
uni.showToast({ title: '扫描打印机中...', icon: 'none' });
// 20秒后自动停止扫描
setTimeout(() => {
bluetoothManager.stopScan();
}, 20000);
} catch (err) {
console.error('扫描启动失败', err);
}
},
/**
* 手动扫描电子秤
*/
async manualScanScale() {
try {
await bluetoothManager.init();
bluetoothManager.setDeviceFoundCallback(this.onScaleFound);
await bluetoothManager.stopScan();
await bluetoothManager.startScan([this.scaleServiceUUID]);
uni.showToast({ title: '扫描电子秤中...', icon: 'none' });
setTimeout(() => {
bluetoothManager.stopScan();
}, 20000);
} catch (err) {
console.error('扫描电子秤失败', err);
}
},
/**
* 打印机发现回调
*/
onPrinterFound(device) {
const name = device.name || '';
// 根据名称过滤器(可修改为你的打印机名称关键字)
if (name.includes('QR380A-15E0_Ble')) {
bluetoothManager.stopScan(); // 发现后停止扫描
uni.showModal({
title: '发现打印机',
content: `设备: ${name}\nMAC: ${device.deviceId}\n是否连接?`,
success: (res) => {
if (res.confirm) {
this.connectAndSavePrinter(device.deviceId, name);
} else {
// 用户取消,可以继续扫描(可选)
this.manualScanPrinter();
}
},
});
}
},
/**
* 电子秤发现回调
*/
onScaleFound(device) {
const name = device.name || '';
if (name.includes('Scale') || name.includes('Weight')) {
bluetoothManager.stopScan();
uni.showModal({
title: '发现电子秤',
content: `设备: ${name}\nMAC: ${device.deviceId}\n是否连接?`,
success: (res) => {
if (res.confirm) {
this.connectScale(device.deviceId);
}
},
});
}
},
/**
* 连接打印机并保存 MAC
*/
async connectAndSavePrinter(deviceId, deviceName) {
try {
uni.showLoading({ title: '连接打印机中...' });
const info = await bluetoothManager.connectKnownDevice(
deviceId,
this.printerServiceUUID,
this.printerWriteUUID
);
this.printerDeviceId = deviceId;
this.printerConnected = true;
// 保存 MAC
uni.setStorageSync('savedPrinterMac', deviceId);
this.lastPrinterMac = deviceId;
uni.hideLoading();
uni.showToast({ title: `打印机 ${deviceName} 已连接`, icon: 'success' });
} catch (err) {
uni.hideLoading();
console.error('连接打印机失败', err);
uni.showToast({ title: '连接失败', icon: 'none' });
}
},
/**
* 连接电子秤(不需要保存,按需连接)
*/
async connectScale(deviceId) {
try {
uni.showLoading({ title: '连接电子秤...' });
const info = await bluetoothManager.connectKnownDevice(
deviceId,
this.scaleServiceUUID,
null, // 写入特征值可选
this.scaleNotifyUUID
);
this.scaleDeviceId = deviceId;
this.scaleConnected = true;
uni.hideLoading();
uni.showToast({ title: '电子秤已连接', icon: 'success' });
} catch (err) {
uni.hideLoading();
console.error('连接电子秤失败', err);
uni.showToast({ title: '连接失败', icon: 'none' });
}
},
/**
* 全局连接状态变化回调
*/
onConnectionChange(deviceId, connected) {
if (deviceId === this.printerDeviceId) {
this.printerConnected = connected;
if (!connected) {
uni.showToast({ title: '打印机断开', icon: 'none' });
// 可选:自动重连(这里不做,避免频繁请求)
}
}
if (deviceId === this.scaleDeviceId) {
this.scaleConnected = connected;
if (!connected) {
uni.showToast({ title: '电子秤断开', icon: 'none' });
}
}
},
/**
* 全局数据接收回调(接收电子秤重量数据)
*/
onDataReceived(deviceId, value) {
if (deviceId === this.scaleDeviceId) {
// 将 ArrayBuffer 转为字符串(根据电子秤协议解析)
const data = this.ab2str(value);
console.log('电子秤原始数据:', data);
// 示例:假设秤返回 "1234g" 或 "12.34kg"
const weight = this.parseWeight(data);
if (weight !== null) {
this.weightValue = weight;
}
}
},
/**
* 打印测试
*/
async printTest() {
if (!this.printerConnected) {
uni.showToast({ title: '打印机未连接', icon: 'none' });
return;
}
try {
// 示例:发送纯文本(实际需组装打印机指令,如 ESC/POS 或 CPCL
const text = '测试打印\n自动连接成功\n时间: ' + new Date().toLocaleString() + '\n\n';
const buffer = this.str2ab(text);
await bluetoothManager.writeData(this.printerDeviceId, buffer);
uni.showToast({ title: '打印指令已发送', icon: 'success' });
} catch (err) {
console.error('打印失败', err);
uni.showToast({ title: '打印失败', icon: 'none' });
}
},
/**
* 断开所有连接
*/
async disconnectAll() {
await bluetoothManager.closeAll();
this.printerDeviceId = null;
this.printerConnected = false;
this.scaleDeviceId = null;
this.scaleConnected = false;
this.weightValue = '--';
uni.showToast({ title: '已断开所有连接', icon: 'success' });
},
// ---------- 辅助函数 ----------
str2ab(str) {
const buf = new ArrayBuffer(str.length);
const view = new Uint8Array(buf);
for (let i = 0; i < str.length; i++) {
view[i] = str.charCodeAt(i);
}
return buf;
},
ab2str(buffer) {
return String.fromCharCode.apply(null, new Uint8Array(buffer));
},
parseWeight(dataStr) {
// 修改为你的电子秤实际解析规则
const match = dataStr.match(/(\d+(?:\.\d+)?)/);
return match ? match[1] : null;
},
},
};
</script>
<style>
.container {
padding: 20px;
display: flex;
flex-direction: column;
gap: 15px;
}
.status-bar {
background: #f5f5f5;
padding: 10px;
border-radius: 8px;
margin-bottom: 10px;
}
button {
margin: 5px 0;
}
</style>