尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

利用 Web Bluetooth API,让网页直接与您的 UT353BT 噪音计通信,读取其实时噪音数据,并转换为视频控制指令

利用 Web Bluetooth API,让网页直接与您的 UT353BT 噪音计通信,读取其实时噪音数据,并转换为视频控制指令 以下是利用 Web Bluetooth API 连接 UT353BT 噪音计并依据实时噪音数据控制网页视频播放的完整实现方案。一、技术可行性分析UT353BT 噪音计支持蓝牙 4.0 及以上版本可通过其官方 iENV APP 进行数据传输-。Web Bluetooth API 允许网页在 HTTPS 环境下直接与 BLE 设备通信无需安装原生 APP-。因此通过 H5 网页直接连接 UT353BT 并读取噪音数据在技术上是完全可行的。二、核心实现步骤整个流程分为五个关键步骤步骤操作说明1扫描并请求设备调用navigator.bluetooth.requestDevice()让用户选择 UT353BT2连接 GATT 服务器通过device.gatt.connect()建立连接3获取服务和特征值获取 UT353BT 的 GATT 服务及数据特征值4订阅数据通知开启特征值通知实时接收噪音数据5解析数据并控制视频将原始数据转换为分贝值动态调整视频音量/速度三、关于 UT353BT 的 GATT 协议重要提示UT353BT 的具体 Service UUID 和 Characteristic UUID 属于未公开的私有协议。你需要通过以下两种方式获取官方途径查阅 UT353BT 的用户手册或联系优利德UNI-T技术支持-。自行探测使用手机上的 BLE 调试工具如nRF Connect或LightBlue连接 UT353BT在服务列表中查找并记录相关 UUID。以下代码中的 UUID如your-service-uuid为占位符请务必替换为你从设备上获取的真实 UUID。四、完整代码实现1. 安装依赖npm install vueuse/core2. Vue 3 完整组件代码template div classnoise-controller !-- 连接区域 -- div classconnection-panel h3 UT353BT 噪音计控制/h3 button clickconnectDevice :disabledisConnecting || isConnected classbtn-connect {{ isConnected ? ✅ 已连接 : isConnecting ? ⏳ 连接中... : 连接噪音计 }} /button p v-ifdeviceName classdevice-info设备: {{ deviceName }}/p p classdb-display :style{ color: dbColor } 当前噪音: strong{{ currentDb }} dB/strong /p p v-iferror classerror❌ {{ error }}/p /div !-- 视频播放器 -- div classvideo-panel video refvideoRef width640 controls autoplay muted classvideo-player source :srcvideoUrl typevideo/mp4 / 您的浏览器不支持视频播放。 /video div classvideo-controls span 视频音量: {{ Math.round(videoVolume * 100) }}%/span span⏱ 播放速度: {{ playbackRate.toFixed(1) }}x/span /div /div /div /template script setup import { ref, computed, watch, onUnmounted } from vue; import { useBluetooth } from vueuse/core; // --- 视频相关 --- const videoRef ref(null); const videoUrl ref(YOUR_VIDEO_URL.mp4); // 替换为你的视频地址 const videoVolume ref(0.5); const playbackRate ref(1.0); // --- 蓝牙相关 --- const currentDb ref(0); const isConnecting ref(false); const deviceName ref(); let noiseCharacteristic null; let notificationListener null; // 使用 VueUse 的 useBluetooth 管理连接 const { isSupported, isConnected, device, requestDevice, server, error } useBluetooth({ acceptAllDevices: false, // ⚠️ 关键: 替换为从 UT353BT 获取的真实 Service UUID filters: [{ services: [your-service-uuid] }], optionalServices: [your-service-uuid], }); // 计算分贝对应的颜色 (绿→黄→红) const dbColor computed(() { if (currentDb.value 50) return #4caf50; if (currentDb.value 70) return #ff9800; return #f44336; }); // --- 连接设备 --- const connectDevice async () { if (isConnecting.value || isConnected.value) return; isConnecting.value true; try { // 1. 请求并连接设备 await requestDevice(); if (!server.value) throw new Error(无法获取 GATT 服务器); deviceName.value device.value?.name || UT353BT; // 2. 获取主服务 (替换为真实 Service UUID) const service await server.value.getPrimaryService(your-service-uuid); // 3. 获取数据特征值 (替换为真实 Characteristic UUID) noiseCharacteristic await service.getCharacteristic(your-characteristic-uuid); // 4. 读取一次当前值 await readNoiseData(); // 5. 订阅数据通知 (实时接收数据) await noiseCharacteristic.startNotifications(); notificationListener (event) { handleNoiseData(event.target.value); }; noiseCharacteristic.addEventListener( characteristicvaluechanged, notificationListener ); console.log(✅ UT353BT 连接成功开始监听噪音数据); } catch (err) { console.error(连接失败:, err); // 错误信息已由 useBluetooth 的 error 暴露 } finally { isConnecting.value false; } }; // --- 读取噪音数据 --- const readNoiseData async () { if (!noiseCharacteristic) return; const value await noiseCharacteristic.readValue(); handleNoiseData(value); }; // --- 解析噪音数据 (核心) --- const handleNoiseData (data) { // ⚠️ 关键: 根据 UT353BT 的实际数据格式解析 // 假设设备返回 2 个字节小端序数值 分贝 × 10 // 例如: 0x01F4 500 → 50.0 dB if (data.byteLength 2) { // 方式1: 读取 16 位无符号整数 (小端序) const rawValue data.getUint16(0, true); const dbValue rawValue / 10.0; // 限制在合理范围 (30~130dB) currentDb.value Math.min(130, Math.max(30, dbValue)); } else { // 如果数据是 ASCII 文本格式 (如 050.0) // 可使用 TextDecoder 解析 try { const decoder new TextDecoder(ascii); const text decoder.decode(data); const match text.match(/(\d\.?\d*)/); if (match) { currentDb.value parseFloat(match[1]); } } catch (e) { console.warn(解析数据失败:, data); } } }; // --- 根据噪音控制视频 --- watch(currentDb, (newDb) { if (!videoRef.value) return; // 映射规则: 30dB → 音量 0%, 130dB → 音量 100% const rawVolume (newDb - 30) / 100; videoVolume.value Math.min(1, Math.max(0, rawVolume)); videoRef.value.volume videoVolume.value; // 可选: 根据噪音控制播放速度 // 30dB → 0.5x, 130dB → 2.0x const rawRate 0.5 (newDb - 30) / 100; playbackRate.value Math.min(2.0, Math.max(0.5, rawRate)); videoRef.value.playbackRate playbackRate.value; }); // --- 清理资源 --- onUnmounted(() { if (noiseCharacteristic notificationListener) { noiseCharacteristic.removeEventListener( characteristicvaluechanged, notificationListener ); noiseCharacteristic.stopNotifications().catch(() {}); } if (device.value?.gatt) { device.value.gatt.disconnect(); } }); /script style scoped .noise-controller { display: flex; flex-direction: column; align-items: center; gap: 30px; padding: 30px; font-family: Arial, sans-serif; background: #f5f7fa; min-height: 100vh; } .connection-panel { background: white; padding: 25px 40px; border-radius: 16px; box-shadow: 0 4px 20px rgba(0,0,0,0.08); text-align: center; width: 100%; max-width: 500px; } .btn-connect { padding: 12px 40px; font-size: 18px; border: none; border-radius: 30px; background: #2563eb; color: white; cursor: pointer; transition: all 0.3s; } .btn-connect:hover:not(:disabled) { background: #1d4ed8; transform: scale(1.02); } .btn-connect:disabled { background: #94a3b8; cursor: not-allowed; } .db-display { font-size: 28px; margin: 15px 0 5px; } .device-info { color: #64748b; font-size: 14px; } .error { color: #ef4444; font-size: 14px; margin-top: 10px; } .video-panel { background: #0f172a; border-radius: 16px; padding: 20px; box-shadow: 0 8px 30px rgba(0,0,0,0.3); } .video-player { border-radius: 10px; max-width: 100%; background: #000; } .video-controls { display: flex; justify-content: space-between; color: #94a3b8; font-size: 14px; padding: 12px 6px 0; } /style五、关键注意事项事项说明浏览器兼容性Web Bluetooth API 目前仅在Chrome 56、Edge 79中支持良好Safari 和 Firefox 暂不支持-21HTTPS 要求API 必须在HTTPS或localhost环境下使用-21用户手势触发requestDevice()必须由用户点击等主动操作触发-21设备协议成功的关键在于获取 UT353BT 正确的 Service UUID、Characteristic UUID 及数据解析格式权限用户需手动允许网页访问蓝牙设备-21六、获取设备 UUID 的实用方法如果无法从官方获取 UT353BT 的 GATT 协议可以通过以下方式自行探测使用 nRF Connect 手机 APP扫描并连接 UT353BT查看服务列表记录所有 Service UUID逐个查看 Characteristic找到包含噪音数据的特征值开启 Notify观察数据变化在 Chrome 中调试打开chrome://bluetooth-internals/扫描并连接设备查看服务和特征值详情七、备选方案如果 Web Bluetooth API 的浏览器兼容性无法满足需求可考虑开发配套手机 APP使用 Flutter/React Native 开发跨平台 APP通过蓝牙读取数据后通过 WebSocket 或 MQTT 将数据推送给网页。使用 BLE 网关将 UT353BT 的数据通过蓝牙网关上传至云端网页通过 API 获取数据。
返回列表