Node.js中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常用選項如下:
屬性
SerialPort有下面幾個屬性可讀:
path
、 baudRate
、 isOpen
、 binding
事件
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內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Node.js實戰之Buffer和Stream模塊系統深入剖析詳解
- Node的文件系統你瞭解多少
- 詳解node.js創建一個web服務器(Server)的詳細步驟
- C#串口連接的讀取和發送詳解
- node.js核心模塊有哪些