Node.js中SerialPort(串口)模块使用

目录
  • 目的
  • 模块安装
    • 基础使用
    • 扫描端口
    • 打开端口
    • 发送数据
    • 接收数据
    • 错误处理
  • 数据解析器
  • SerialPort类
    • 构造方法
    • 属性
    • 事件
    • 方法
  • 命令行工具
  • 总结

目的

上位机与各种电路模块间常常采用串口进行通讯,Node.js中可以使用SerialPort模块操作串口,这篇文章将对其使用进行简单说明。

官网:https://serialport.io/
文档:https://serialport.io/docs/
项目地址:https://github.com/serialport/node-serialport

目前SerialPort模块版本为 9.2.7

模块安装

使用下面命令就可以安装SerialPort模块:

npm install serialport

SerialPort模块功能中有部分是用C/C++实现的,所以不同的平台需要该平台可用的二进制文件才能运行,对于常见的平台通常会有预编译好的二进制文件。如果没有的话通常会尝试使用 node-gyp (依赖Python 3.x)进行编译,通常包管理器会自动处理相关事务:

有时候或是有些平台下可能需要手动编译。对于编译而言需要平台上有相应的编译工具,可以参考 《Node.js入门 02:包管理器npm》 这个文章中的模块编译章节。

安装了编译工具后可以重新安装SerialPort模块或者手动进行编译处理,具体内容可以参考SerialPort模块文档中 Installing SerialPort 章节:https://serialport.io/docs/guide-installation/

基础使用

安装SerialPort模块后可以使用 const SerialPort = require('serialport') 方式导入。

扫描端口

使用 SerialPort.list(): Promise<PortInfo[]> 静态方法可以获取设备上的串口列表,比如下面演示:

const SerialPort = require('serialport');

SerialPort.list().then((ports) => {
    console.log(ports); // 打印串口列表
}).catch((err) => {
    console.log(err);
});

需要注意的是同一个端口在这个列表中有可能会重复出现。

也可以使用 async / await 方式使用上面方法:

const SerialPort = require('serialport');

(async () => {
    try {
        let ports = await SerialPort.list();
        console.log(ports); // 打印串口列表
    } catch (error) {
        console.log(error);
    }
})();

打开端口

默认情况下创建 SerialPort 对象就会打开端口,比如下面这样:

const SerialPort = require('serialport');

const port = new SerialPort('COM6', (err) => {
    if (err) {
        console.log('端口打开失败!');
        return;
    }
    console.log('端口打开成功!');
});

SerialPort类的构造方法中有一个 autoOpen 选项用于控制创建对象是是否自动打开端口,默认为自动打开,也可以将它关闭,这样可以后面手动进行打开端口动作:

const SerialPort = require('serialport');

const port = new SerialPort('COM6', { autoOpen: false });

port.open(function (err) {
    if (err) {
        console.log('端口打开失败!');
        return;
    }
    console.log('端口打开成功!');
});

SerialPort类的构造方法中可以使用 baudRate 选项设置串口通讯波特率,默认为9600:

const SerialPort = require('serialport');

const port = new SerialPort('COM6', { baudRate: 115200 }); // 设置波特率为115200

更多内容可以参考下面章节SerialPort类的构造方法说明。

发送数据

可以使用SerialPort对象的 write 方法发送数据,该方法会将要发送的数据放入发送缓存,然后依次发送,比如下面这样:

const SerialPort = require('serialport');
const port = new SerialPort('COM6');

port.write('Hello world!\n'); // 发送字符串
port.write(Buffer.from('Hey!\n')); // 发送Buffer数据
port.write(new Uint8Array([0x48, 0x69, 0x21, 0x0A])); // 发送字节数组

write 方法也可以添加回调函数:

const SerialPort = require('serialport');
const port = new SerialPort('COM6');

port.write('Hello world!\n', (err) => {
    if (err) {
        console.log('write操作失败!');
        return;
    }
    console.log('write操作成功!');
});

需要注意的是上面的回调函数非异常状态下触发的时候只是表示 write 方法本身操作完成,并不代表数据完全从端口发送完成,可以使用 drain 方法来处理,该方法会阻塞直到发送完成:

const SerialPort = require('serialport');
const port = new SerialPort('COM6');

port.write('Hello world!\n');
port.drain(err => {
    if (err) return;
    console.log('发送完成!');
});

接收数据

可以使用下面方式接收数据:

const SerialPort = require('serialport');
const port = new SerialPort('COM6');

// 以 paused mode 监听收到的数据,需要主动读取数据
port.on('readable', () => {
    console.log(port.read()); // 使用read方法读取数据,可以指定读取字节数
});

// 以 flowing mode 监听收到的数据
port.on('data', (data) => {
    console.log(data);
});

除了上面方式外,也可以使用 pipe 将数据传送到另一个流。

错误处理

SerialPort对象大多数操作都有回调函数,回调函数中的第一个参数都是异常对象。另外也可以通过 error 事件来统一处理异常:

const SerialPort = require('serialport');
const port = new SerialPort('COM6');

port.on('error', err => {
    console.log(err);
});

数据解析器

SerialPort模块中准备了一些数据解析器,主要用来处理收到的一些一些常见形式的串口数据,主要提供的功能如下:

ByteLength Parser
以收到的数据长度为单位进行解析:

const SerialPort = require('serialport');
const port = new SerialPort('COM6');

const ByteLength = require('@serialport/parser-byte-length');
const parser = port.pipe(new ByteLength({ length: 8 })); // 每收到8个字节触发
parser.on('data', chunk => {
    console.log(chunk); // 打印收到的数据
});

ccTalk Parser
解析 ccTalk 格式数据,格式详见:https://en.wikipedia.org/wiki/CcTalk

Delimiter Parser
以指定字符为界限处理数据:

const SerialPort = require('serialport');
const port = new SerialPort('COM6');

const Delimiter = require('@serialport/parser-delimiter');
const parser = port.pipe(new Delimiter({ delimiter: '\n' })); // 以 \n 分隔处理数据
parser.on('data', chunk => {
    console.log(chunk.toString()); // 打印收到的数据
});

delimiter选项可以是 string|Buffer|number[] ;includeDelimiter选项表示数据中是否包含分隔符,默认不包含。

InterByteTimeout Parser
指定时间未收到数据触发解析:

const SerialPort = require('serialport');
const port = new SerialPort('COM6');

const InterByteTimeout = require('@serialport/parser-inter-byte-timeout');
const parser = port.pipe(new InterByteTimeout({interval: 2000})); // 2000毫秒未接到数据触发
parser.on('data', chunk => {
    console.log(chunk); // 打印收到的数据
});

maxBufferSize选项用于指定接收到该数量数据后就算没有超时也将触发动作。

Readline Parser
以行为单位解析数据,默认行分隔符为 \n,可以使用 delimiter 选项重新设置为其它的,比如 \r\n

Ready Parser
以开始标志进行解析。

Regex Parser
以正则表达式为分隔进行解析。

SerialPort类

使用SerialPort模块主要就是使用SerialPort类,其介绍在SerialPort模块文档中 Stream Interface 章节:https://serialport.io/docs/api-stream,这里稍微摘录下其中部分内容。

构造方法

new SerialPort(path [, openOptions] [, openCallback])

构造方法用于创建一个串口对象,path为串口号,openCallback为自动打开失败时的回调函数;

openOptions常用选项如下:

选项 类型 说明 默认值
autoOpen boolean 自动打开端口 true
baudRate number 波特率 9600
dataBits number 数据位,可选值:8、7、6、5 8
highWaterMark number 读和写缓存大小 65536
lock boolean 锁定端口,防止其它平台打开(Windows上不支持false) true
stopBits number 停止位,可选值:1、2 1
parity string 校验,可选值:none、even、mark、odd、space none
rtscts boolean 流控制设置 false
xon boolean 流控制设置 false
xoff boolean 流控制设置 false
xany boolean 流控制设置 false

属性

SerialPort有下面几个属性可读:
pathbaudRateisOpenbinding

事件

SerialPort会触发的事件有下面几个:

  • open 端口打开时触发;
  • error 发送错误时触发;
  • close 端口关闭时触发;
  • data 收到数据时触发;
  • drain 如果write方法返回false,则再次调用write方法时将触发该事件;

方法

SerialPort可用的一些方法如下:

  • open(() => {}): void 打开端口;
  • update(options: updateOptions, callback?: err => {}): void 更改波特率;
  • write(data: string|Buffer|Array<number>, encoding?: string, callback?: error => {}): boolean 发送数据;
  • read(size?: number): string|Buffer|null 读取数据;
  • close(callback?: error => {}): void 关闭端口;
  • set(options: setOptions, callback?: error => {}): void 设置流控制;
  • get(callback: (error, data: ModemStatus) => {}): void 获取已打开端口的流控制状态;
  • flush(callback? error => {}):void 清空接收和发送缓存中未处理数据;
  • drain(callback? error => {}):void 等待数据发送完成;
  • pause(): this 暂停 flowing mode 触发data事件,转为 paused mode;
  • resume(): this 恢复 data 事件,从 paused mode 转为 flowing mode;

命令行工具

SerialPort模块也提供了一些命令行工具,用于直接在命令行界面中使用。下面是官网首页的使用演示:

更多内容可以参考SerialPort模块文档中 Command Line Tools 章节:https://serialport.io/docs/guide-cli

总结

Node.js的SerialPort模块使用主要就是上面一些内容了。

另外需要提一点的是SerialPort模块并不是直接操作串口,而是调用了各个平台上底层的接口来使用串口,如果有进行相关内容的开发或是有特殊需求的话可以参考SerialPort模块文档中Binding相关内容。

到此这篇关于Node.js中SerialPort(串口)模块使用的文章就介绍到这了,更多相关Node.js SerialPort内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解nodejs内置模块

    概述 nodejs内置模块指的是除默认提供的语法之外,提供的美容,无需下载,直接引入,引入只写名称即可. nodejs内置模块: 1.path模块  用于处理文件路径. path.normalize(路径解析,得到规范路径): path.join(路径合并): path.resolve(获取绝对路径): path.relative(获取相对路径). ...... 2.until模块  弥补js功能不足,新增API. util.format(格式化输出字符串); util.isArray(检查是否

  • Node.js中的模块化,npm包管理器详解

    目录 模块化的基本概念 什么是模块化 模块化拆分的好处 Node.js中的模块化 Node.js中模块的分类 加载模块 模块作用域 向外共享模块作用域中的成员 module对象 exports对象 npm与包 包 如何下载包 在项目中安装包的命令 解决下包速度慢的问题 为什么下包速度慢 解决方法一--淘宝NPM镜像服务器 解决方法二--切换npm的下包镜像源 解决方法三--nrm 总结 模块化的基本概念 什么是模块化 模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程.对于整个

  • node.js核心模块有哪些

    全局对象 在浏览器JS中,通常window是全局对象,而nodejs中的全局对象是global,所有全局变量都是global对象的属性. 在nodejs中能够直接访问到的对象通常都是global的属性,如console. process等 全局对象与全局变量 global最根本的作用是作为全局变量的宿主. 全局变量的条件: 在最外层定义的变量:全局对象的属性:隐式定义的变量(未定义直接赋值的变量) 定义一个全局变量,同时也是全局对象的属性. 永远使用var定义变量以避免引入全局变量,因为全局变量

  • 详解NodeJS模块化

    目录 一.前言 二.正文 2.1.什么是模块 2.2.Resolving 2.3.require.resolve 2.4.模块间的父子依赖关系 2.5.exports, module.exports 2.6.模块循环依赖 2.7..json和.node 2.8.Wrapping 2.9.Cache 三.总结 一.前言 我们知道,Node.js是基于CommonJS规范进行模块化管理的,模块化是面对复杂的业务场景不可或缺的工具,或许你经常使用它,但却从没有系统的了解过,所以今天我们来聊一聊Node

  • Node.js中SerialPort(串口)模块使用

    目录 目的 模块安装 基础使用 扫描端口 打开端口 发送数据 接收数据 错误处理 数据解析器 SerialPort类 构造方法 属性 事件 方法 命令行工具 总结 目的 上位机与各种电路模块间常常采用串口进行通讯,Node.js中可以使用SerialPort模块操作串口,这篇文章将对其使用进行简单说明. 官网:https://serialport.io/ 文档:https://serialport.io/docs/ 项目地址:https://github.com/serialport/node-

  • node.js中fs文件系统模块的使用方法实例详解

    本文实例讲述了node.js中fs文件系统模块的使用方法.分享给大家供大家参考,具体如下: node.js中为我们提供了fs文件系统模块,实现对文件或目录的创建,修改和删除等操作. fs模块中,所有的方法分为同步和异步两种实现. 有 sync 后缀的方法为同步方法,没有 sync 后缀的方法为异步方法. 一.文件的整个读取 const fs = require('fs'); //参数一表示读取的文件 //参数二表示读取的配置,{encoding:'null', flag:'r'} //encod

  • node.js中path路径模块的使用方法实例分析

    本文实例讲述了node.js中path路径模块的使用方法.分享给大家供大家参考,具体如下: path模块是node.js中处理路径的核心模块.可以很方便的处理关于文件路径的问题. join() 将多个参数值合并成一个路径 const path = require('path'); console.log(path.join('./a', 'b', 'c')); basename() 获取路径中的文件名 const path = require('path'); //获取文件名,包含扩展名 con

  • Node.js 中的 fs 模块与Path模块方法详解

    概述: 文件系统模块是一个简单包装的标准 POSIX 文件 I/O 操作方法集.可以通过调用 require("fs") 来获取该模块.文件系统模块中的所有方法均有异步和同步版本. 文件系统模块中的异步方法需要一个完成时的回调函数作为最后一个传入形参. 回调函数的构成由调用的异步方法所决定,通常情况下回调函数的第一个形参为返回的错误信息. 如果异步操作执行正确并返回,该错误形参则为null或者undefined.如果使用的是同步版本的操作方法,一旦出现错误,会以通常的抛出错误的形式返回

  • Node.js中对通用模块的封装方法

    在Node.js中对模块载入和执行进行了包装,使得模块文件中的变量在一个闭包中,不会污染全局变量,和他人冲突. 前端模块通常是我们开发人员为了避免和他人冲突才把模块代码放置在一个闭包中. 如何封装Node.js和前端通用的模块,我们可以参考Underscore.js 实现,他就是一个Node.js和前端通用的功能函数模块,查看代码: 复制代码 代码如下: // Create a safe reference to the Underscore object for use below.  var

  • Node.js中文件操作模块File System的详细介绍

    File System的缩写是fs,该模块提供本地文件的读写能力. Nodejs导入文件系统模块(fs)语法如下所示: var fs = require("fs"); 异步和同步 Node.js文件系统(fs模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的fs.readFile()和同步的fs.readFileSync() . 异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error).同步则没有回调函数. 建议大家是用异步方法,比起同步

  • Node.js中路径处理模块path详解

    前言 在node.js中,提供了一个path某块,在这个模块中,提供了许多使用的,可被用来处理与转换路径的方法与属性,将path的接口按照用途归类,仔细琢磨琢磨,也就没那么费解了.下面我们就来详细介绍下关于Node.js中的路径处理模块path. 获取路径/文件名/扩展名 获取路径:path.dirname(filepath) 获取文件名:path.basename(filepath) 获取扩展名:path.extname(filepath) 获取所在路径 例子如下: var path = re

  • Node.js中的child_process模块详解

    前言 本文主要给大家介绍了关于Node.js中child_process模块的相关内容,在介绍child_process模块之前,先来看一个例子. const http = require('http'); const longComputation = () => { let sum = 0; for (let i = 0; i < 1e10; i++) { sum += i; }; return sum; }; const server = http.createServer(); ser

  • 使用node.JS中的url模块解析URL信息

    在HTTP部分,详细介绍了URL的相关知识.而nodejs中的url模块提供了一些实用函数,用于URL处理与解析. 解析URL 解析 URL 对象有以下内容,依赖于他们是否在 URL 字符串里存在.任何不在 URL 字符串里的部分,都不会出现在解析对象里 'http://user:pass@host.com:8080/p/a/t/h?query=string#hash' ┌──────────────────────────────────────────────────────────────

  • Node.js中文件系统fs模块的使用及常用接口

    fs是filesystem的缩写,该模块提供本地文件的读写能力,基本上是POSIX文件操作命令的简单包装.但是,这个模块几乎对所有操作提供异步和同步两种操作方式,供开发者选择. JavaScript 的是没有操作文件的能力,但是 Node 是可以做到的,Node 提供了操作文件系统模块,是 Node 中使用非常重要和高频的模块,是绝对要掌握的一个模块系统. fs 模块提供了非常多的接口,这里主要说一下一些常用的接口. 1.常用API快速复习 fs.stat 检测是文件还是目录 const fs

随机推荐