2015-11-09 line monitor > コア部分変更 (ノンブロッキング受信) > RS-232C受信 > RS-232C送信 / UDP送信

http://qiita.com/7of9/items/cc5d01fe492817eb84d7
においてUSBシリアルの受信処理を実装した。問題はブロッキング受信なので、2つのシリアルポートがあった時に、片方の受信で処理が止まってしまうこと。

受信処理をノンブロッキングに変更することにした。

```txt:動作環境
RS-232C送信 : Windows8.1 pro + TeraTerm [CR+LF送信設定済み]
RS-232C受信 / UDP送信 : RaspberyPi2 + raspbian
UDP受信 : CentOS 6.5 (32bit)
```

```txt:通信ケーブル
A. Win8.1 : SRC06-USB (USBシアリルケーブル)
B-1. RPi2 : VE488 (USBシリアルケーブル)
B-2. RPi2 : VE488 (USBシリアルケーブル)
X : TX-RX変換用治具 (`AとB-1` または `AとB-2`を接続に使用)
```

XはDSUB9ピンコネクタ２つをクロス接続したもの。

RPi2側のプログラムは以下とした。

```151109b.py
import serial
import time
import socket

def main():
    print "Hello"
    dstip = "192.168.10.8"
    dstport = 6000
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    con1=serial.Serial('/dev/ttyUSB1', 9600, timeout=0.1)
    con2=serial.Serial('/dev/ttyUSB0', 9600, timeout=0.1)

    rcvd1=""
    rcvd2=""

    while True:
        str1=con1.read()
        if (len(str1) > 0):
            rcvd1 = rcvd1 + str1
        if "\n" in rcvd1:
            print "rcvd1=", rcvd1
            sock.sendto("1:" + rcvd1, (dstip, dstport))
            con2.write(str1)
            rcvd1 = ""

        str2=con2.read()
        if (len(str2) > 0):
            rcvd2 = rcvd2 + str2
        if "\n" in rcvd2:
            print "rcvd2=", rcvd2
            sock.sendto("2:" + rcvd2, (dstip, dstport))
            con1.write(str2)
            rcvd2 = ""


if __name__ == '__main__':
    main()
```

- RPi2側でpythonプログラムを実行。
- CentOS側でUDP受信の処理を実行 (`# tcpdump -A -n udp portrange 6000`)

この状態でWin8.1側でTeraTermから送信

  - `2224<CR><LF>`送信. `2225<CR><LF>`送信。
  - シリアルケーブルの接続をA-B1接続からA-B2接続に変更
  - `2226<CR><LF>`送信. `2227<CR><LF>`送信.

RPi2側の結果が以下。２つのシリアル(rcvd2とrcvd1)において受信が成功している。

```
pi@raspberrypi ~/lineMonitor $ python -u 151109b.py 
Hello
rcvd2= 2224

rcvd2= 2225

rcvd1= 2226

rcvd1= 2227

```

以下はlinux側でのUDPの受信の結果。
2224から2227までの文字が受信できている。UDPへのリレーが成功。

```
# tcpdump -A -n udp portrange 6000
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
22:24:30.889493 IP 192.168.10.5.37728 > 192.168.10.8.6000: UDP, length 8
E..$3.@.@.q...
...
..`.p....2:2224
..........
22:24:37.577441 IP 192.168.10.5.37728 > 192.168.10.8.6000: UDP, length 8
E..$3.@.@.q{..
...
..`.p....2:2225
..........
22:24:49.748362 IP 192.168.10.5.37728 > 192.168.10.8.6000: UDP, length 8
E..$48@.@.q3..
...
..`.p....1:2226
..........
22:24:52.027533 IP 192.168.10.5.37728 > 192.168.10.8.6000: UDP, length 8
E..$4.@.@.p...
...
..`.p....1:2227
..........

```


ちょっとずつ進んできた。

コードがきたないのはpythonでの「関数」処理を未学習のため。

while True内のCPU負荷が高そうなのについては、どうすればいいのか未調査。


## 関数化

上記の処理を関数を使って整理。
以下がいいかはまだ分からない。
実際に使ってみたが、プログラムは壊れてなかった。

```151111f.py
import serial
import time
import socket

def comrelay(rcvd, srccom, dstcom):
    str1 = srccom.read()
    if (len(str1) > 0):
        rcvd = rcvd + str1
    if "\n" in rcvd:
        print "rcvd=", rcvd
        dstcom.write(rcvd)
        return rcvd, True # new line = true

    return rcvd, False # new line = false

def main():
    print "Hello"
    dstip = "192.168.10.8"
    dstport = 6000
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    con1=serial.Serial('/dev/ttyUSB1', 9600, timeout=0.1)
    con2=serial.Serial('/dev/ttyUSB0', 9600, timeout=0.1)

    rcvd1=""
    rcvd2=""

    while True:
        rcvd1,isNL = comrelay(rcvd1, con1, con2)
        if isNL == True:
            sock.sendto("1:" + rcvd1, (dstip, dstport))
            rcvd1 = ""

        rcvd2,isNL = comrelay(rcvd2, con2, con1)
        if isNL == True:
            sock.sendto("2:" + rcvd2, (dstip, dstport))
            rcvd2 = ""

if __name__ == '__main__':
    main()
```