Files
smartDriveEEUniApp/unpackage/dist/dev/mp-weixin/common/bluetooth.js
2026-01-20 08:46:36 +08:00

447 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
const common_vendor = require("./vendor.js");
class BluetoothRecorder {
constructor() {
this.adapterState = false;
this.isScanning = false;
this.connectedDeviceId = null;
this.deviceList = [];
this.services = [];
this.characteristics = [];
this.notifyCharacteristicId = null;
this.writeCharacteristicId = null;
this.audioBuffer = [];
this.isReceiving = false;
this.onDeviceFound = null;
this.onDeviceConnected = null;
this.onDeviceDisconnected = null;
this.onAudioDataReceived = null;
this.onError = null;
}
/**
* 初始化蓝牙适配器
*/
async initBluetoothAdapter() {
return new Promise((resolve, reject) => {
common_vendor.index.openBluetoothAdapter({
success: (res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:36", "蓝牙适配器初始化成功", res);
this.adapterState = true;
this._listenAdapterState();
resolve(res);
},
fail: (err) => {
common_vendor.index.__f__("error", "at common/bluetooth.js:42", "蓝牙适配器初始化失败", err);
this.adapterState = false;
this._handleError("蓝牙适配器初始化失败", err);
reject(err);
}
});
});
}
/**
* 监听蓝牙适配器状态变化
*/
_listenAdapterState() {
common_vendor.index.onBluetoothAdapterStateChange((res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:56", "蓝牙适配器状态变化", res);
this.adapterState = res.available;
if (!res.available) {
this.connectedDeviceId = null;
this._handleError("蓝牙适配器不可用", res);
}
});
}
/**
* 开始搜索蓝牙设备
* @param {Object} options - 搜索选项
* @param {Array} options.services - 服务UUID列表可选
* @param {number} options.interval - 上报间隔(毫秒)
* @param {boolean} options.allowDuplicatesKey - 是否允许重复上报
*/
async startScan(options = {}) {
if (this.isScanning) {
common_vendor.index.__f__("warn", "at common/bluetooth.js:74", "已经在扫描中");
return;
}
if (!this.adapterState) {
await this.initBluetoothAdapter();
}
return new Promise((resolve, reject) => {
common_vendor.index.onBluetoothDeviceFound((res) => {
const devices = res.devices || [];
devices.forEach((device) => {
const exists = this.deviceList.find((d) => d.deviceId === device.deviceId);
if (!exists) {
this.deviceList.push({
deviceId: device.deviceId,
name: device.name || "未知设备",
RSSI: device.RSSI,
advertisData: device.advertisData,
advertisServiceUUIDs: device.advertisServiceUUIDs,
localName: device.localName
});
if (this.onDeviceFound) {
this.onDeviceFound(device);
}
}
});
});
common_vendor.index.startBluetoothDevicesDiscovery({
services: options.services || [],
allowDuplicatesKey: options.allowDuplicatesKey || false,
interval: options.interval || 0,
success: (res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:113", "开始搜索蓝牙设备", res);
this.isScanning = true;
resolve(res);
},
fail: (err) => {
common_vendor.index.__f__("error", "at common/bluetooth.js:118", "搜索蓝牙设备失败", err);
this.isScanning = false;
this._handleError("搜索蓝牙设备失败", err);
reject(err);
}
});
});
}
/**
* 停止搜索蓝牙设备
*/
async stopScan() {
if (!this.isScanning) {
return;
}
return new Promise((resolve, reject) => {
common_vendor.index.stopBluetoothDevicesDiscovery({
success: (res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:138", "停止搜索蓝牙设备", res);
this.isScanning = false;
resolve(res);
},
fail: (err) => {
common_vendor.index.__f__("error", "at common/bluetooth.js:143", "停止搜索失败", err);
this._handleError("停止搜索失败", err);
reject(err);
}
});
});
}
/**
* 连接蓝牙设备
* @param {string} deviceId - 设备ID
*/
async connectDevice(deviceId) {
if (this.connectedDeviceId === deviceId) {
common_vendor.index.__f__("warn", "at common/bluetooth.js:157", "设备已连接");
return;
}
return new Promise((resolve, reject) => {
common_vendor.index.createBLEConnection({
deviceId,
success: async (res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:165", "蓝牙设备连接成功", res);
this.connectedDeviceId = deviceId;
this._listenConnectionState(deviceId);
try {
await this.getServices(deviceId);
if (this.onDeviceConnected) {
this.onDeviceConnected(deviceId);
}
resolve(res);
} catch (err) {
reject(err);
}
},
fail: (err) => {
common_vendor.index.__f__("error", "at common/bluetooth.js:186", "蓝牙设备连接失败", err);
this._handleError("蓝牙设备连接失败", err);
reject(err);
}
});
});
}
/**
* 监听连接状态
*/
_listenConnectionState(deviceId) {
common_vendor.index.onBLEConnectionStateChange((res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:199", "蓝牙连接状态变化", res);
if (res.deviceId === deviceId) {
if (!res.connected) {
this.connectedDeviceId = null;
this.isReceiving = false;
if (this.onDeviceDisconnected) {
this.onDeviceDisconnected(deviceId);
}
}
}
});
}
/**
* 断开蓝牙设备连接
*/
async disconnectDevice() {
if (!this.connectedDeviceId) {
return;
}
return new Promise((resolve, reject) => {
common_vendor.index.closeBLEConnection({
deviceId: this.connectedDeviceId,
success: (res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:225", "蓝牙设备断开成功", res);
this.connectedDeviceId = null;
this.isReceiving = false;
this.audioBuffer = [];
resolve(res);
},
fail: (err) => {
common_vendor.index.__f__("error", "at common/bluetooth.js:232", "蓝牙设备断开失败", err);
this._handleError("蓝牙设备断开失败", err);
reject(err);
}
});
});
}
/**
* 获取蓝牙设备服务列表
* @param {string} deviceId - 设备ID
*/
async getServices(deviceId) {
return new Promise((resolve, reject) => {
common_vendor.index.getBLEDeviceServices({
deviceId,
success: async (res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:249", "获取服务列表成功", res);
this.services = res.services || [];
for (const service of this.services) {
try {
await this.getCharacteristics(deviceId, service.uuid);
} catch (err) {
common_vendor.index.__f__("warn", "at common/bluetooth.js:257", "获取特征值失败", service.uuid, err);
}
}
resolve(res);
},
fail: (err) => {
common_vendor.index.__f__("error", "at common/bluetooth.js:264", "获取服务列表失败", err);
this._handleError("获取服务列表失败", err);
reject(err);
}
});
});
}
/**
* 获取特征值列表
* @param {string} deviceId - 设备ID
* @param {string} serviceId - 服务UUID
*/
async getCharacteristics(deviceId, serviceId) {
return new Promise((resolve, reject) => {
common_vendor.index.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:283", "获取特征值成功", serviceId, res);
const chars = res.characteristics || [];
this.characteristics.push(...chars);
chars.forEach((char) => {
if (char.properties.notify || char.properties.indicate) {
if (!this.notifyCharacteristicId) {
this.notifyCharacteristicId = {
deviceId,
serviceId,
characteristicId: char.uuid
};
this.enableNotify(deviceId, serviceId, char.uuid);
}
}
if (char.properties.write || char.properties.writeNoResponse) {
if (!this.writeCharacteristicId) {
this.writeCharacteristicId = {
deviceId,
serviceId,
characteristicId: char.uuid
};
}
}
});
resolve(res);
},
fail: (err) => {
common_vendor.index.__f__("error", "at common/bluetooth.js:317", "获取特征值失败", err);
reject(err);
}
});
});
}
/**
* 启用特征值通知(用于接收音频数据)
* @param {string} deviceId - 设备ID
* @param {string} serviceId - 服务UUID
* @param {string} characteristicId - 特征值UUID
*/
async enableNotify(deviceId, serviceId, characteristicId) {
return new Promise((resolve, reject) => {
common_vendor.index.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId,
state: true,
// 启用通知
success: (res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:338", "启用通知成功", res);
common_vendor.index.onBLECharacteristicValueChange((res2) => {
this._handleAudioData(res2.value);
});
this.isReceiving = true;
resolve(res);
},
fail: (err) => {
common_vendor.index.__f__("error", "at common/bluetooth.js:349", "启用通知失败", err);
this._handleError("启用通知失败", err);
reject(err);
}
});
});
}
/**
* 处理接收到的音频数据
* @param {ArrayBuffer} data - 音频数据
*/
_handleAudioData(data) {
const base64 = common_vendor.index.arrayBufferToBase64(data);
this.audioBuffer.push({
data: base64,
timestamp: Date.now()
});
if (this.onAudioDataReceived) {
this.onAudioDataReceived({
data: base64,
arrayBuffer: data,
timestamp: Date.now()
});
}
}
/**
* 读取特征值
* @param {string} deviceId - 设备ID
* @param {string} serviceId - 服务UUID
* @param {string} characteristicId - 特征值UUID
*/
async readCharacteristic(deviceId, serviceId, characteristicId) {
return new Promise((resolve, reject) => {
common_vendor.index.readBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
success: (res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:394", "读取特征值成功", res);
resolve(res);
},
fail: (err) => {
common_vendor.index.__f__("error", "at common/bluetooth.js:398", "读取特征值失败", err);
this._handleError("读取特征值失败", err);
reject(err);
}
});
});
}
/**
* 写入特征值(发送命令到设备)
* @param {ArrayBuffer} value - 要写入的数据
*/
async writeCharacteristic(value) {
if (!this.writeCharacteristicId) {
throw new Error("未找到可写入的特征值");
}
const { deviceId, serviceId, characteristicId } = this.writeCharacteristicId;
return new Promise((resolve, reject) => {
common_vendor.index.writeBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
value,
success: (res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:424", "写入特征值成功", res);
resolve(res);
},
fail: (err) => {
common_vendor.index.__f__("error", "at common/bluetooth.js:428", "写入特征值失败", err);
this._handleError("写入特征值失败", err);
reject(err);
}
});
});
}
/**
* 获取已缓存的音频数据
*/
getAudioBuffer() {
return this.audioBuffer;
}
/**
* 清空音频缓冲区
*/
clearAudioBuffer() {
this.audioBuffer = [];
}
/**
* 合并音频数据为完整文件Base64格式
*/
mergeAudioData() {
return this.audioBuffer.map((item) => item.data).join("");
}
/**
* 处理错误
*/
_handleError(message, error) {
common_vendor.index.__f__("error", "at common/bluetooth.js:461", `[BluetoothRecorder] ${message}`, error);
if (this.onError) {
this.onError({
message,
error
});
}
}
/**
* 关闭蓝牙适配器
*/
async closeBluetoothAdapter() {
if (this.connectedDeviceId) {
await this.disconnectDevice();
}
if (this.isScanning) {
await this.stopScan();
}
return new Promise((resolve, reject) => {
common_vendor.index.closeBluetoothAdapter({
success: (res) => {
common_vendor.index.__f__("log", "at common/bluetooth.js:487", "关闭蓝牙适配器成功", res);
this.adapterState = false;
resolve(res);
},
fail: (err) => {
common_vendor.index.__f__("error", "at common/bluetooth.js:492", "关闭蓝牙适配器失败", err);
reject(err);
}
});
});
}
/**
* 获取设备列表
*/
getDeviceList() {
return this.deviceList;
}
/**
* 清空设备列表
*/
clearDeviceList() {
this.deviceList = [];
}
}
const bluetoothRecorder = new BluetoothRecorder();
exports.bluetoothRecorder = bluetoothRecorder;
//# sourceMappingURL=../../.sourcemap/mp-weixin/common/bluetooth.js.map