PowerShellでシリアルポートを使ってシリアルコンソールに接続するターミナルソフトの簡易版スクリプトを作ってみた
概要
シリアルポートは随分前からレガシーになっているが、未だにスイッチのコンソールとかモデム端末でATコマンドなんかを少しだけいじることがある。Windowsには昔はハイパーターミナルが付属していたが今は無いのでTeraTerm等が使われる。ターミナルソフトがインストールされていればいいのだが、ちょっとだけ使いたいときインストールするのも面倒な状況で簡易的にターミナルソフトの代替ができるPowerShellスクリプトを作ってみた。
USB RS232Cの場合当然ながらデバイスドライバーは別途インストールが必要。
環境
- Windows PowerShell 2.0、3.0、5.1で確認
- 注意: ISE環境ではコンソール(キーボード/画面)入出力処理に制限があるためエラーになり使用不可。PowerShellコンソール環境で動作する。
- VT100エミュレーションは5.1からサポートされたためそれ以前はエスケープシーケンスがうまく表示できない
- PowerShell coreでは.Netアセンブリがうまく追加できず動作しなかった
スクリプト説明
- 注意: ISE環境ではコンソール(キーボード/画面)入出力処理に制限があるためエラーになり使用不可。PowerShellコンソール環境で動作する。
Powershellのブログ記事に基づいて.NetのSerialportクラスを使ったスクリプトを作成。単純にWriteLine()やReadLine()メソッドを使うだけだと、いちいち入力したり表示するたびにメソッド呼出しの入力操作が必要になって面倒なので以下の処理とした。
・シリアル受信イベントをRegister-ObjectEventで登録してコンソールに自動的に表示する
・キーボード入力を読み取って送信するループを繰り返す
これらによりターミナルソフト風の動作が可能
もし自動化スクリプトを作成するのならWriteLine()やReadLine()で逐次処理させたほうが扱いやすい。あくまでユーザーが対話的にオペレーションする場合を想定。
参照 PowerShell Team Blog
参照 .Net System.IO.Portsクラス
接続開始時のスクリプト
COMポートオープンエラーとかRS232Cのパリティエラーとか例外処理関係は簡便のため割愛
ログを取りたい場合は、トランスクリプトを事前に開始しておく。(Start-Transcriptでデータが取れる)
### 接続開始時のスクリプト ###
# 1. COMポートのインスタンス生成 (COM1、9600bps、パリティ無し) パリティある場合::Even、::Oddとする
$c = New-Object System.IO.Ports.SerialPort "COM1", 9600, ([System.IO.Ports.Parity]::None)
# 2. DTR、RTSを設定 (機器・ケーブル仕様に合わせる)
$c.DtrEnable = $true
$c.RtsEnable = $true
# 3. ハンドシェイク無し (必要なら::RequestToSendや::XOnXOffとする)
$c.Handshake=[System.IO.Ports.Handshake]::None
# 4. 改行文字をCR(0x0D)に設定 (機器仕様に合わせる)
# ※NewLineプロパティはWriteLineやReadLineメソッドに適用されるため本方法では動作に影響しない
# 実際の変更方法の例は後述
$c.NewLine = "`r"
# 5. 文字コードをSJISに設定 (機器仕様に合わせる)
$c.Encoding=[System.Text.Encoding]::GetEncoding("Shift_JIS")
# 6. シリアル受信イベントを登録(受信したらコンソールに出力)
$d = Register-ObjectEvent -InputObject $c -EventName "DataReceived" `
-Action {param([System.IO.Ports.SerialPort]$sender, [System.EventArgs]$e) `
Write-Host -NoNewline $sender.ReadExisting()}
# 7. COMポートを開く
$c.Open()
# 8. キーボード入力をシリアルポートに送信する無限ループ (ReadKey($false)とすればローカルエコーになる)
# これ以降、ターミナルソフトのようなキーボード入力と機器の出力表示になります (コピペデータも機器に送られるので注意)
# 終了時はctrl-cで抜ける
for(;;){if([Console]::KeyAvailable){$c.Write(([Console]::ReadKey($true)).KeyChar)}}
実行例のスクリーンショット
Yamahaルーターの例
LTEモデムの例
CentreCOM FS808TP V1の例(VT100)
※VT100エミュレーションはWMF 5.1からサポートされたのでそれ以前はうまく表示できない
カラー表示がやや変だが一応動く
接続終了のスクリプト
本方法終了後、Powershellコンソールを続行するなら下記の手順を実行して後片付けする
### 接続断時のスクリプト ###
# 9. COMポート閉じる
$c.Close()
# 10. イベント登録解除
Unregister-Event $d.Name
# 11. ジョブ削除
Remove-Job $d.id
Powershell自体を閉じてしまえばCOMポートとか各種リソースは解放されるのでそれでもいい。
改行コードの変更方法
受信する改行コードの変更
機器から受信する改行コードがCR+LFでない場合(CRのみやLFのみの場合)、6.の行内のWrite-HostのところにてCR+LFに置換する。(Windows PowershellコンソールはCR+LFで改行のため)
# 機器から受信する改行がCRのみの場合、Write-HostするデータをReplaceで置換する
$d = Register-ObjectEvent -InputObject $c -EventName "DataReceived" `
-Action {param([System.IO.Ports.SerialPort]$sender, [System.EventArgs]$e) `
Write-Host -NoNewline ($sender.ReadExisting()).Replace("`r","`r`n")}
# LFのみの場合も同じくReplaceで置換する
$d = Register-ObjectEvent -InputObject $c -EventName "DataReceived" `
-Action {param([System.IO.Ports.SerialPort]$sender, [System.EventArgs]$e) `
Write-Host -NoNewline ($sender.ReadExisting()).Replace("`n","`r`n")}
送信する改行コードの変更
機器へ送信する改行コードは8.の行内でEnterキーのReadKeyがCRになるので、下記のようにCR+LFまたはLFにする。
# $c.Write()の引数を以下のように置換する例
# EnterキーをCR+LFへ変更する場合
for(;;){if([Console]::KeyAvailable){$c.Write( `
$(switch(([Console]::ReadKey($true)).KeyChar){{$_-eq[char]13}{"`r`n"}default{$_}}))}}
# EnterキーをLFのみへ変更する場合
for(;;){if([Console]::KeyAvailable){$c.Write( `
$(switch(([Console]::ReadKey($true)).KeyChar){{$_-eq[char]13}{"`n"}default{$_}}))}}
その他
シリアル通信のエラー(パリティエラーとか)については、ErrorReceivedイベント処理を追加すれば対応できる。
シリアル通信の制御信号については、PinChangedイベント処理を追加すれば対応できる。
Author And Source
この問題について(PowerShellでシリアルポートを使ってシリアルコンソールに接続するターミナルソフトの簡易版スクリプトを作ってみた), 我々は、より多くの情報をここで見つけました https://qiita.com/yapg57kon/items/58d7f47022b3e405b5f3著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .