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

如何使用Angular 14(TypeScript)从串口读取Arduino RFID设备数据?

实现Angular 14读取Arduino串口RFID数据的方案

核心逻辑

浏览器无法直接访问本地串口,需借助Web Serial API(仅支持Chromium内核浏览器),通过Angular服务封装串口连接、数据读取逻辑,实现接收Arduino返回的RFID UID。

步骤1:封装串口操作服务

创建全局服务统一管理串口生命周期与数据流转:

// serial.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class SerialService {
  private port: SerialPort | null = null;
  private reader: ReadableStreamDefaultReader | null = null;
  public uidData$ = new Subject<string>();

  // 请求用户选择Arduino对应的串口
  async requestPort(): Promise<void> {
    try {
      this.port = await navigator.serial.requestPort();
      await this.port.open({ baudRate: 9600 }); // 匹配Arduino设置的波特率
      this.startReading();
    } catch (error) {
      console.error('串口连接失败:', error);
    }
  }

  // 持续读取串口数据
  private async startReading(): Promise<void> {
    if (!this.port) return;

    const textDecoder = new TextDecoderStream();
    const readableStreamClosed = this.port.readable?.pipeTo(textDecoder.writable);
    const reader = textDecoder.readable.getReader();

    this.reader = reader;

    while (true) {
      try {
        const { value, done } = await reader.read();
        if (done) {
          console.log('读取流已关闭');
          reader.releaseLock();
          break;
        }
        // 过滤空行,提取有效UID(Arduino需用Serial.println输出UID)
        const uid = value.trim();
        if (uid) this.uidData$.next(uid);
      } catch (error) {
        console.error('读取数据出错:', error);
        break;
      }
    }

    await readableStreamClosed;
  }

  // 关闭串口连接
  async closePort(): Promise<void> {
    if (this.reader) {
      await this.reader.cancel();
      this.reader.releaseLock();
    }
    if (this.port) {
      await this.port.close();
      this.port = null;
    }
  }
}

步骤2:组件中调用服务实现UI交互

创建组件触发串口连接、展示读取到的UID:

// rfid-reader.component.ts
import { Component, OnDestroy, OnInit } from '@angular/core';
import { SerialService } from './serial.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-rfid-reader',
  template: `
    <button (click)="connectSerial()" [disabled]="isConnected">连接串口</button>
    <button (click)="disconnectSerial()" [disabled]="!isConnected">断开连接</button>
    <div *ngIf="latestUid">读取到的UID: <strong>{{ latestUid }}</strong></div>
  `
})
export class RfidReaderComponent implements OnInit, OnDestroy {
  latestUid: string | null = null;
  isConnected = false;
  private uidSubscription: Subscription | null = null;

  constructor(private serialService: SerialService) {}

  ngOnInit(): void {
    // 订阅UID数据更新
    this.uidSubscription = this.serialService.uidData$.subscribe(uid => {
      this.latestUid = uid;
      // 此处可添加业务逻辑,如将UID提交至后端
    });
  }

  async connectSerial(): Promise<void> {
    await this.serialService.requestPort();
    this.isConnected = true;
  }

  async disconnectSerial(): Promise<void> {
    await this.serialService.closePort();
    this.isConnected = false;
    this.latestUid = null;
  }

  ngOnDestroy(): void {
    this.uidSubscription?.unsubscribe();
    this.serialService.closePort();
  }
}

关键注意事项

  • 浏览器限制:Web Serial API仅支持Chrome、Edge等Chromium内核浏览器,Firefox、Safari暂不兼容。
  • Arduino配置:需确保Arduino代码使用Serial.println(uid)输出UID,保证每条数据以换行符结尾,方便前端解析。
  • 权限要求:必须通过用户交互(如点击按钮)触发串口请求,浏览器不允许页面加载时自动访问串口。
  • 波特率匹配:前端设置的波特率需与Arduino代码中Serial.begin(XXX)的参数完全一致,否则会读取到乱码。

内容的提问来源于stack exchange,提问作者Nadeesh Hirushan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 10:24:46