0602
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user