LoginSignup
3
3

シリアルポート通信の傍受

Last updated at Posted at 2024-04-10

今ではレガシーポートとなってしまったシリアルポートだが現場ではまだまだ使われており、ときに受信してデータを取り出さなければならないことがある。機器が古すぎて通信仕様書が手に入らないこともあるし、受信だけの一方通行の垂れ流しならまだいいが双方向だとこちらから正しく問い合わせないとまともに返ってこないのでお手上げだ。リプレースであれば既存機器間の通信を傍受すれば手がかりを得られるだろう。今回はそんな場面に遭遇したので覚書として残しておく。

com0comのインストールと設定

https://qiita.com/yaju/items/e5818c99857883a59033
Setupでは例えば物理ポートがCOM5だった場合、Virtual Port Pair 0をCOM10, 11、Pair 1をCOM20, 21のように設定してuse Ports classは全てチェックを入れてApplyする

comleak.pyの準備

pyserialのインストール

> python -m pip install pyserial

※以下は上記リンク先のコードを転載させていただいてます。port = serial.Serial(port=s, baudrate=115200, write_timeout=0.05) のbaudrateは実際の機器にあわせて9600などに変更してください。

comleak.py
#!/usr/bin/python3
# -*- coding: utf8 -*-
# comleak.py v1.0 written by fuku
#
# Usage: comleak.py SerialDevice1 SerialDevice2 [..]
#   ex(Windows): python3 comleak.py COM4 COM10 COM12
#   ex(Linux): comleak.py /dev/ttyS3 /dev/ttyS9 /dev/ttyS11
#   ひとつのシリアルポートに出力されたデータを他のシリアルポートにも流す。
#

import sys, time
import serial

argv = sys.argv     # コマンドライン引数を取得する。

# シリアルデバイス名のリストを作成する。
deviceList = []
for s in argv[1:]:
  if not s in deviceList:
    deviceList.append(s)
deviceCnt = len(deviceList)

# 下記の場合は中断する。
# ・デバイスの数が不足している
# ・デバイス名に重複がある
if deviceCnt < 2 or deviceCnt != len(argv) - 1:
  print('Usage: comleak.py <Ser0> <Ser1> [..]')
  exit()

# 指定されたシリアルポートをすべて開く。
ser = {}
for s in deviceList:
  try:
    port = serial.Serial(port=s, baudrate=115200, write_timeout=0.05)
    ser[port] = b''
  except:
    print("Error: %s can't open." % s)
    exit()

ports = ser.keys()  # 開いたシリアルデバイスをリスト化する。

try:    # ^C をキャッチするため try にする。
  while True:
    # 全シリアルデバイスを読み込む。(データが到来していれば)
    for p in ports:
      ser[p] = p.read_all()

    # 到来したデータを全デバイスに出力する。(自デバイスを除く)
    for p in ports:
      data = ser[p]
      if data != b'':
        for q in ports:
          if q != p:
            try:
              q.write(data)
            except serial.serialutil.SerialTimeoutException:
              pass  # 読み込む準備が出来ていないデバイスはスキップ*する。

    time.sleep(0.1)   # 100ms 待つ。
except KeyboardInterrupt:
  pass

for p in ports:
  p.close()

comleak.py の実行(以下の4)

> python .\comleak.py COM5 COM10 COM20

止めるときは Ctrl + C で

Ratatoskrのインストール(以下の2)と設定、傍受(以下の6)

https://www.rouge.gr.jp/~fuku/tips/serial-sniffing/
上記で設定した場合、機器をCOM11、RatatoskrをCOM21に接続して傍受する(COM10, 20は物理ポートのCOM5を介して通信する)

Ratatoskrの使い方

最初はよくわからないと思うが、上部のGATE_00Xを右クリックしてポートや通信速度を設定した後、これ自身がトグルボタンになっておりクリックして接続、もう一度クリックして切断になる。また、接続した状態で下部のSend file Pathの右の[...]ボタンで送信したいデータの入ったファイルを選択して[Send]ボタンでデータを送信できる。

Ratatoskr_1.png

実は今までなるべく実環境に近い方がよいだろうという考えもあり、PC2台をシリアルケーブルとUSB変換ケーブルでつなぎ、各々でテストプログラムを動かして開発していた。しかし、これを使えば1台で済むしクラウドの仮想環境で構築すればどこでもシリアル通信プログラムのテストが可能になる(つまり寝っ転がったままできる)のだ。

以上

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3