const logEnable = false let isAndroid = false let ecBluetoothAdapterStateChangeCallback = () => {} let ecBluetoothDeviceFoundCallback = () => {} let ecBLEConnectionStateChangeCallback = () => {} let ecBLECharacteristicValueChangeCallback = () => {} let ecDeviceId = '' let ecGattServerUUID = '' const ecGattServerUUIDOption1 = '0000FFF0-0000-1000-8000-00805F9B34FB' const ecGattServerUUIDOption2 = 'FFF0' const yiyuanUUIDOption1 = '0000F536-0000-1000-8000-00805F9B34FB'; const yiyuanUUIDOption2 = 'F536'; let ecGattCharacteristicWriteUUID = '' const ecGattCharacteristicWriteUUIDOption1 = '0000FFF2-0000-1000-8000-00805F9B34FB' const ecGattCharacteristicWriteUUIDOption2 = 'FFF2' const yiyuancharacterID1 = '0000FF15-0000-1000-8000-00805F9B34FB' const yiyuancharacterID2 = 'FF15' import i18 from '@/utils/i18.js' const log = data => { if (logEnable) { console.log('[eciot]:' + JSON.stringify(data)) } } const onBluetoothAdapterStateChange = cb => { ecBluetoothAdapterStateChangeCallback = cb } const _openBluetoothAdapter = () => { return new Promise(function(resolve, reject) { uni.openBluetoothAdapter({ success(res) { log(res) resolve({ ok: true, errCode: 0, errMsg: '' }) }, fail(res) { log(res) // {"errMsg":"openBluetoothAdapter:fail not available","code":10001} resolve({ ok: false, errCode: res.code, errMsg: res.errMsg, }) }, }) }) } uni.onBluetoothAdapterStateChange(res => { log(res) // {"discovering":true,"available":true} if (!res.available) { ecBluetoothAdapterStateChangeCallback({ ok: false, errCode: 30005, errMsg: i18('蓝牙适配器不可用'), }) } }) const openBluetoothAdapter = async () => { await _openBluetoothAdapter() const systemInfo = uni.getSystemInfoSync() log(systemInfo) if (systemInfo.platform.toLowerCase() === 'android') { isAndroid = true } const systemSetting = uni.getSystemSetting() log(systemSetting) const appAuthorizeSetting = uni.getAppAuthorizeSetting() log(appAuthorizeSetting) if (!systemSetting.bluetoothEnabled) { ecBluetoothAdapterStateChangeCallback({ ok: false, errCode: 30001, errMsg: i18('请打开系统蓝牙开关'), }) return } if (isAndroid && !systemSetting.locationEnabled) { ecBluetoothAdapterStateChangeCallback({ ok: false, errCode: 30002, errMsg: i18('请打开系统定位开关'), }) return } if (isAndroid && (appAuthorizeSetting.locationAuthorized!=='authorized')) { ecBluetoothAdapterStateChangeCallback({ ok: false, errCode: 30003, errMsg: i18('请打开应用定位权限,允许应用使用您的位置信息'), }) return } const openRes = await _openBluetoothAdapter() ecBluetoothAdapterStateChangeCallback(openRes) } uni.onBluetoothDeviceFound(res => { // log(res) const device = res.devices[0] const name = device.name ? device.name : device.localName if (!name) { return } let id = device.deviceId let rssi = device.RSSI ecBluetoothDeviceFoundCallback({ id, name, rssi }) }) const onBluetoothDeviceFound = cb => { ecBluetoothDeviceFoundCallback = cb } const startBluetoothDevicesDiscovery = () => { uni.startBluetoothDevicesDiscovery({ //services: [ecServerId], allowDuplicatesKey: true, // powerLevel: 'high', complete(res) { log(res) }, }) } const stopBluetoothDevicesDiscovery = () => { uni.stopBluetoothDevicesDiscovery({ complete(res) { log(res) }, }) } const onBLEConnectionStateChange = cb => { ecBLEConnectionStateChangeCallback = cb } const _createBLEConnection = () => { return new Promise(function(resolve, reject) { uni.createBLEConnection({ deviceId: ecDeviceId, success(res) { log(res) resolve({ ok: true, errCode: 0, errMsg: '' }) }, fail(res) { log(res) resolve({ ok: false, errCode: res.code, errMsg: res.errMsg, }) }, }) }) } const getBLEDeviceServices = () => { return new Promise(function(resolve, reject) { setTimeout(()=>{ uni.getBLEDeviceServices({ deviceId: ecDeviceId, success(res) { log(res) resolve({ ok: true, errCode: 0, errMsg: '', services: res.services, }) }, fail(res) { log(res) resolve({ ok: false, errCode: res.code, errMsg: res.errMsg }) }, }) },1200)//之前是800ms,要休眠到1200ms }) } const getBLEDeviceCharacteristics = serviceId => { return new Promise(function(resolve, reject) { uni.getBLEDeviceCharacteristics({ deviceId: ecDeviceId, serviceId, success(res) { log(res) resolve({ ok: true, errCode: 0, errMsg: '', characteristics: res.characteristics, }) }, fail(res) { log(res) resolve({ ok: false, errCode: res.code, errMsg: res.errMsg }) }, }) }) } const notifyBLECharacteristicValueChange = (serviceId, characteristicId) => { return new Promise(function(resolve, reject) { uni.notifyBLECharacteristicValueChange({ state: true, deviceId: ecDeviceId, serviceId, characteristicId, success(res) { log(res) resolve({ ok: true, errCode: 0, errMsg: '' }) }, fail(res) { log(res) resolve({ ok: false, errCode: res.code, errMsg: res.errMsg }) }, }) }) } const setBLEMTU = mtu => { return new Promise(function(resolve, reject) { setTimeout(()=>{ uni.setBLEMTU({ deviceId: ecDeviceId, mtu, success(res) { log(res) resolve({ ok: true, errCode: 0, errMsg: '' }) }, fail(res) { log(res) resolve({ ok: false, errCode: res.code, errMsg: res.errMsg }) }, }) },500) }) } uni.onBLEConnectionStateChange(async res => { log(res) if (res.connected) { console.log("=== 设备连接成功 ===") const servicesResult = await getBLEDeviceServices() console.log("服务发现结果:", servicesResult) if (!servicesResult.ok) { ecBLEConnectionStateChangeCallback(servicesResult) closeBLEConnection() return } console.log("设备提供的所有服务:", servicesResult.services) // 优先查找的服务和特征值UUID(与微信端保持一致) const targetServiceUUIDs = [ '0000FFE0-0000-1000-8000-00805F9B34FB'.toUpperCase(), 'FFE0'.toUpperCase(), // 保留原来的选项 '0000FFF0-0000-1000-8000-00805F9B34FB'.toUpperCase(), 'FFF0'.toUpperCase(), '0000F536-0000-1000-8000-00805F9B34FB'.toUpperCase(), 'F536'.toUpperCase() ]; const targetCharacteristicUUIDs = [ '0000FFE1-0000-1000-8000-00805F9B34FB'.toUpperCase(), 'FFE1'.toUpperCase(), // 保留原来的选项 '0000FFF2-0000-1000-8000-00805F9B34FB'.toUpperCase(), 'FFF2'.toUpperCase(), '0000FF15-0000-1000-8000-00805F9B34FB'.toUpperCase(), 'FF15'.toUpperCase() ]; let serviceFound = false; let notifyEnabled = false; // 新增:跟踪是否成功启用通知 let writeCharacteristicFound = false; // 跟踪是否找到写入特征值 // 首先按优先级查找 serviceLoop: for (const service of servicesResult.services) { const serviceUUID = service.uuid.toUpperCase(); console.log("正在检查服务:", serviceUUID); // 检查是否是目标服务 if (targetServiceUUIDs.includes(serviceUUID)) { console.log("✅ 找到目标服务:", serviceUUID); // 获取该服务下的所有特征值 const characteristicsResult = await getBLEDeviceCharacteristics(service.uuid) console.log(`服务 ${service.uuid} 的特征值获取结果:`, characteristicsResult); if (!characteristicsResult.ok) { console.log(`获取服务 ${service.uuid} 的特征值失败`) continue } console.log(`服务 ${service.uuid} 下的特征值:`, characteristicsResult.characteristics) // 分别查找通知特征值和写入特征值 let notifyCharacteristic = null; let writeCharacteristic = null; // 遍历所有特征值 for (const characteristic of characteristicsResult.characteristics) { const charUUID = characteristic.uuid.toUpperCase(); console.log("检查特征值:", charUUID, "属性:", characteristic.properties); // 查找通知特征值 if (characteristic.properties && (characteristic.properties.notify || characteristic.properties.indicate)) { notifyCharacteristic = characteristic; console.log("✅ 找到通知特征值:", charUUID); // 尝试启用通知 const notifyResult = await notifyBLECharacteristicValueChange( service.uuid, characteristic.uuid ) if (notifyResult.ok) { console.log("✅ 通知已启用:", characteristic.uuid); notifyEnabled = true; } else { console.log("⚠️ 启用通知失败:", characteristic.uuid, notifyResult); } } // 查找写入特征值 if (targetCharacteristicUUIDs.includes(charUUID) && characteristic.properties && (characteristic.properties.write || characteristic.properties.writeNoResponse)) { writeCharacteristic = characteristic; console.log("✅ 找到写入特征值:", charUUID); } } // 如果找到了写入特征值,设置全局变量 if (writeCharacteristic) { ecGattServerUUID = service.uuid; ecGattCharacteristicWriteUUID = writeCharacteristic.uuid; console.log("服务 UUID:", ecGattServerUUID); console.log("写入特征值 UUID:", ecGattCharacteristicWriteUUID); serviceFound = true; writeCharacteristicFound = true; break serviceLoop; } } } // 如果没找到目标服务/特征值,则使用动态查找 if (!serviceFound) { console.log("未找到预定义的服务/特征值,使用动态查找...") serviceLoop2: for (const service of servicesResult.services) { console.log("正在检查服务:", service.uuid) // 获取该服务下的所有特征值 const characteristicsResult = await getBLEDeviceCharacteristics(service.uuid) console.log(`服务 ${service.uuid} 的特征值获取结果:`, characteristicsResult); if (!characteristicsResult.ok) { console.log(`获取服务 ${service.uuid} 的特征值失败`) continue } console.log(`服务 ${service.uuid} 下的特征值:`, characteristicsResult.characteristics) // 分别查找通知特征值和写入特征值 let notifyCharacteristic = null; // 遍历所有特征值 for (const characteristic of characteristicsResult.characteristics) { console.log("动态查找 - 检查特征值:", characteristic.uuid, "属性:", characteristic.properties); // 查找通知特征值 if (characteristic.properties && (characteristic.properties.notify || characteristic.properties.indicate)) { notifyCharacteristic = characteristic; console.log("✅ 找到通知特征值:", characteristic.uuid); // 尝试启用通知 const notifyResult = await notifyBLECharacteristicValueChange( service.uuid, characteristic.uuid ) if (notifyResult.ok) { console.log("✅ 通知已启用:", characteristic.uuid); notifyEnabled = true; } else { console.log("⚠️ 启用通知失败:", characteristic.uuid, notifyResult); } } // 查找写入特征值 if (characteristic.properties && (characteristic.properties.write || characteristic.properties.writeNoResponse)) { // 找到支持写入的特征值,设置全局变量 ecGattServerUUID = service.uuid ecGattCharacteristicWriteUUID = characteristic.uuid console.log("✅ 找到可写特征值") console.log("服务 UUID:", ecGattServerUUID) console.log("特征值 UUID:", ecGattCharacteristicWriteUUID) serviceFound = true writeCharacteristicFound = true; break serviceLoop2; // 使用标签跳出外层循环 } } } } // 如果没有找到可写特征值 if (!writeCharacteristicFound) { console.error("❌ 未找到支持写入的特征值") console.log("所有服务和特征值信息:", servicesResult.services); ecBLEConnectionStateChangeCallback({ ok: false, errCode: 30000, errMsg: '未找到支持写入的特征值', }) closeBLEConnection() return } // 检查是否成功启用了通知 if (!notifyEnabled) { console.warn("⚠️ 警告:未成功启用任何特征值的通知功能"); console.log("⚠️ 设备可能使用轮询方式而非通知方式通信"); // 继续连接,因为有些设备可能不使用通知机制 } else { console.log("✅ 通知功能已成功启用"); } // 设置MTU(仅安卓) if (isAndroid) { try { await setBLEMTU(247) console.log("MTU 设置成功") } catch (error) { console.log("MTU 设置失败:", error) } } // 连接成功回调 console.log("=== 准备发送连接成功回调 ==="); console.log("服务UUID:", ecGattServerUUID); console.log("写入特征值UUID:", ecGattCharacteristicWriteUUID); ecBLEConnectionStateChangeCallback({ ok: true, errCode: 0, errMsg: '', }) } else { console.log("=== 设备断开连接 ==="); ecBLEConnectionStateChangeCallback({ ok: false, errCode: 0, errMsg: 'disconnect', }) } }) const createBLEConnection = async id => { ecDeviceId = id const res = await _createBLEConnection() if (!res.ok) { ecBLEConnectionStateChangeCallback(res) } } const closeBLEConnection = () => { uni.closeBLEConnection({ deviceId: ecDeviceId, complete(res) { log(res); uni.showToast({ title: '操作执行成功!', icon: 'success', duration: 2000 }); }, }) } uni.onBLECharacteristicValueChange(res => { log(res) let x = new Uint8Array(res.value) log(x) let str = utf8BytesToStr(x) let strHex = '' for (let i = 0; i < x.length; i++) { strHex = strHex + x[i].toString(16).padStart(2, '0').toUpperCase() } log(str) log(strHex) ecBLECharacteristicValueChangeCallback(str, strHex) }) const onBLECharacteristicValueChange = cb => { ecBLECharacteristicValueChangeCallback = cb } const _writeBLECharacteristicValue = buffer => { return new Promise(function(resolve, reject) { uni.writeBLECharacteristicValue({ deviceId: ecDeviceId, serviceId: ecGattServerUUID, characteristicId: ecGattCharacteristicWriteUUID, value: buffer, writeType: 'writeNoResponse', success(res) { log(res) resolve({ ok: true, errCode: 0, errMsg: '' }) }, fail(res) { console.log("写入失败"); console.log(res); log(res) resolve({ ok: false, errCode: res.code, errMsg: res.errMsg }) }, }) }) } const writeBLECharacteristicValue = async (str, isHex) => { if (str.length === 0) return { ok: false, errCode: 30000, errMsg: 'data is null' } let buffer if (isHex) { buffer = new ArrayBuffer(str.length / 2) let x = new Uint8Array(buffer) for (let i = 0; i < x.length; i++) { x[i] = parseInt(str.substr(2 * i, 2), 16) } } else { // AT指令模式 - 处理ASCII字符串 // 转换为UTF-8字节数组 const encoder = new TextEncoder(); const utf8Bytes = encoder.encode(str); buffer = utf8Bytes.buffer; // 显示ASCII格式的日志 console.log("TX: " + str); // 发送数据日志 const writeData = "RX: " + str; saveWriteDataToLocal(writeData, 'rx'); } if (isHex){ // 显示十六进制格式的日志(类似 RX: + 的格式) const hexArray = [...new Uint8Array(buffer)] .map(b => b.toString(16).padStart(2, '0').toUpperCase()); const hexString = hexArray.join(' '); console.log("RX: " + hexString); // 发送数据日志,格式如 "RX: 01 03 00 01 00 01" // 保存写入数据到本地存储 const writeData = "RX: " + hexString; saveWriteDataToLocal(writeData,'rx'); }else { const writeData = "RX: " + str; saveWriteDataToLocal(writeData,'rx'); } return await _writeBLECharacteristicValue(buffer) } /** * 向蓝牙特征值写入数据 * @param {string} str - 要发送的字符串数据 * @param {boolean} isHex - 数据格式标志。 * false: str 包含十六进制字符串 (e.g., "01030001004695F8") * true: str 包含 ASCII 字符串 (e.g., "Hello") * @returns {Promise} 写入操作的结果 */ const writeBLECharacteristicValueTwo = async (str, isHex) => { if (str.length === 0) return { ok: false, errCode: 30000, errMsg: 'data is null' } let buffer; // isHex === false 时,发送 ASCII 字符串 if (!isHex) { // AT指令模式 - 处理ASCII字符串 // 转换为UTF-8字节数组 const encoder = new TextEncoder(); const utf8Bytes = encoder.encode(str); buffer = utf8Bytes.buffer; // 显示ASCII格式的日志 console.log("TX (ASCII): " + str); // 发送数据日志 const writeData = "TX (ASCII): " + str; saveWriteDataToLocal(writeData, 'tx'); } // isHex === true 时,发送十六进制字符串 else { // 移除所有空格,确保是连续的十六进制字符串 const hexString = str.replace(/\s/g, ''); // 检查长度是否为偶数 if (hexString.length % 2 !== 0) { console.error("Invalid hex string length"); return { ok: false, errCode: 30001, errMsg: 'Invalid hex string length' }; } // 检查是否包含非十六进制字符 if (!/^[0-9A-Fa-f]*$/.test(hexString)) { console.error("Invalid hex characters"); return { ok: false, errCode: 30002, errMsg: 'Invalid hex characters' }; } // 创建 ArrayBuffer 并填充数据 buffer = new ArrayBuffer(hexString.length / 2); let x = new Uint8Array(buffer); for (let i = 0; i < x.length; i++) { x[i] = parseInt(hexString.substr(2 * i, 2), 16); } // 显示十六进制格式的日志 const formattedHex = hexString.match(/.{1,2}/g)?.join(' ') || ''; console.log("TX (HEX): " + formattedHex); // 发送数据日志 const writeData = "TX (HEX): " + formattedHex; saveWriteDataToLocal(writeData, 'tx'); } console.log("Buffer to send:", new Uint8Array(buffer)); return await _writeBLECharacteristicValue(buffer); } // 新增:模拟 QString::toLatin1() 的行为 function stringToLatin1Bytes(str) { const bytes = []; for (let i = 0; i < str.length; i++) { const code = str.charCodeAt(i); // 获取 UTF-16 code unit // 检查是否在 Latin-1 范围内 (0-255) if (code >= 0 && code <= 255) { bytes.push(code); // 直接作为字节值 } else { // C++ QString::toLatin1() 对于超出范围的字符通常会变成 0 或 '?' (0x3F) // 这里我们选择 0x3F ('?') // 你需要根据 C++ 实际行为调整,可能是 0x00 bytes.push(0x3F); // 或者 bytes.push(0x00); } } return new Uint8Array(bytes); } const utf8BytesToStr = utf8Bytes => { let unicodeStr = '' for (let pos = 0; pos < utf8Bytes.length;) { let flag = utf8Bytes[pos] let unicode = 0 if (flag >>> 7 === 0) { unicodeStr += String.fromCharCode(utf8Bytes[pos]) pos += 1 } // else if ((flag & 0xFC) === 0xFC) { // unicode = (utf8Bytes[pos] & 0x3) << 30 // unicode |= (utf8Bytes[pos + 1] & 0x3F) << 24 // unicode |= (utf8Bytes[pos + 2] & 0x3F) << 18 // unicode |= (utf8Bytes[pos + 3] & 0x3F) << 12 // unicode |= (utf8Bytes[pos + 4] & 0x3F) << 6 // unicode |= (utf8Bytes[pos + 5] & 0x3F) // unicodeStr += String.fromCharCode(unicode) // pos += 6 // } // else if ((flag & 0xF8) === 0xF8) { // unicode = (utf8Bytes[pos] & 0x7) << 24 // unicode |= (utf8Bytes[pos + 1] & 0x3F) << 18 // unicode |= (utf8Bytes[pos + 2] & 0x3F) << 12 // unicode |= (utf8Bytes[pos + 3] & 0x3F) << 6 // unicode |= (utf8Bytes[pos + 4] & 0x3F) // unicodeStr += String.fromCharCode(unicode) // pos += 5 // } else if ((flag & 0xf0) === 0xf0) { unicode = (utf8Bytes[pos] & 0xf) << 18 unicode |= (utf8Bytes[pos + 1] & 0x3f) << 12 unicode |= (utf8Bytes[pos + 2] & 0x3f) << 6 unicode |= utf8Bytes[pos + 3] & 0x3f unicodeStr += String.fromCharCode(unicode) pos += 4 } else if ((flag & 0xe0) === 0xe0) { unicode = (utf8Bytes[pos] & 0x1f) << 12 unicode |= (utf8Bytes[pos + 1] & 0x3f) << 6 unicode |= utf8Bytes[pos + 2] & 0x3f unicodeStr += String.fromCharCode(unicode) pos += 3 } else if ((flag & 0xc0) === 0xc0) { //110 unicode = (utf8Bytes[pos] & 0x3f) << 6 unicode |= utf8Bytes[pos + 1] & 0x3f unicodeStr += String.fromCharCode(unicode) pos += 2 } else { unicodeStr += String.fromCharCode(utf8Bytes[pos]) pos += 1 } } return unicodeStr } const strToUtf8Bytes = str => { let bytes = [] for (let i = 0; i < str.length; ++i) { let code = str.charCodeAt(i) if (code >= 0x10000 && code <= 0x10ffff) { bytes.push((code >> 18) | 0xf0) // 第一个字节 bytes.push(((code >> 12) & 0x3f) | 0x80) bytes.push(((code >> 6) & 0x3f) | 0x80) bytes.push((code & 0x3f) | 0x80) } else if (code >= 0x800 && code <= 0xffff) { bytes.push((code >> 12) | 0xe0) bytes.push(((code >> 6) & 0x3f) | 0x80) bytes.push((code & 0x3f) | 0x80) } else if (code >= 0x80 && code <= 0x7ff) { bytes.push((code >> 6) | 0xc0) bytes.push((code & 0x3f) | 0x80) } else { bytes.push(code) } } return bytes } // 在文件顶部添加全局变量 let globalWriteLogs = [] let logListeners = [] // 保存数据到全局变量的函数(移除本地存储) const saveWriteDataToLocal = (data, type) => { try { const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, '0'); const day = String(now.getDate()).padStart(2, '0'); const hours = String(now.getHours()).padStart(2, '0'); const minutes = String(now.getMinutes()).padStart(2, '0'); const seconds = String(now.getSeconds()).padStart(2, '0'); // 创建日志条目 const logEntry = { time: `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`, data: data, type: type } // 添加到全局变量 globalWriteLogs.push(logEntry) // 限制全局日志数量为最近100条 if (globalWriteLogs.length > 100) { globalWriteLogs = globalWriteLogs.slice(-100) } // 通知所有监听器 notifyLogListeners() } catch (e) { } } // 添加获取全局日志的方法 const getGlobalWriteLogs = () => { return globalWriteLogs } // 添加清空全局日志的方法 const clearGlobalWriteLogs = () => { globalWriteLogs = [] notifyLogListeners() } // 添加监听器管理方法 const addLogListener = (callback) => { logListeners.push(callback) } const removeLogListener = (callback) => { const index = logListeners.indexOf(callback) if (index > -1) { logListeners.splice(index, 1) } } // 通知监听器 const notifyLogListeners = () => { logListeners.forEach(callback => { callback(globalWriteLogs) }) } // 根据类型删除日志的函数(仅操作全局变量) const removeWriteDataByType = (type) => { try { const originalLength = globalWriteLogs.length; // 过滤掉指定类型的日志 globalWriteLogs = globalWriteLogs.filter(log => log.type !== type) const deletedCount = originalLength - globalWriteLogs.length; // 通知所有监听器更新 notifyLogListeners() console.log(`已删除类型为 '${type}' 的日志,共删除 ${deletedCount} 条`); return { success: true, deletedCount: deletedCount } } catch (e) { console.error('删除写入数据失败:', e) return { success: false, error: e } } } // 清空所有日志的函数(仅操作全局变量) const clearAllWriteData = () => { try { globalWriteLogs = [] notifyLogListeners() console.log("已清空所有日志"); return { success: true } } catch (e) { console.error('清空所有日志失败:', e) return { success: false, error: e } } } // 获取特定类型的日志 const getWriteDataByType = (type) => { try { const filteredLogs = globalWriteLogs.filter(log => log.type === type) return filteredLogs } catch (e) { console.error('获取特定类型日志失败:', e) return [] } } // 获取所有日志(按时间倒序排列) const getAllWriteDataSorted = () => { try { // 创建副本避免修改原数组 let writeLogs = [...globalWriteLogs] // 按时间倒序排列(最新的在前面) writeLogs.sort((a, b) => { return new Date(b.time) - new Date(a.time); }); return writeLogs } catch (e) { console.error('获取排序日志失败:', e) return [] } } // 导出新增的方法 export default { onBluetoothAdapterStateChange, openBluetoothAdapter, onBluetoothDeviceFound, startBluetoothDevicesDiscovery, stopBluetoothDevicesDiscovery, onBLEConnectionStateChange, createBLEConnection, closeBLEConnection, onBLECharacteristicValueChange, writeBLECharacteristicValue, saveWriteDataToLocal, getGlobalWriteLogs, clearGlobalWriteLogs, addLogListener, removeLogListener, removeWriteDataByType, // 新增 clearAllWriteData, // 新增 getWriteDataByType, // 新增 getAllWriteDataSorted, // 新增 writeBLECharacteristicValueTwo }