0

0

如何用Web Serial实现传感器数据的实时采集与可视化?

betcha

betcha

发布时间:2025-09-17 08:42:01

|

572人浏览过

|

来源于php中文网

原创

Web Serial API使浏览器能直接与串口设备通信,实现传感器数据的实时采集与可视化。通过前端应用调用API连接设备,读取格式化数据(如JSON或CSV),并利用Chart.js等库动态更新图表,相比传统方案具备零安装、低延迟、跨平台、易部署等优势。但需注意浏览器兼容性(仅Chromium系支持)、用户手动授权、数据解析容错、断线重连及高频数据带来的性能压力。为提升体验,可采用数据节流、批处理更新、Web Workers分担解析任务,并选用高效图表库优化渲染。整体上,该技术让Web应用突破沙盒限制,成为连接物理世界的交互中心。

如何用web serial实现传感器数据的实时采集与可视化?

Web Serial API的出现,为浏览器直接与串口设备交互打开了一扇门,这意味着我们可以在不依赖任何桌面应用或中间件的情况下,直接在网页上实现传感器数据的实时采集、处理与可视化。这不仅极大地简化了开发和部署流程,也为物联网(IoT)前端应用带来了前所未有的灵活性和用户体验。简单来说,它让你的浏览器能够“听懂”并“展示”来自物理世界的数据。

解决方案

要实现Web Serial实时采集与可视化,核心在于构建一个前端应用,通过Web Serial API与串口设备(如连接了传感器的微控制器)建立通信,接收数据,然后利用前端图表库进行动态展示。

  1. 设备端固件准备:

    • 确保你的微控制器(例如Arduino、ESP32、树莓派Pico等)已连接传感器,并能稳定读取数据。

    • 编写固件代码,通过串口(UART)周期性地发送传感器数据。为了方便前端解析,建议将数据格式化,例如使用JSON字符串或逗号分隔的值(CSV),并以换行符(

      \n
      )作为数据包的分隔符。

      // 示例:Arduino伪代码
      #include  // 如果使用JSON
      
      void setup() {
        Serial.begin(115200); // 设置波特率
      }
      
      void loop() {
        float temperature = readTemperatureSensor(); // 假设有函数读取温度
        float humidity = readHumiditySensor();     // 假设有函数读取湿度
      
        // 使用JSON格式发送
        StaticJsonDocument<64> doc;
        doc["temp"] = temperature;
        doc["hum"] = humidity;
        serializeJson(doc, Serial);
        Serial.println(); // 添加换行符作为数据包结束标志
      
        delay(1000); // 每秒发送一次
      }
  2. Web前端应用构建:

    • 请求并打开串口: 用户需要通过交互(例如点击按钮)来授权网页访问串口。

      async function connectSerial() {
        try {
          const port = await navigator.serial.requestPort();
          await port.open({ baudRate: 115200 }); // 波特率需与设备端匹配
          console.log('串口已连接!');
          readSerialData(port); // 开始读取数据
          return port;
        } catch (error) {
          console.error('连接串口失败:', error);
          alert('连接串口失败,请确保设备已连接且未被占用。');
        }
      }
    • 读取数据: 使用

      ReadableStreamDefaultReader
      循环读取串口数据。由于串口数据是字节流,需要将其解码为字符串,并根据约定好的分隔符解析出完整的数据包。

      let serialPort;
      let reader;
      let inputDone;
      let outputDone;
      let inputStream;
      let outputStream;
      let textDecoder = new TextDecoder();
      let receivedDataBuffer = ''; // 用于缓存不完整的数据包
      
      async function readSerialData(port) {
        serialPort = port;
        inputStream = port.readable;
        reader = inputStream.getReader();
        inputDone = new Promise(resolve => (reader.closed = resolve));
      
        while (true) {
          const { value, done } = await reader.read();
          if (done) {
            console.log('读取器已关闭。');
            break;
          }
          // 解码字节流为字符串
          receivedDataBuffer += textDecoder.decode(value, { stream: true });
      
          // 根据换行符分割数据包
          let lines = receivedDataBuffer.split('\n');
          receivedDataBuffer = lines.pop(); // 最后一个可能不完整,放回缓存
      
          lines.forEach(line => {
            if (line.trim() === '') return; // 忽略空行
            try {
              const data = JSON.parse(line); // 假设是JSON格式
              console.log('接收到数据:', data);
              updateVisualization(data); // 更新可视化
            } catch (e) {
              console.error('解析数据失败:', e, '原始数据:', line);
            }
          });
        }
      }
    • 数据可视化: 选用一个前端图表库(如Chart.js、ECharts、D3.js等),根据接收到的数据动态更新图表。

      // 示例:使用Chart.js
      let myChart; // 定义全局变量以便更新
      
      function initializeChart() {
        const ctx = document.getElementById('sensorChart').getContext('2d');
        myChart = new Chart(ctx, {
          type: 'line',
          data: {
            labels: [], // 时间戳或序号
            datasets: [{
              label: '温度 (°C)',
              data: [],
              borderColor: 'rgb(255, 99, 132)',
              tension: 0.1
            }, {
              label: '湿度 (%)',
              data: [],
              borderColor: 'rgb(54, 162, 235)',
              tension: 0.1
            }]
          },
          options: {
            animation: false, // 实时数据通常不需要动画
            scales: {
              x: {
                type: 'time', // 如果标签是时间戳
                time: {
                  unit: 'second'
                }
              },
              y: {
                beginAtZero: false
              }
            }
          }
        });
      }
      
      function updateVisualization(newData) {
        if (!myChart) {
          initializeChart();
        }
      
        const now = Date.now();
        // 限制图表显示的数据点数量,避免内存和性能问题
        const maxDataPoints = 60;
      
        myChart.data.labels.push(now);
        myChart.data.datasets[0].data.push({ x: now, y: newData.temp });
        myChart.data.datasets[1].data.push({ x: now, y: newData.hum });
      
        if (myChart.data.labels.length > maxDataPoints) {
          myChart.data.labels.shift();
          myChart.data.datasets[0].data.shift();
          myChart.data.datasets[1].data.shift();
        }
        myChart.update();
      }
      
      // 页面加载时调用
      document.addEventListener('DOMContentLoaded', () => {
        initializeChart();
        document.getElementById('connectButton').addEventListener('click', connectSerial);
      });

为什么选择Web Serial API,它比传统方案好在哪里?

Web Serial API的出现,确实像一道光,照亮了浏览器与硬件交互的全新路径。在此之前,如果你想在网页上直接控制或读取串口设备,那几乎是个不可能完成的任务,或者说,需要各种“曲线救国”的方案。

传统上,我们可能会选择:

  • 桌面应用: 使用Electron、Qt、C# WinForms或Python Tkinter等框架开发桌面应用。这固然能提供强大的硬件访问能力,但代价是用户必须下载、安装、更新应用,而且每个操作系统版本都需要单独维护,部署和分发都比较麻烦。
  • 云端方案: 传感器数据先上传到云端服务器(通过MQTT、HTTP等协议),再由Web应用从云端获取。这种方案虽然实现了Web端可视化,但引入了网络延迟,需要搭建和维护后端服务,成本和复杂度都增加了,对于本地化、低延迟的应用场景并不理想。
  • 浏览器插件/扩展: 过去一些尝试通过浏览器插件来扩展硬件访问能力,但插件的开发、审核和兼容性问题一直是个痛点,且安全性受限。

Web Serial API的优势则非常明显,它几乎完美地弥补了上述方案的短板:

  • 零安装、跨平台: 你的应用就是一个网页,用户只需用支持的浏览器打开即可。无需安装任何软件,自然就实现了跨操作系统兼容性(只要浏览器支持)。这对于用户体验来说,简直是质的飞跃。
  • 直接、低延迟: 数据直接从设备流向浏览器,没有中间服务器的转发,延迟极低,真正实现了“实时”。这对于需要快速响应和精确控制的场景至关重要。
  • 充分利用Web生态: 你可以尽情发挥前端技术的优势,利用各种成熟的JavaScript库进行数据处理、复杂的交互设计和炫酷的可视化。Web前端的开发效率和生态丰富度是其他方案难以比拟的。
  • 简化部署: 你的应用就是一个静态网页,可以部署在任何Web服务器上,甚至通过GitHub Pages等免费服务托管。部署成本几乎为零。

对我个人而言,Web Serial最吸引人的地方在于它打破了Web应用的“沙盒”限制,让浏览器不再仅仅是一个信息消费者,而能真正成为一个与物理世界深度互动的控制中心。这种直接感和便利性,是任何其他方案都无法比拟的。

站长俱乐部购物系统
站长俱乐部购物系统

功能介绍:1、模块化的程序设计,使得前台页面设计与程序设计几乎完全分离。在前台页面采用过程调用方法。在修改页面设计时只需要在相应位置调用设计好的过程就可以了。另外,这些过程还提供了不同的调用参数,以实现不同的效果;2、阅读等级功能,可以加密产品,进行收费管理;3、可以完全可视化编辑文章内容,所见即所得;4、无组件上传文件,服务器无需安装任何上传组件,无需支持FSO,即可上传文件。可限制文件上传的类

下载

在实际开发中,Web Serial API有哪些常见的坑和挑战?

Web Serial API虽然强大,但在实际开发中,也确实会遇到一些让人挠头的问题。我个人在尝试的时候,就踩过不少坑,有些是API本身的限制,有些则是开发习惯的转变。

  1. 浏览器兼容性: 这是最主要的限制。目前Web Serial API主要在基于Chromium的浏览器(如Chrome、Edge、Opera等)中得到良好支持。Firefox和Safari等其他浏览器家族尚未实现,这意味着你的应用无法在这些浏览器上运行。在项目初期,必须明确目标用户使用的浏览器环境。
  2. 用户授权流程: 出于安全考虑,每次连接串口都需要用户手动选择并授权。这对于开发者来说,意味着你不能在页面加载时自动连接,必须有一个用户交互(比如点击按钮)。而且,如果页面刷新或关闭再打开,用户可能需要重新授权。虽然这是必要的安全措施,但对于追求无缝体验的应用来说,确实有点烦人。
  3. 数据格式与解析: 设备端发送的数据格式必须与Web端解析逻辑严格匹配。如果设备发送的数据不规范(比如缺少换行符、数据包不完整),Web端解析时就很容易出错。我遇到过因为设备端偶然发送空数据或者数据包被截断,导致前端
    JSON.parse
    报错,整个数据流中断的问题。前端需要一个健壮的缓冲区和解析逻辑来处理这些“脏数据”。
  4. 错误处理与断线重连: 串口连接并不总是稳定的,设备可能意外断开,或者端口被其他应用占用。Web Serial API的错误事件和状态管理需要细致处理。例如,如何优雅地处理
    port.close()
    ,如何检测断开并尝试自动重连,这些都需要精心设计。如果处理不好,用户体验会非常糟糕。
  5. 性能瓶颈: 当传感器数据量非常大(例如每秒几百上千个数据点)时,频繁地更新DOM或图表可能会导致浏览器主线程卡顿,页面不流畅。这时就需要考虑数据节流、批处理更新、甚至使用Web Workers来处理数据解析,将UI更新与数据处理分离。
  6. 调试困难: 调试串口通信本身就比调试HTTP请求更复杂。你可能需要借助串口调试工具(如
    screen
    ,
    minicom
    或各种GUI串口助手)来验证设备端发送的数据是否正确,再回到浏览器开发者工具中调试Web端的接收和解析逻辑。
  7. 安全模型: 虽然有用户授权,但直接访问硬件接口仍然是一个敏感操作。开发者需要确保自己的Web应用没有安全漏洞,避免恶意利用Web Serial API。

这些挑战并非不可逾越,但它们确实要求开发者在设计和实现时更加严谨和周全。了解这些“坑”能帮助我们提前规避风险,构建更稳定、更健壮的应用。

如何优化Web Serial数据流,提升可视化性能和用户体验?

在Web Serial数据流的场景中,性能和用户体验是两个核心关注点。毕竟,我们希望看到的是流畅、响应迅速的实时数据,而不是卡顿的页面和混乱的图表。我个人在处理高频数据时,有一些心得,主要围绕着“如何高效处理数据”和“如何优雅呈现数据”展开。

  1. 数据采样与节流:

    • 不是所有数据都需要展示: 如果你的传感器以100Hz的频率发送数据,但人眼或图表根本无法区分每10毫秒的变化,那么就没有必要将所有数据点都渲染出来。
    • 前端采样: 在Web端接收到数据后,可以每隔N个数据点才更新一次图表,或者每隔固定时间(例如200ms)才处理一次最新的数据。
    • 设备端采样: 更进一步,如果设备端本身数据量就非常大,可以考虑在微控制器层面就进行数据采样或平均处理,减少通过串口发送的数据量。这能有效减轻串口通信和前端解析的压力。
  2. 批处理更新:

    • 与其每接收到一个数据点就立即更新一次图表(这可能导致频繁的DOM操作或Canvas重绘),不如将短时间内接收到的多个数据点缓存起来,然后一次性更新图表。
    • 例如,你可以设置一个定时器,每隔100-200毫秒,将在这段时间内收集到的所有新数据点添加到图表中,然后调用图表库的
      update()
      方法。这可以显著减少渲染开销。
  3. 利用Web Workers处理数据:

    • JavaScript是单线程的,所有的UI更新、事件处理和数据计算都在主线程上进行。当数据解析、格式转换或复杂计算变得繁重时,主线程就容易被阻塞,导致页面卡顿。
    • 将这些计算密集型任务放到Web Worker中执行。Web Worker在后台线程运行,不会阻塞主线程。它可以在接收到原始字节流后,在后台完成解码、JSON解析、数据结构转换等操作,然后将处理好的数据通过
      postMessage
      发送回主线程,主线程只负责接收并更新UI。
    • 这样,即使有大量数据涌入,UI也能保持流畅响应。
  4. 选择高效的图表库和渲染方式:

    • 不同的图表库有不同的性能特点。对于高频实时数据,通常Canvas-based的图表库(如Chart.js、ECharts、Plotly.js)在性能上会优于SVG-based的图表库(如D3.js在复杂场景下可能需要更多优化)。
    • 有些库还提供专门的实时数据模式增量更新功能,可以避免每次更新都重新绘制整个图表,只更新变化的部分。
    • 考虑使用一些轻量级的图表库,或者只导入你需要的功能模块,减少不必要的开销。
  5. 提供清晰的UI反馈和错误提示:

    • 连接状态: 在连接、断开、接收数据时,给用户清晰的视觉反馈(例如按钮状态变化、连接状态指示灯、文本提示)。
    • 错误信息: 当出现连接失败、数据解析错误等问题时,提供具体、易懂的错误信息,而不是一个抽象的“出错了”。例如:“连接失败:端口可能已被占用,请检查并重试。”
    • 数据有效性: 如果数据超出预期范围,可以在UI上高亮显示或发出警告。
  6. 实现健壮的断线重连机制:

    • 意外断开是常有的事。在检测到串口断开后,可以尝试在一定延迟后自动重连,或者提供一个“重新连接”按钮。
    • 在重连过程中,显示适当的加载或尝试连接状态,避免用户以为应用卡死。
  7. 数据缓存与历史记录:

    • 实时图表通常只显示最近一段时间的数据。但用户可能需要查看更长时间的历史数据。可以在前端维护一个更大的数据缓存,当用户需要时,再从缓存中渲染历史图表或提供数据导出功能。

这些优化措施并非孤立,而是相互配合,共同提升Web Serial应用的整体性能和用户体验。很多时候,与其追求极致的数据量,不如思考用户真正需要什么,然后有策略地呈现。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
视频后缀名都有哪些
视频后缀名都有哪些

视频后缀名都有avi、mpg、mpeg、rm、rmvb、flv、wmv、mov、mkv、ASF、M1V、M2V、MPE、QT、VOB、RA、RMJ、RMS、RAM、等等。更多关于视频后缀名的相关知识,详情请看本专题下面的文章,php中文网欢迎大家前来学习。

3532

2023.10.31

C++ Qt图形开发
C++ Qt图形开发

本专题专注于 C++ Qt框架在图形界面开发中的应用,系统讲解窗口设计、信号与槽机制、界面布局、事件处理、数据库连接与跨平台打包等核心技能,通过多个桌面应用项目实战,帮助学员快速掌握 Qt 框架并独立完成跨平台GUI软件的开发。

68

2025.08.15

C++ 图形界面开发基础(Qt方向)
C++ 图形界面开发基础(Qt方向)

本专题系统讲解 使用 C++ 与 Qt 进行图形界面(GUI)开发的核心技能,内容涵盖 Qt 项目结构、窗口组件、信号与槽机制、事件处理、布局管理、资源管理,以及跨平台编译与打包流程。通过多个小型桌面应用实战案例,帮助学习者掌握从界面设计到功能实现的完整 GUI 开发能力。

76

2025.12.05

什么是中间件
什么是中间件

中间件是一种软件组件,充当不兼容组件之间的桥梁,提供额外服务,例如集成异构系统、提供常用服务、提高应用程序性能,以及简化应用程序开发。想了解更多中间件的相关内容,可以阅读本专题下面的文章。

178

2024.05.11

Golang 中间件开发与微服务架构
Golang 中间件开发与微服务架构

本专题系统讲解 Golang 在微服务架构中的中间件开发,包括日志处理、限流与熔断、认证与授权、服务监控、API 网关设计等常见中间件功能的实现。通过实战项目,帮助开发者理解如何使用 Go 编写高效、可扩展的中间件组件,并在微服务环境中进行灵活部署与管理。

215

2025.12.18

json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

419

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

535

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

311

2023.10.13

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
XML教程
XML教程

共142课时 | 5.9万人学习

Java 教程
Java 教程

共578课时 | 52.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号