文章目录
目的
crm开发定制与各种电路模块间常常crm开发定制采用串口进行通讯,Node.jscrm开发定制中可以使用SerialPortcrm开发定制模块操作串口,crm开发定制这篇文章将对其使用进crm开发定制行简单说明。
官网:
项目地址:
目前SerialPortcrm开发定制模块版本为 10.4.0
模块安装
crm开发定制使用下面命令就可以安装模块:
# npm init -y # crm开发定制初始化项目npm install serialport# npm install serialport@10 # 安装10.x.xcrm开发定制版本中最新的包
- 1
- 2
- 3
SerialPort模块功能中有部分是用C/C++实现的,所以不同的平台需要该平台可用的二进制文件才能运行,对于常见的平台通常会有预编译好的二进制文件。如果没有的话通常会尝试使用 node-gyp (依赖Python)进行编译,通常包管理器会自动处理相关事务。
在Linux中使用root用户或是sudo方式安装的话需要带上额外参数,不然可能会报错:
sudo npm install serialport --unsafe-perm
快速使用
模块导入
安装完成后使用可以使用下面两种方式导入模块:
const { SerialPort } = require('serialport');// import { SerialPort } from 'serialport'; // esm方式
- 1
- 2
扫描端口
使用SerialPort.list()可以得到设备上的串口列表。这是一个Promise对象,可以使用then方式或是使用async/await方式处理:
const { SerialPort } = require('serialport');(async () => { try { let ports = await SerialPort.list(); console.log(ports); // 打印串口列表 } catch (error) { console.log(error); }})();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
需要注意的是同一个端口在这个列表中有可能会重复出现。
打开端口
可以使用下面方法创建并打开端口:
const { SerialPort } = require('serialport');const serialport = new SerialPort({ path: 'COM7', baudRate: 9600 });
- 1
- 2
- 3
打开端口这个动作可以添加回调函数:
const { SerialPort } = require('serialport');const port = new SerialPort({ path: 'COM7', baudRate: 9600 }, (err) => { if (err) { console.log('端口打开失败!'); return; } console.log('端口打开成功!');});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
另外也可以在创建时不打开端口,在使用前用open方法打开:
const { SerialPort } = require('serialport');const serialport = new SerialPort({ path: 'COM7', baudRate: 9600, autoOpen: false });serialport.open();
- 1
- 2
- 3
- 4
- 5
发送数据
打开端口后可以使用write方法发送数据:
const { SerialPort } = require('serialport');const sp = new SerialPort({ path: 'COM7', baudRate: 115200 });sp.write('Hello world!'); // 发送字符串sp.write(Buffer.from('Hey!')); // 发送Buffer数据sp.write(new Uint8Array([0x48, 0x69, 0x21, 0x0A])); //发送字节数组
- 1
- 2
- 3
- 4
- 5
- 6
需要注意的是打开端口的动作是异步的,所以上面代码的write执行的时候端口可能还没打开,write会先将数据写入到缓存中,等到端口打开时再发送。
需要注意的是write方法返回true或是触发回调函数并不代表发送完成,需要结合drain方法才能判断发送完成:
const { SerialPort } = require('serialport');const sp = new SerialPort({ path: 'COM7', baudRate: 115200 });port.write('Hello world!');port.drain(err => { if (err) return; console.log('发送完成!');});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
接收数据
可以使用下面两种方式来接收数据:
const { SerialPort } = require('serialport');const sp = new SerialPort({ path: 'COM7', baudRate: 115200 });// 以 paused mode 监听收到的数据,需要主动读取数据sp.on('readable', () => { console.log(sp.read()); // 使用read方法读取数据,可以指定读取字节数});// 以 flowing mode 监听收到的数据sp.on('data', (data) => { console.log(data);});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
错误处理
SerialPort对象大多数操作都有回调函数,回调函数中的第一个参数都是异常对象。另外也可以通过 error 事件来统一处理异常:
const { SerialPort } = require('serialport');const sp = new SerialPort({ path: 'COM7', baudRate: 115200 });sp.on('error', err => { console.log(err);});
- 1
- 2
- 3
- 4
- 5
- 6
SerialPort更多说明
构造方法
new SerialPortStream(openOptions, [openCallback])
构造方法用于创建一个串口对象,openOptions为参数,openCallback为打开端口失败时的回调函数;
openOptions常用选项如下:
选项 | 类型 | 说明 | 默认值 |
---|---|---|---|
path | string | 端口号 | |
baudRate | number | 波特率 | |
dataBits | number | 数据位,可选值:5、6、7、8 | 8 |
lock | boolean | 锁定端口,防止其它平台打开(Windows上不支持false) | true |
stopBits | number | 停止位,可选值:1、1.5、2 | 1 |
parity | string | 校验,可选值:none、even、mark、odd、space | none |
rtscts | boolean | 流控制设置 | false |
xon | boolean | 流控制设置 | false |
xoff | boolean | 流控制设置 | false |
xany | boolean | 流控制设置 | false |
hupcl | boolean | 流控制设置(关闭串口时将DTR设置为低) | true |
autoOpen | boolean | 自动打开端口 | true |
highWaterMark | number | 读和写缓存大小 | 64k (65536?) |
endOnClose | boolean | 当串口关闭时发送end事件 | false |
属性
SerialPort有下面几个属性可读:
path
、 baudRate
、 isOpen
、 binding
事件
SerialPort会触发的事件有下面几个:
open
端口打开时触发;error
发生错误时触发;close
端口关闭时触发;data
flowing mode下收到数据时触发;drain
如果write方法返回false,则在恢复可以发送数据时将触发该事件;
方法
SerialPort可用的一些方法如下:
open(callback?: (err: Error | null) => {}): 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模块中准备了一些数据解析器,主要用来处理收到的一些常见形式的串口数据。
parser-byte-length
以收到的数据长度为单位进行解析:
const { SerialPort } = require('serialport');const sp = new SerialPort({ path: 'COM7', baudRate: 115200 });const { ByteLengthParser } = require('@serialport/parser-byte-length');const parser = sp.pipe(new ByteLengthParser({ length: 8 })); // 每收到8个字节触发parser.on('data', chunk => { console.log(chunk); // 打印收到的数据});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
parser-cctalk
解析 ccTalk 格式数据,格式详见:
parser-delimiter
以指定字符为界线处理数据:
const { SerialPort } = require('serialport');const sp = new SerialPort({ path: 'COM7', baudRate: 115200 });const { DelimiterParser } = require('@serialport/parser-delimiter');const parser = sp.pipe(new DelimiterParser({ delimiter: ';' })); // 以 ; 分隔处理数据parser.on('data', chunk => { console.log(chunk.toString()); // 打印收到的数据});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
DelimiterParser可用参数有:
delimiter
: string | Buffer | number[]includeDelimiter
: 表示数据中是否包含分隔符,默认为false(不包含)
parser-inter-byte-timeout
指定时间未收到数据触发解析:
const { SerialPort } = require('serialport');const sp = new SerialPort({ path: 'COM7', baudRate: 115200 });const { InterByteTimeoutParser } = require('@serialport/parser-inter-byte-timeout');const parser = sp.pipe(new InterByteTimeoutParser({ interval: 2000, maxBufferSize: 4 }));parser.on('data', chunk => { console.log(chunk); // 打印收到的数据});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
maxBufferSize选项用于指定接收到该数量数据后就算没有超时也将触发动作。
parser-packet-length
以分隔符数据长度等标识数据包进行解析。
parser-readline
以行为单位解析数据,默认行分隔符为 ,可以使用 delimiter 选项重新设置为其它的,比如
\r
。
parser-ready
以标志字符串进行解析。触发时会触发一个以标志字符串为名称的事件。
parser-regex
以正则表达式为分隔进行解析。
parser-slip-encoder
parser-spacepacket
命令行工具
SerialPort模块也提供了一些命令行工具,用于直接在命令行界面中使用。下面是官网首页的使用演示:
更多内容可以参考SerialPort模块文档中 Command Line Packages 章节内容。
在渲染进程中使用
SerialPort模块10.x.x版本最大的变化是可以直接在Electron的渲染进程中使用了:
总结
Node.js的SerialPort模块使用主要就是上面一些内容了。
另外需要提一点的是SerialPort模块并不是直接操作串口,而是调用了各个平台上底层的接口来使用串口,如果有进行相关内容的开发或是有特殊需求的话可以参考SerialPort模块文档中binding相关内容。