"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