You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React.tsx应用如何从COM端口获取数据?求实现方案

解决方案

首先纠正一个误解:serialport完全支持TypeScript,不需要额外适配TSX——它本身就包含了完整的类型定义,直接安装就能在React.tsx项目中使用。不过要注意:浏览器环境无法直接访问COM端口,因为这属于Node.js的系统级API,所以你需要根据项目形态选择两种方案之一:

方案一:用Electron打包成桌面应用(推荐本地直接访问串口)

如果你的项目是面向桌面端的,Electron可以让React.tsx应用拥有Node.js的系统权限,直接调用serialport读取串口数据:

  1. 初始化Electron+React+TS项目
    可以用现成模板快速搭建:

    npx create-react-app my-ship-app --template typescript
    cd my-ship-app
    npm install electron electron-builder --save-dev
    
  2. 安装serialport
    直接安装即可,TypeScript类型已内置:

    npm install serialport
    
  3. 主进程处理串口逻辑
    在Electron主进程(比如main.ts)中写串口读取代码,通过IPC通信把数据传给React渲染进程:

    import { app, BrowserWindow, ipcMain } from 'electron';
    import { SerialPort } from 'serialport';
    import { ReadlineParser } from '@serialport/parser-readline';
    
    let mainWindow: BrowserWindow | null;
    
    function createWindow() {
      mainWindow = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
          contextIsolation: true,
          preload: `${__dirname}/preload.js` // 用preload做安全的IPC桥接
        }
      });
    
      mainWindow.loadURL('http://localhost:3000');
    }
    
    app.whenReady().then(() => {
      createWindow();
    
      // 初始化串口连接(替换为你的COM端口和波特率)
      const port = new SerialPort({ path: 'COM3', baudRate: 9600 });
      const parser = port.pipe(new ReadlineParser({ delimiter: '\r\n' }));
    
      // 监听串口数据,发送给渲染进程
      parser.on('data', (rawData) => {
        const parsedData = parseNMEAData(rawData);
        ipcMain.emit('ship-data', parsedData);
      });
    });
    
    // 示例:解析NMEA 0183格式的船舶数据
    function parseNMEAData(raw: string) {
      const parts = raw.split(',');
      if (parts[0] === '$GPGGA') {
        return {
          latitude: parts[2],
          longitude: parts[4],
          altitude: parts[9]
        };
      }
      return null;
    }
    
  4. React组件接收数据并计算
    在preload脚本中暴露IPC接口,然后在React组件中监听数据:

    // preload.js
    const { contextBridge, ipcRenderer } = require('electron');
    contextBridge.exposeInMainWorld('electronAPI', {
      onShipData: (callback) => ipcRenderer.on('ship-data', callback)
    });
    
    // React组件(ShipData.tsx)
    import { useEffect, useState } from 'react';
    
    interface ShipData {
      latitude: string;
      longitude: string;
      altitude: string;
    }
    
    export default function ShipDataComponent() {
      const [data, setData] = useState<ShipData | null>(null);
      const [calculatedSpeed, setCalculatedSpeed] = useState<number>(0);
    
      useEffect(() => {
        const handleData = (_, parsedData: ShipData) => {
          setData(parsedData);
          // 添加船舶数据计算逻辑
          const speed = calculateShipSpeed(parsedData);
          setCalculatedSpeed(speed);
        };
    
        window.electronAPI.onShipData(handleData);
        return () => window.electronAPI.onShipData(handleData);
      }, []);
    
      // 示例计算逻辑
      function calculateShipSpeed(data: ShipData): number {
        // 根据实际需求实现,比如基于经纬度变化计算航速
        return 15.5; // 示例值
      }
    
      return (
        <div className="ship-data">
          <h2>船舶实时数据</h2>
          {data ? (
            <>
              <p>纬度: {data.latitude}</p>
              <p>经度: {data.longitude}</p>
              <p>计算航速: {calculatedSpeed} 节</p>
            </>
          ) : (
            <p>等待串口数据...</p>
          )}
        </div>
      );
    }
    

方案二:Node.js后端中转(适合Web端应用)

如果你的项目是Web端,无法直接访问本地串口,可以搭建一个Node.js后端,用serialport读取数据后通过API/WebSocket推送给React前端:

  1. 搭建Node.js后端

    mkdir ship-data-server && cd ship-data-server
    npm init -y
    npm install serialport express ws
    
  2. 后端代码示例(server.ts)

    import express from 'express';
    import WebSocket from 'ws';
    import { SerialPort } from 'serialport';
    import { ReadlineParser } from '@serialport/parser-readline';
    
    const app = express();
    const server = app.listen(3001, () => console.log('后端运行在3001端口'));
    const wss = new WebSocket.Server({ server });
    
    const port = new SerialPort({ path: 'COM3', baudRate: 9600 });
    const parser = port.pipe(new ReadlineParser({ delimiter: '\r\n' }));
    
    parser.on('data', (rawData) => {
      const parsedData = parseNMEAData(rawData);
      // 通过WebSocket推送给所有连接的前端
      wss.clients.forEach(client => {
        if (client.readyState === WebSocket.OPEN) {
          client.send(JSON.stringify(parsedData));
        }
      });
    });
    
    function parseNMEAData(raw: string) {
      const parts = raw.split(',');
      return parts[0] === '$GPGGA' ? {
        latitude: parts[2],
        longitude: parts[4]
      } : null;
    }
    
  3. React前端连接后端

    // React组件
    import { useEffect, useState } from 'react';
    
    interface ShipData {
      latitude: string;
      longitude: string;
    }
    
    export default function ShipWebComponent() {
      const [data, setData] = useState<ShipData | null>(null);
    
      useEffect(() => {
        const ws = new WebSocket('ws://localhost:3001');
        ws.onmessage = (event) => {
          const parsedData = JSON.parse(event.data);
          if (parsedData) {
            setData(parsedData);
            // 执行计算逻辑
            const result = computeShipMetrics(parsedData);
            console.log(result);
          }
        };
    
        return () => ws.close();
      }, []);
    
      function computeShipMetrics(data: ShipData) {
        // 你的计算逻辑
        return { distance: 100 };
      }
    
      return (
        <div>
          {data ? (
            <>
              <p>纬度: {data.latitude}</p>
              <p>经度: {data.longitude}</p>
            </>
          ) : (
            <p>连接后端中...</p>
          )}
        </div>
      );
    }
    

关键注意事项

  • 串口路径(如COM3)和波特率必须与船舶设备的配置一致
  • 船舶数据通常遵循NMEA 0183协议,需要根据具体报文格式编写解析逻辑
  • 用Electron时,务必通过preload脚本做IPC桥接,避免直接开启nodeIntegration带来的安全风险

内容的提问来源于stack exchange,提问作者Dylan Lucas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 05:50:29