【docker】シリアルポートからデータを読む (u-blox 受信機)

# docker container でシリアルポートからのデータを扱いたい

Jetson NanoでUSBでu-blox 受信機を接続して、docker container でデータを読むことができました。
そのときのメモです。多分、Jetson Nanoや u-blox は関係なく、一般的な初歩的なお話だと思います。(^^;)
復習も兼ねて「くどく」書いています。。。

ポイントは、Docker のマニュアルにもありますが、ホスト側のシリアリポートをそのまま仮想環境にマッピングするには、一言、docker run の引数に書くだけでOKです。

```
docker run --device=<ホストOSのdevice>:仮想環境のdevice> 
```

とするだけです。実際は、Docker-docs-ja で

- [ホスト・デバイスをコンテナに追加（--device）](https://docs.docker.jp/engine/reference/commandline/run.html#device)
- [実行時の権限、Linux 機能、LXC 設定](http://docs.docker.jp/v1.12/engine/reference/run.html#linux-lxc)

等を読むと、権限や通信帯域の設定など、細かい話もあるにはあります。が、今回はホストOSと同じ設定（どちらもubuntu18.04だし）なのでdon't care でOKでした。

# 動作確認

以下、Jetson Nanoでu-blox M8TをUSBで接続し、最後に```docker run ```で入力を読めることを確認したときのメモです。

### シリアル通信するデバイスの動作確認

デバイスはu-blox M8Tを使いました。（だから何だ。。。）

```
$lsusb
Bus 001 Device 004: ID 1546:01a8 U-Blox AG
Bus 001 Device 002: ID 0bda:5411 Realtek Semiconductor Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$dmesg
...
[1442054.399797] tegra-xusb-padctl 7009f000.xusb_padctl: power on UTMI pads 1
[1442054.403431] tegra-xusb 70090000.xusb: Firmware timestamp: 2019-10-17 15:58:59 UTC, Version: 50.25 release
[1442054.404047] tegra-pmc: PMC tegra_pmc_utmi_phy_disable_sleepwalk : port 0
[1442054.404242] tegra-pmc: PMC tegra_pmc_utmi_phy_disable_sleepwalk : port 1
[1442054.404427] tegra-pmc: PMC tegra_pmc_utmi_phy_disable_sleepwalk : port 2
[1442054.405876] tegra-xusb 70090000.xusb: exiting ELPG done
[1442054.409069] usb usb2: usb_suspend_both: status 0
[1442054.750106] usb 1-2.4: new full-speed USB device number 4 using tegra-xusb
[1442054.773772] usb 1-2.4: New USB device found, idVendor=1546, idProduct=01a8
[1442054.773846] usb 1-2.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[1442054.773896] usb 1-2.4: Product: u-blox GNSS receiver
[1442054.773944] usb 1-2.4: Manufacturer: u-blox AG - www.u-blox.com
[1442054.864251] cdc_acm 1-2.4:1.0: ttyACM0: USB ACM device
[1442054.864676] usbcore: registered new interface driver cdc_acm
[1442054.864679] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
$ ls -lth /dev/ttyACM*
crw-rw---- 1 root dialout 166, 0 10月 19 17:08 /dev/ttyACM0
```

u-blox 受信機をUSBポートにさしました。

```
$ sudo usermod -a -G dialout $USER
$ screen /dev/ttyACM0 115200
```

screenはctrl+a d で終了します。

### docker 素材の用意

次に、シリアルポートからデータを読む python スクリプトを用意します。[pyserial](https://pyserial.readthedocs.io/en/latest/shortintro.html)を使います。


```python:serial_read.py
#!/usr/bin/env python3
import sys
import serial

port = sys.argv[1]
with serial.Serial(port, 115200) as ser:
    while True:
        data =ser.read(1024)
        print(data)
```

```python3 serial_read.py /dev/ttyACM0``` で動作確認をした後、Dockerfile を作成します。

```
FROM ubuntu:18.04

# Install python and pip
RUN apt-get update -y && \
  apt-get install -y -qq --no-install-recommends \
  python3 \
  python3-serial \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

ENV PATH /usr/local/bin/:$PATH

# the port number the container should expose
COPY serial_read.py /usr/local/bin
RUN  chmod +x /usr/local/bin/serial_read.py

ENTRYPOINT [ "serial_read.py" ]
```

### 動作確認

できたら、build して動かしてみます。ここでは、仮想環境でのシリアルポートを /dev/myserialport としました。

```shell
$ docker build -t test/serial .
Successfully tagged test/serial:latest
$ docker run --device=/dev/ttyACM0:/dev/myserialport --rm -it test/serial /dev/myserialport
b'$GNRMC,093210.00,V,,,,,,,191020,,,N*61\r\n$GNVTG,,,,,,,,,N*2E\r\n$GNGGA,093210.00,,,,,0,00,99.99,,,,,,*71\r\n$GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E\r\n$GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E\r\n$GPGSV,2,1,06,04,,,13,05,,,12,20,,,21,24,,,11*7B\r\n$GPGSV,2,2,06,26,,,09,29,,,21*7A\r\n$GLGSV,1,1,00*65\r\n$GNGLL,,,,,093210.00,V,N*5D\r\n$GNZDA,093210.00,19,10,2020,00,00*78\r\n$GNTXT,01,01,02,u-blox AG - www.u-blox.com*4E\r\n$GNTXT,01,01,02,HW UBX-M8030 00080000*60\r\n$GNTXT,01,01,02,EXT CORE 3.01 (111141)*39\r\n$GNTXT,01,01,02,ROM BASE 2.01 (75331)*19\r\n$GNTXT,01,01,02,FWVER=TIM 1.10*50\r\n$GNTXT,01,01,02,PROTVER=22.00*18\r\n$GNTXT,01,01,02,MOD=NEO-M8T-0*7D\r\n$GNTXT,01,01,02,FIS=0xEF4015 (100111)*58\r\n$GNTXT,01,01,02,GPS;GLO;GAL;BDS*77\r\n$GNTXT,01,01,02,SBAS;IMES;QZSS*49\r\n$GNTXT,01,01,02,GNSS OTP=GPS;GLO*37\r\n$GNTXT,01,01,02,LLC=FFFFFFFF-FFFFFFED-FFFFFFFF-FFFFFFAE-FFFFFF69*27\r\n$GNTXT,01,01,02,ANTSUPERV=AC SD PDoS SR*3E\r\n$GNTXT,01,01,02,ANTSTATUS=OK*25\r\n$GNTXT,01,01,02,PF=3FA*4C\r\n$GNRMC,093211.00,V,,,,,,,191020,,,N*60\r\n$GNVTG,,,,,,,,,N*2E\r\n$'
```

無事に動いたのでよかった。(^^)/

# まとめ

とりあえず、docker でシリアルポートを扱うことはできた。リソースの取り扱いにはオプションがあるので、将来的にはそれらを使うことになるかもしれないので、そのときはそのとき。

(2020/10/19)