Node.js中SerialPort(串口)模塊使用
目的
上位機(jī)與各種電路模塊間常常采用串口進(jìn)行通訊,Node.js中可以使用SerialPort模塊操作串口,這篇文章將對(duì)其使用進(jìn)行簡(jiǎn)單說(shuō)明。
官網(wǎng):https://serialport.io/
文檔:https://serialport.io/docs/
項(xiàng)目地址:https://github.com/serialport/node-serialport
目前SerialPort模塊版本為 9.2.7
模塊安裝
使用下面命令就可以安裝SerialPort模塊:
npm install serialport
SerialPort模塊功能中有部分是用C/C++實(shí)現(xiàn)的,所以不同的平臺(tái)需要該平臺(tái)可用的二進(jìn)制文件才能運(yùn)行,對(duì)于常見(jiàn)的平臺(tái)通常會(huì)有預(yù)編譯好的二進(jìn)制文件。如果沒(méi)有的話通常會(huì)嘗試使用 node-gyp (依賴Python 3.x)進(jìn)行編譯,通常包管理器會(huì)自動(dòng)處理相關(guān)事務(wù):
有時(shí)候或是有些平臺(tái)下可能需要手動(dòng)編譯。對(duì)于編譯而言需要平臺(tái)上有相應(yīng)的編譯工具,可以參考 《Node.js入門(mén) 02:包管理器npm》 這個(gè)文章中的模塊編譯章節(jié)。
安裝了編譯工具后可以重新安裝SerialPort模塊或者手動(dòng)進(jìn)行編譯處理,具體內(nèi)容可以參考SerialPort模塊文檔中 Installing SerialPort 章節(jié):https://serialport.io/docs/guide-installation/
基礎(chǔ)使用
安裝SerialPort模塊后可以使用 const SerialPort = require('serialport')
方式導(dǎo)入。
掃描端口
使用 SerialPort.list(): Promise<PortInfo[]>
靜態(tài)方法可以獲取設(shè)備上的串口列表,比如下面演示:
const SerialPort = require('serialport'); SerialPort.list().then((ports) => { console.log(ports); // 打印串口列表 }).catch((err) => { console.log(err); });
需要注意的是同一個(gè)端口在這個(gè)列表中有可能會(huì)重復(fù)出現(xiàn)。
也可以使用 async / await 方式使用上面方法:
const SerialPort = require('serialport'); (async () => { try { let ports = await SerialPort.list(); console.log(ports); // 打印串口列表 } catch (error) { console.log(error); } })();
打開(kāi)端口
默認(rèn)情況下創(chuàng)建 SerialPort 對(duì)象就會(huì)打開(kāi)端口,比如下面這樣:
const SerialPort = require('serialport'); const port = new SerialPort('COM6', (err) => { if (err) { console.log('端口打開(kāi)失?。?); return; } console.log('端口打開(kāi)成功!'); });
SerialPort類的構(gòu)造方法中有一個(gè) autoOpen 選項(xiàng)用于控制創(chuàng)建對(duì)象是是否自動(dòng)打開(kāi)端口,默認(rèn)為自動(dòng)打開(kāi),也可以將它關(guān)閉,這樣可以后面手動(dòng)進(jìn)行打開(kāi)端口動(dòng)作:
const SerialPort = require('serialport'); const port = new SerialPort('COM6', { autoOpen: false }); port.open(function (err) { if (err) { console.log('端口打開(kāi)失??!'); return; } console.log('端口打開(kāi)成功!'); });
SerialPort類的構(gòu)造方法中可以使用 baudRate 選項(xiàng)設(shè)置串口通訊波特率,默認(rèn)為9600:
const SerialPort = require('serialport'); const port = new SerialPort('COM6', { baudRate: 115200 }); // 設(shè)置波特率為115200
更多內(nèi)容可以參考下面章節(jié)SerialPort類的構(gòu)造方法說(shuō)明。
發(fā)送數(shù)據(jù)
可以使用SerialPort對(duì)象的 write
方法發(fā)送數(shù)據(jù),該方法會(huì)將要發(fā)送的數(shù)據(jù)放入發(fā)送緩存,然后依次發(fā)送,比如下面這樣:
const SerialPort = require('serialport'); const port = new SerialPort('COM6'); port.write('Hello world!\n'); // 發(fā)送字符串 port.write(Buffer.from('Hey!\n')); // 發(fā)送Buffer數(shù)據(jù) port.write(new Uint8Array([0x48, 0x69, 0x21, 0x0A])); // 發(fā)送字節(jié)數(shù)組
write
方法也可以添加回調(diào)函數(shù):
const SerialPort = require('serialport'); const port = new SerialPort('COM6'); port.write('Hello world!\n', (err) => { if (err) { console.log('write操作失敗!'); return; } console.log('write操作成功!'); });
需要注意的是上面的回調(diào)函數(shù)非異常狀態(tài)下觸發(fā)的時(shí)候只是表示 write
方法本身操作完成,并不代表數(shù)據(jù)完全從端口發(fā)送完成,可以使用 drain
方法來(lái)處理,該方法會(huì)阻塞直到發(fā)送完成:
const SerialPort = require('serialport'); const port = new SerialPort('COM6'); port.write('Hello world!\n'); port.drain(err => { if (err) return; console.log('發(fā)送完成!'); });
接收數(shù)據(jù)
可以使用下面方式接收數(shù)據(jù):
const SerialPort = require('serialport'); const port = new SerialPort('COM6'); // 以 paused mode 監(jiān)聽(tīng)收到的數(shù)據(jù),需要主動(dòng)讀取數(shù)據(jù) port.on('readable', () => { console.log(port.read()); // 使用read方法讀取數(shù)據(jù),可以指定讀取字節(jié)數(shù) }); // 以 flowing mode 監(jiān)聽(tīng)收到的數(shù)據(jù) port.on('data', (data) => { console.log(data); });
除了上面方式外,也可以使用 pipe
將數(shù)據(jù)傳送到另一個(gè)流。
錯(cuò)誤處理
SerialPort對(duì)象大多數(shù)操作都有回調(diào)函數(shù),回調(diào)函數(shù)中的第一個(gè)參數(shù)都是異常對(duì)象。另外也可以通過(guò) error 事件來(lái)統(tǒng)一處理異常:
const SerialPort = require('serialport'); const port = new SerialPort('COM6'); port.on('error', err => { console.log(err); });
數(shù)據(jù)解析器
SerialPort模塊中準(zhǔn)備了一些數(shù)據(jù)解析器,主要用來(lái)處理收到的一些一些常見(jiàn)形式的串口數(shù)據(jù),主要提供的功能如下:
ByteLength Parser
以收到的數(shù)據(jù)長(zhǎng)度為單位進(jìn)行解析:
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個(gè)字節(jié)觸發(fā) parser.on('data', chunk => { console.log(chunk); // 打印收到的數(shù)據(jù) });
ccTalk Parser
解析 ccTalk 格式數(shù)據(jù),格式詳見(jiàn):https://en.wikipedia.org/wiki/CcTalk
Delimiter Parser
以指定字符為界限處理數(shù)據(jù):
const SerialPort = require('serialport'); const port = new SerialPort('COM6'); const Delimiter = require('@serialport/parser-delimiter'); const parser = port.pipe(new Delimiter({ delimiter: '\n' })); // 以 \n 分隔處理數(shù)據(jù) parser.on('data', chunk => { console.log(chunk.toString()); // 打印收到的數(shù)據(jù) });
delimiter選項(xiàng)可以是 string|Buffer|number[] ;includeDelimiter選項(xiàng)表示數(shù)據(jù)中是否包含分隔符,默認(rèn)不包含。
InterByteTimeout Parser
指定時(shí)間未收到數(shù)據(jù)觸發(fā)解析:
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毫秒未接到數(shù)據(jù)觸發(fā) parser.on('data', chunk => { console.log(chunk); // 打印收到的數(shù)據(jù) });
maxBufferSize選項(xiàng)用于指定接收到該數(shù)量數(shù)據(jù)后就算沒(méi)有超時(shí)也將觸發(fā)動(dòng)作。
Readline Parser
以行為單位解析數(shù)據(jù),默認(rèn)行分隔符為 \n
,可以使用 delimiter 選項(xiàng)重新設(shè)置為其它的,比如 \r\n
。
Ready Parser
以開(kāi)始標(biāo)志進(jìn)行解析。
Regex Parser
以正則表達(dá)式為分隔進(jìn)行解析。
SerialPort類
使用SerialPort模塊主要就是使用SerialPort類,其介紹在SerialPort模塊文檔中 Stream Interface 章節(jié):https://serialport.io/docs/api-stream,這里稍微摘錄下其中部分內(nèi)容。
構(gòu)造方法
new SerialPort(path [, openOptions] [, openCallback])
構(gòu)造方法用于創(chuàng)建一個(gè)串口對(duì)象,path為串口號(hào),openCallback為自動(dòng)打開(kāi)失敗時(shí)的回調(diào)函數(shù);
openOptions常用選項(xiàng)如下:
選項(xiàng) | 類型 | 說(shuō)明 | 默認(rèn)值 |
---|---|---|---|
autoOpen | boolean | 自動(dòng)打開(kāi)端口 | true |
baudRate | number | 波特率 | 9600 |
dataBits | number | 數(shù)據(jù)位,可選值:8、7、6、5 | 8 |
highWaterMark | number | 讀和寫(xiě)緩存大小 | 65536 |
lock | boolean | 鎖定端口,防止其它平臺(tái)打開(kāi)(Windows上不支持false) | true |
stopBits | number | 停止位,可選值:1、2 | 1 |
parity | string | 校驗(yàn),可選值:none、even、mark、odd、space | none |
rtscts | boolean | 流控制設(shè)置 | false |
xon | boolean | 流控制設(shè)置 | false |
xoff | boolean | 流控制設(shè)置 | false |
xany | boolean | 流控制設(shè)置 | false |
屬性
SerialPort有下面幾個(gè)屬性可讀:
path
、 baudRate
、 isOpen
、 binding
事件
SerialPort會(huì)觸發(fā)的事件有下面幾個(gè):
open
端口打開(kāi)時(shí)觸發(fā);error
發(fā)送錯(cuò)誤時(shí)觸發(fā);close
端口關(guān)閉時(shí)觸發(fā);data
收到數(shù)據(jù)時(shí)觸發(fā);drain
如果write方法返回false,則再次調(diào)用write方法時(shí)將觸發(fā)該事件;
方法
SerialPort可用的一些方法如下:
open(() => {}): void
打開(kāi)端口;update(options: updateOptions, callback?: err => {}): void
更改波特率;write(data: string|Buffer|Array<number>, encoding?: string, callback?: error => {}): boolean
發(fā)送數(shù)據(jù);read(size?: number): string|Buffer|null
讀取數(shù)據(jù);close(callback?: error => {}): void
關(guān)閉端口;set(options: setOptions, callback?: error => {}): void
設(shè)置流控制;get(callback: (error, data: ModemStatus) => {}): void
獲取已打開(kāi)端口的流控制狀態(tài);flush(callback? error => {}):void
清空接收和發(fā)送緩存中未處理數(shù)據(jù);drain(callback? error => {}):void
等待數(shù)據(jù)發(fā)送完成;pause(): this
暫停 flowing mode 觸發(fā)data事件,轉(zhuǎn)為 paused mode;resume(): this
恢復(fù) data 事件,從 paused mode 轉(zhuǎn)為 flowing mode;
命令行工具
SerialPort模塊也提供了一些命令行工具,用于直接在命令行界面中使用。下面是官網(wǎng)首頁(yè)的使用演示:
更多內(nèi)容可以參考SerialPort模塊文檔中 Command Line Tools 章節(jié):https://serialport.io/docs/guide-cli
總結(jié)
Node.js的SerialPort模塊使用主要就是上面一些內(nèi)容了。
另外需要提一點(diǎn)的是SerialPort模塊并不是直接操作串口,而是調(diào)用了各個(gè)平臺(tái)上底層的接口來(lái)使用串口,如果有進(jìn)行相關(guān)內(nèi)容的開(kāi)發(fā)或是有特殊需求的話可以參考SerialPort模塊文檔中Binding相關(guān)內(nèi)容。
到此這篇關(guān)于Node.js中SerialPort(串口)模塊使用的文章就介紹到這了,更多相關(guān)Node.js SerialPort內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
NodeJS收發(fā)GET和POST請(qǐng)求的示例代碼
本篇文章主要介紹了NodeJS收發(fā)GET和POST請(qǐng)求的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08DevEco?Studio設(shè)置Nodejs提示路徑只能包含英文、數(shù)字、下劃線等解決辦法
這篇文章主要給大家介紹了關(guān)于DevEco?Studio設(shè)置Nodejs提示路徑只能包含英文、數(shù)字、下劃線等的解決辦法,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01node.js中的fs.renameSync方法使用說(shuō)明
這篇文章主要介紹了node.js中的fs.renameSync方法使用說(shuō)明,本文介紹了fs.renameSync的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12nodejs對(duì)文件中的圖片進(jìn)行歸類操作示例
這篇文章主要為大家介紹了nodejs對(duì)文件中的圖片進(jìn)行歸類的實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07淺談Koa2框架利用CORS完成跨域ajax請(qǐng)求
這篇文章主要介紹了淺談Koa2框架利用CORS完成跨域ajax請(qǐng)求,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03Nodejs環(huán)境實(shí)現(xiàn)socket通信過(guò)程解析
這篇文章主要介紹了Nodejs環(huán)境實(shí)現(xiàn)socket通信過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07從零開(kāi)始學(xué)習(xí)Node.js系列教程一:http get和post用法分析
這篇文章主要介紹了從零開(kāi)始學(xué)習(xí)Node.js系列教程一:http get和post用法,結(jié)合具體實(shí)例形式分析了nodejs中g(shù)et與post請(qǐng)求的使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-04-04Nodejs極簡(jiǎn)入門(mén)教程(二):定時(shí)器
這篇文章主要介紹了Nodejs極簡(jiǎn)入門(mén)教程(二):定時(shí)器,本文講解了setTimeout、setInterval、setImmediate及process.nextTick等內(nèi)容,需要的朋友可以參考下2014-10-10