first commit

This commit is contained in:
2025-04-15 01:51:54 +08:00
commit 40c821350f
47 changed files with 2816 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
<view>
<!-- 蓝牙启动关闭开关 = 初始化蓝牙 关闭本机蓝牙 开关 -->
<view class="page">
<view class="page-description">开关</view>
<view class="page-section">
<view class="page-section-demo switch-list">
<view class="switch-item">
<!-- checked:是否被选中初始状态默认开关 onChangechecked 改变时触发event.detail={value:checked}。 -->
<switch onChange="switchopenBluetoothAdapter" aria-label="{{switchopenBluetoothAdapter ? 'switch opened' : 'switch closed'}}" />
</view>
</view>
</view>
</view>
是否正在搜索设备{{discovering}}
蓝牙模块是否可用需支持 BLE 并且蓝牙是打开状态{{available}}
<!-- 开始搜索 停止搜索开关 开关 -->
<view class="page">
<view class="page-description">开关</view>
<view class="page-section">
<view class="page-section-demo switch-list">
<view class="switch-item">
<!-- checked:是否被选中初始状态默认开关 onChangechecked 改变时触发event.detail={value:checked}。 -->
<switch onChange="startBluetoothDevicesDiscovery" aria-label="{{startBluetoothDevicesDiscovery ? 'switch opened' : 'switch closed'}}" />
</view>
</view>
</view>
</view>
<view class="page">
<view class="page-description">图标</view>
<view class="page-section">
<view class="page-section-title">Type</view>
<view class="page-section-demo icon-list">
<block a:for="{{iconType}}">
<view class="item">
<icon type="{{item}}" aria-label="{{item}}" size="45" />
<text>{{item}}</text>
</view>
</block>
</view>
</view>
<view class="page">
<view class="page-description">单选框</view>
<view class="page-section">
<view class="section section_gap">
<form onSubmit="onSubmit" onReset="onReset">
<view class="page-section-demo">
<radio-group
class="radio-group"
onChange="radioChange"
name="lib"
>
<label a:for="{{devices}}" class="radio" key="label-{{index}}">
<radio
value="{{item.deviceId}}"
checked="{{item.checked}}"
disabled="{{item.disabled}}"
/>
<text class="radio-text">{{item.name}}</text>
</label>
</radio-group>
</view>
<view class="page-section-btns">
<view>
<button size="mini" type="ghost" formType="reset">待开发</button></view>
<view>
<button size="mini" type="primary" formType="submit">连接并打印</button></view>
</view>
</form>
</view>
</view>
</view>
指令集选择 下拉选择框
蓝牙选择框+选择+打印+清空查找更多蓝牙 devices 单选列表框
已经连接蓝牙名名称文本 文本 状态一行
获取蓝牙状态 有两个标识 打勾 状态一行
</view>

View File

@@ -0,0 +1,766 @@
Component({
mixins: [],
data: {
// 初始化蓝牙的开关状态false 表示关闭true 表示打开
switchswitchopenBluetoothAdapter: false,
// 搜索蓝牙设备的开关状态false 表示停止搜索true 表示开始搜索
switchstartBluetoothDevicesDiscovery: false,
// 蓝牙模块是否处于搜索状态,'' 表示初始值,后续会更新为 true 或 false
discovering: '',
// 蓝牙模块是否可用,'' 表示初始值,后续会更新为 true 或 false
available: '',
// 存储已发现的蓝牙设备列表
deviceslist: [],
// 选择的保持连接的蓝牙对象
devices: [],
devices: {},
selectedDevice: {},
// 存储设备名称,可根据需求调整
devicesName: [],
// 当前选中的蓝牙设备的 ID
deviceId: '',
// 只是查找某个蓝牙设备
services: '',
// 图标类型数组,这里只包含 'cancel',可根据需求添加其他图标类型
iconType: [
// 'success',
'cancel',
],
// 蓝牙连接状态
isConnected: false,
// 心跳定时器 ID
heartbeatTimer: null,
// 存储获取到的可写特征值列表
writableCharacteristics: [],
// 存储所有服务及其特征值
allServicesAndCharacteristics: {}
},
props: {},
didMount() {
// 获取本机蓝牙模块的状态
this.getBluetoothAdapterState();
// 监听新设备发现事件
this.listenDeviceFound();
// 监听蓝牙连接断开事件
this.listenBLEConnectionStateChanged();
},
didUpdate() {},
didUnmount() {
try {
// 取消监听新设备发现事件,避免内存泄漏
dd.offBluetoothDeviceFound(this.handleDeviceFound);
} catch (error) {
console.warn('取消监听新设备发现事件时出错:', error);
}
try {
// 关闭蓝牙连接
this.closeBluetoothConnection();
} catch (error) {
console.warn('关闭蓝牙连接时出错:', error);
}
try {
// 清除心跳定时器
if (this.data.heartbeatTimer) {
clearInterval(this.data.heartbeatTimer);
}
} catch (error) {
console.warn('清除心跳定时器时出错:', error);
}
try {
// 取消监听蓝牙连接状态变化事件
dd.offBLEConnectionStateChanged(this.handleBLEConnectionStateChanged);
} catch (error) {
console.warn('取消监听蓝牙连接状态变化事件时出错:', error);
}
},
methods: {
getBluetoothAdapterState() {
// 调用 dd.getBluetoothAdapterState 方法获取本机蓝牙模块的状态
dd.getBluetoothAdapterState({
success: (res) => {
console.log('本机蓝牙模块状态:', res);
// 更新组件数据,将蓝牙模块的搜索状态和可用性状态存储到 data 中
this.setData({
// res.discovering 为 true 表示蓝牙模块处于搜索状态false 表示不处于搜索状态
discovering: res.discovering,
// res.available 为 true 表示蓝牙模块可用false 表示不可用
available: res.available
});
},
fail: (res) => {
console.log('获取本机蓝牙模块状态失败,错误码:', res.errorCode);
if (res.errorCode === 10000) {
dd.showToast({
title: '请先打开蓝牙开关',
icon: 'none'
});
} else {
// dd.showToast({
// title: `获取本机蓝牙模块状态失败,错误码: ${res.errorCode}`,
// icon: 'none'
// });
}
},
complete: (res) => {
console.log('获取本机蓝牙模块状态调用结束', res);
}
});
},
switchopenBluetoothAdapter(e) {
console.log('switchopenBluetoothAdapter 发生 change 事件,携带值为', e.detail.value);
// 更新组件数据,将开关的新状态存储到 data 中
this.setData({
switchswitchopenBluetoothAdapter: e.detail.value,
});
if (e.detail.value) {
// 开关打开,初始化蓝牙模块
// 调用 dd.openBluetoothAdapter 方法初始化蓝牙模块
dd.openBluetoothAdapter({
// 自动关闭蓝牙适配器
autoClose: true,
success: (res) => {
console.log('蓝牙模块初始化成功,是否支持 BLE:', res.isSupportBLE);
dd.showToast({
title: '蓝牙模块初始化成功',
icon: 'success'
});
// 监听手机蓝牙状态的改变
dd.onBluetoothAdapterStateChange((res) => {
console.log('蓝牙适配器状态改变:', res);
});
},
fail: (res) => {
console.error('蓝牙模块初始化失败,错误码:', res.errorCode);
// const title = `蓝牙模块初始化失败,错误码: ${res.errorCode}`;
// if (title) {
// dd.showToast({
// title,
// icon: 'none'
// });
// }
// 根据不同的错误码给出相应的提示信息
switch (res.errorCode) {
case 12:
console.log('请尝试打开蓝牙。');
break;
case 13:
console.log('请尝试重新连接。');
break;
case 14:
console.log('请授权使用蓝牙功能。');
break;
case 15:
console.log('未知错误。');
break;
case 10000:
console.log('未初始化蓝牙适配器');
break;
default:
console.log('其他错误');
}
},
complete: (res) => {
console.log('蓝牙模块初始化调用结束', res);
}
});
} else {
// 开关关闭,关闭蓝牙模块
// 调用 dd.closeBluetoothAdapter 方法关闭蓝牙模块
dd.closeBluetoothAdapter({
success: () => {
console.log('蓝牙模块已关闭');
dd.showToast({
title: '蓝牙模块已关闭',
icon: 'success'
});
},
fail: (res) => {
console.error('关闭蓝牙模块失败,错误码:', res.errorCode);
// const title = `关闭蓝牙模块失败,错误码: ${res.errorCode}`;
// if (title) {
// dd.showToast({
// title,
// icon: 'none'
// });
// }
},
complete: () => {
console.log('关闭蓝牙模块调用结束');
}
});
}
},
startBluetoothDevicesDiscovery(e) {
console.log('startBluetoothDevicesDiscovery 发生 change 事件,携带值为', e.detail.value);
// 更新组件数据,将开关的新状态存储到 data 中
this.setData({
switchstartBluetoothDevicesDiscovery: e.detail.value,
});
if (e.detail.value) {
// 开关打开,开始搜索蓝牙设备
console.log('开始搜寻附近的蓝牙外围设备');
// 调用 dd.startBluetoothDevicesDiscovery 方法开始搜索蓝牙设备
dd.startBluetoothDevicesDiscovery({
// 搜索指定服务 UUID 的蓝牙设备
// services: ['fff0'],
success: (res) => {
console.log(res);
dd.showToast({
title: '开始搜索蓝牙设备',
icon: 'success'
});
// 开始搜索后获取已发现设备
this.getDiscoveredDevices();
},
fail: (res) => {
console.error('搜寻蓝牙设备失败,错误码:', res.errorCode);
// const title = `搜寻蓝牙设备失败,错误码: ${res.errorCode}`;
// if (title) {
// dd.showToast({
// title,
// icon: 'none'
// });
// }
},
complete: (res) => {
console.log('搜寻蓝牙设备调用结束', res);
}
});
} else {
// 开关关闭,停止搜索蓝牙设备
console.log('停止搜寻附近的蓝牙外围设备');
// 调用 dd.stopBluetoothDevicesDiscovery 方法停止搜索蓝牙设备
dd.stopBluetoothDevicesDiscovery({
success: (res) => {
console.log(res);
dd.showToast({
title: '停止搜索蓝牙设备',
icon: 'success'
});
},
fail: (res) => {
console.error('停止搜寻蓝牙设备失败,错误码:', res.errorCode);
// const title = `停止搜寻蓝牙设备失败,错误码: ${res.errorCode}`;
// if (title) {
// dd.showToast({
// title,
// icon: 'none'
// });
// }
},
complete: (res) => {
console.log('停止搜寻蓝牙设备调用结束', res);
}
});
}
},
getDiscoveredDevices() {
// 调用 dd.getBluetoothDevices 方法获取已发现的蓝牙设备列表
dd.getBluetoothDevices({
success: (res) => {
console.log('已发现的蓝牙设备:', res.devices);
// 更新组件数据,将已发现的设备列表和设备名称存储到 data 中
this.setData({
deviceslist: res.devices,
devicesName: res.devices.map(device => device.name),
devices: res.devices // 将完整的设备对象保存到 devices 数组中
});
// dd.showToast({
// title: '获取已发现蓝牙设备成功',
// icon: 'success'
// });
},
fail: (res) => {
console.error('获取已发现的蓝牙设备失败,错误码:', res.errorCode);
// const title = `获取已发现的蓝牙设备失败,错误码: ${res.errorCode}`;
// if (title) {
// dd.showToast({
// title,
// icon: 'none'
// });
// }
},
complete: (res) => {
console.log('获取已发现的蓝牙设备调用结束', res);
}
});
},
listenDeviceFound() {
// 绑定 handleDeviceFound 方法的上下文,确保在事件回调中 this 指向正确
this.handleDeviceFound = this.handleDeviceFound.bind(this);
// 调用 dd.onBluetoothDeviceFound 方法监听新设备发现事件
dd.onBluetoothDeviceFound(this.handleDeviceFound);
},
handleDeviceFound(res) {
// console.log('新发现的蓝牙设备:', res.devices);
// 获取当前已发现的设备列表
const currentDevices = this.data.devices;
// 过滤出新发现的设备,避免重复添加
const newDevices = res.devices.filter(device => {
return currentDevices.every(existingDevice => existingDevice.deviceId !== device.deviceId);
});
// 更新组件数据,将新发现的设备添加到已发现设备列表中
this.setData({
devices: [...currentDevices, ...newDevices],
devicesName: [...this.data.devicesName, ...newDevices.map(device => device.name)]
});
// const title = '发现新的蓝牙设备';
// if (title) {
// dd.showToast({
// title,
// icon: 'success'
// });
// }
},
radioChange(e) {
console.log('选择的蓝牙是', e.detail.value);
const deviceId = e.detail.value;
const devices = this.data.devices;
const selectedDevice = devices.find(device => device.deviceId === deviceId);
if (selectedDevice) {
this.setData({
deviceId,
selectedDevice: selectedDevice // 将选中的蓝牙设备对象保存到 data 的 devices 中
});
// const title = '已选择蓝牙设备,开始连接';
// if (title) {
// dd.showToast({
// title,
// icon: 'success'
// });
// }
this.connectBluetoothDevice();
} else {
console.log('未找到选中的蓝牙设备');
// const title = '未找到选中的蓝牙设备';
// if (title) {
// dd.showToast({
// title,
// icon: 'none'
// });
// }
}
},
connectBluetoothDevice() {
const deviceId = this.data.deviceId;
if (deviceId) {
dd.connectBLEDevice({
deviceId,
success: (res) => {
console.log('连接蓝牙设备成功', res);
this.setData({
isConnected: true,
iconType: [
'success',
],
});
// const title = '蓝牙设备连接成功';
// if (title) {
// dd.showToast({
// title,
// icon: 'success'
// });
// }
// 获取设备的服务列表
this.getBLEDeviceServices(deviceId);
},
fail: (res) => {
console.error('连接蓝牙设备失败,错误码:', res.errorCode);
// const title = `连接蓝牙设备失败,错误码: ${res.errorCode}`;
// if (title) {
// dd.showToast({
// title,
// icon: 'none'
// });
// }
},
complete: (res) => {
console.log('连接蓝牙设备调用结束', res);
}
});
} else {
console.log('请先选择要连接的蓝牙设备');
const title = '请先选择要连接的蓝牙设备';
if (title) {
dd.showToast({
title,
icon: 'none'
});
}
}
},
/**
* 获取设备的服务列表
* @param {string} deviceId - 设备 ID
*/
getBLEDeviceServices(deviceId) {
dd.getBLEDeviceServices({
deviceId,
success: (serviceRes) => {
const services = serviceRes.services;
if (services && services.length > 0) {
services.forEach((service) => {
const serviceUuid = service.uuid || service.serviceId;
if (serviceUuid) {
this.getBLEDeviceCharacteristics(deviceId, serviceUuid);
} else {
console.error('服务的 UUID 和 serviceId 均为空,无法获取特征值。服务详情:', service);
const title = '服务 UUID 和 serviceId 均为空,无法获取特征值';
if (title) {
dd.showToast({
title,
icon: 'none'
});
}
}
});
} else {
console.error('未获取到服务列表');
const title = '未获取到服务列表';
if (title) {
dd.showToast({
title,
icon: 'none'
});
}
}
},
fail: (serviceErr) => {
console.error('获取服务失败', serviceErr);
const title = '获取服务失败';
if (title) {
dd.showToast({
title,
icon: 'none'
});
}
}
});
},
/**
* 获取设备的特征值列表
* @param {string} deviceId - 设备 ID
* @param {string} serviceId - 服务 ID
*/
getBLEDeviceCharacteristics(deviceId, serviceId) {
if (!deviceId || !serviceId) {
console.error('deviceId 或 serviceId 为空,无法获取特征值');
return;
}
dd.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (characteristicRes) => {
const characteristics = characteristicRes.characteristics;
console.log('获取到的所有特征值:', characteristics);
// 先筛选出可读可写的特征值
const readableAndWritable = characteristics.filter(
(characteristic) => characteristic.properties.read && characteristic.properties.write
);
// 如果没有可读可写的特征值,则筛选出只可写的特征值
const writable = readableAndWritable.length > 0 ?
readableAndWritable :
characteristics.filter(
(characteristic) => characteristic.properties.write
);
console.log('筛选出的可写特征值:', writable);
// 更新组件数据,存储可写特征值列表
this.setData({
writableCharacteristics: [...this.data.writableCharacteristics, ...writable]
});
console.log('获取特征值成功', characteristicRes);
const title = '获取特征值成功';
if (title) {
dd.showToast({
title,
icon: 'success'
});
}
},
fail: (characteristicErr) => {
console.error('获取特征值失败', characteristicErr);
const title = '获取特征值失败';
if (title) {
dd.showToast({
title,
icon: 'none'
});
}
}
});
},
/**
* 重新连接蓝牙设备
*/
reconnectBluetoothDevice() {
const deviceId = this.data.deviceId;
if (deviceId) {
setTimeout(() => {
dd.createBLEConnection({
deviceId,
success: (res) => {
console.log('重新连接蓝牙设备成功', res);
this.setData({
isConnected: true,
iconType: [
'success',
],
});
const title = '蓝牙设备重新连接成功';
if (title) {
dd.showToast({
title,
icon: 'success'
});
}
// this.startHeartbeat();
},
fail: (res) => {
console.error('重新连接蓝牙设备失败,错误码:', res.errorCode);
const title = `重新连接蓝牙设备失败,错误码: ${res.errorCode}`;
if (title) {
dd.showToast({
title,
icon: 'none'
});
}
this.reconnectBluetoothDevice();
},
complete: (res) => {
console.log('重新连接蓝牙设备调用结束', res);
}
});
}, 2000); // 2 秒后重试
}
},
/**
* 关闭蓝牙连接
*/
closeBluetoothConnection() {
const deviceId = this.data.deviceId;
if (deviceId && this.data.isConnected) {
dd.closeBLEConnection({
deviceId,
success: (res) => {
console.log('蓝牙连接已关闭', res);
this.setData({
isConnected: false,
iconType: [
'cancel',
],
});
if (this.data.heartbeatTimer) {
clearInterval(this.data.heartbeatTimer);
}
const title = '蓝牙连接已关闭';
if (title) {
dd.showToast({
title,
icon: 'success'
});
}
},
fail: (res) => {
console.error('关闭蓝牙连接失败,错误码:', res.errorCode);
const title = `关闭蓝牙连接失败,错误码: ${res.errorCode}`;
if (title) {
dd.showToast({
title,
icon: 'none'
});
}
},
complete: (res) => {
console.log('关闭蓝牙连接调用结束', res);
}
});
}
},
/**
* 监听蓝牙连接状态变化事件
*/
listenBLEConnectionStateChanged() {
// 先关闭之前的事件监听
dd.offBLEConnectionStateChanged(this.handleBLEConnectionStateChanged);
// 绑定回调函数上下文
this.handleBLEConnectionStateChanged = this.handleBLEConnectionStateChanged.bind(this);
// 监听蓝牙连接状态变化事件
dd.onBLEConnectionStateChanged(this.handleBLEConnectionStateChanged);
},
/**
* 处理蓝牙连接状态变化事件的回调函数
*/
handleBLEConnectionStateChanged(res) {
const {
deviceId,
connected
} = res;
if (connected) {
console.log(`蓝牙设备 ${deviceId} 连接成功`);
const title = `蓝牙设备 ${deviceId} 连接成功`;
if (title) {
dd.showToast({
title,
icon: 'success'
});
}
this.setData({
isConnected: true,
iconType: [
'success',
],
});
} else {
console.log(`蓝牙设备 ${deviceId} 连接断开,尝试重新连接`);
const title = `蓝牙设备 ${deviceId} 连接断开,尝试重新连接`;
if (title) {
dd.showToast({
title,
icon: 'none'
});
}
this.setData({
isConnected: false,
iconType: [
// 'success',
'cancel'
],
});
this.reconnectBluetoothDevice();
}
},
onSubmit() {
const selectedDevice = this.data.selectedDevice;
console.log('selectedDevice', selectedDevice);
const isConnected = this.data.isConnected;
// 检查蓝牙设备是否已连接
if (!selectedDevice || !isConnected) {
console.log('请先连接蓝牙设备');
const title = '请先连接蓝牙设备';
if (title) {
dd.showToast({
title,
icon: 'none'
});
}
return;
}
// 从可写特征值列表中获取第一个可写特征值(这里假设只有一个可写特征值,你可以根据实际情况调整)
const writableCharacteristic = this.data.writableCharacteristics[0];
console.log('writableCharacteristics', this.data.writableCharacteristics);
if (!writableCharacteristic) {
console.log('未找到可写特征值');
const title = '未找到可写特征值';
if (title) {
dd.showToast({
title,
icon: 'none'
});
}
return;
}
const serviceId = writableCharacteristic.serviceId;
const characteristicId = writableCharacteristic.characteristicId;
const deviceId = selectedDevice.deviceId;
// 检查参数完整性
if (!deviceId || !serviceId || !characteristicId) {
console.error('缺少必要参数:', {
deviceId,
serviceId,
characteristicId
});
const title = '缺少必要参数,请检查连接';
if (title) {
dd.showToast({
// title,
icon: 'none'
});
}
return;
}
// 假设 printcode 是一个变量,需要在代码里定义
const printcode = [1, 2, 3, 4];
const sendPrintCode = (index) => {
if (index >= printcode.length) {
console.log('所有 printcode 数据发送完成');
// const title = '所有 printcode 数据发送完成';
// if (title) {
// dd.showToast({
// // title,
// icon: 'success'
// });
// }
return;
}
const currentCode = printcode[index];
const command = `
SIZE 7,5
GAP 2,0
CLS
QRCODE 20,150,H,5,A,0,"${currentCode}"
TEXT 20,350,"2",0,1,1,"${currentCode}"
PRINT 1,1
`;
const encoder = new TextEncoder('utf-8');
const commandBuffer = encoder.encode(command);
// 将二进制数据转换为 hex 编码
const hexValue = Array.from(commandBuffer)
.map(byte => byte.toString(16).padStart(2, '0'))
.join('');
// 分段发送数据
const chunkSize = 40; // 每个分段的长度20 字节 = 40 个十六进制字符
const chunks = [];
for (let i = 0; i < hexValue.length; i += chunkSize) {
chunks.push(hexValue.slice(i, i + chunkSize));
}
const sendNextChunk = (chunkIndex) => {
if (chunkIndex >= chunks.length) {
console.log(`printcode ${currentCode} 的所有数据分段发送完成`);
sendPrintCode(index + 1);
return;
}
const currentChunk = chunks[chunkIndex];
console.log(`准备发送 printcode ${currentCode} 的第 ${chunkIndex + 1} 个数据分段,长度: ${currentChunk.length}`, currentChunk);
dd.writeBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
value: currentChunk,
success: (res) => {
console.log(`printcode ${currentCode} 的第 ${chunkIndex + 1} 个数据分段发送成功`, res);
sendNextChunk(chunkIndex + 1);
},
fail: (res) => {
console.error(`printcode ${currentCode} 的第 ${chunkIndex + 1} 个数据分段发送失败,错误码:`, res.errorCode);
const title = `printcode ${currentCode} 的第 ${chunkIndex + 1} 个数据分段发送失败,错误码: ${res.errorCode}`;
// if (title) {
// dd.showToast({
// title: title,
// icon: 'none'
// });
// }
},
complete: (res) => {
console.log(`printcode ${currentCode} 的第 ${chunkIndex + 1} 个数据分段发送调用结束`, res);
}
});
};
sendNextChunk(0);
};
sendPrintCode(0);
}
}
});

View File

@@ -0,0 +1,3 @@
{
"component": true
}