[はじめてのRDBOX(2)]rdbox使ってみました：画像参照アプリの構築編

# はじめに
ROS の初心者が、とっても簡単なROSアプリを作ってみました。（連載記事です）
- 今回は、RDBOX や ROS 等の話は出てきません
- 今回は、本記事の目的である RDBOX/ROS アプリ関連技術とは直接関係がないため、多くを省略した記事となっていることを、ご了承ください

# 今回の記事の概要
- Flask を使って、あるディレクトリに存在するファイルの一覧を表示し、指定された画像ファイルの表示を担当するアプリを構築する
- 今回の記事に該当するソースファイルは、以下のアドレスから参照可能です
  - https://github.com/higuchi-toshio-intec/example-picam/tree/master/picam_viewer

# 使用環境
- 特に明記しない限り、この連載では Docker 環境を使用しています
- Docker 環境起動

  ```
  $ sudo docker pull ubuntu:18.04
  $ sudo docker run -dit --name hajimete_rdbox --net host ubuntu:18.04
  $ sudo docker exec -it hajimete_rdbox /bin/bash
  root@hajimete_rdbox:/#
  ```

- 必要に応じて update やツール類（以下の例では vim や curl）のインストールします

  ```
  root@hajimete_rdbox:/# apt update
  root@hajimete_rdbox:/# apt upgrade
  root@hajimete_rdbox:/# apt install -y vim curl [その他必要に応じてパッケージ]
  ```


# 仕様と構築
- Flask アプリの説明はほとんど省略させてもらいます
  - Flask の基本的な使用方法は、他者の記事を参照された方が役立つはずです
- 環境変数 PICAM_PORT で指定されたポート番号でブラウザからの接続を待ちます
- 環境変数 PICAM_DATA で指定されたディレクトリ以下に画像ファイルが存在すると想定します

## パッケージ導入
- 今回の記事で必要となるパッケージを導入

  ```
  $ sudo apt install -y python python-flask
  ```

## ファイルの作成
- 以下(↓)は具体的な手順（下記例では、GitHubよりファイルを取得）

  ```
  $ mkdir -p ${HOME}/picam_viewer
  $ cd ${HOME}/picam_viewer
  $ mkdir -p app/templates/photo
  $ cd app
  $ curl -s -o picam_viewer.py https://raw.githubusercontent.com/higuchi-toshio-intec/example-picam/master/picam_viewer/app/picam_viewer.py
  $ cd templates/photo
  $ curl -s -o list.html https://raw.githubusercontent.com/higuchi-toshio-intec/example-picam/master/picam_viewer/app/templates/photo/list.html
  $ curl -s -o view.html https://raw.githubusercontent.com/higuchi-toshio-intec/example-picam/master/picam_viewer/app/templates/photo/view.html
  ```

## app/picam_viewer.py
- 今回の記事のアプリ本体

### ソースファイルの主要部分説明
- ブラウザから '/' でのアクセスで画像ファイル一覧を表示
  - 処理内容は、'/photo/list' へのアクセスと同様なので、関数 photo_list() を呼び出して終了している

```
@app.route('/')
def photo_root():
    return photo_list()
```

- ブラウザから '/photo/list' でのアクセスで画像ファイル一覧を表示
  1. 蓄積されている画像データの「年月」情報を取得
  1. 指定された「年月」の画像データファイルの一覧を取得
  1. テンプレート(photo/list.html)をもとに一覧表示

```
@app.route('/photo/list')
def photo_list():
    args = {}
    args['list_yyyymm'] = list_photo_yyyymm()
    args['sel_yyyymm'] = request.args.get('view_year')
    if (args['sel_yyyymm'] == ""):
        args['sel_yyyymm'] = args['list_yyyymm'][0]

    #
    args['list_photo'] = list_photo(args['sel_yyyymm'])

    #
    body = render_template("photo/list.html", args=args)
    return body
```

- ブラウザから '/photo/view' でのアクセスで画像ファイルを表示
  1. 指定された「画像ファイルID」を取得し、念のため不正な文字を削除
  1. 画像ファイルが存在する場合、画像ファイルを表示
  1. 画像ファイルが存在しない場合、テンプレート(photo/view.html)をもとに「該当画像なし」と表示

```
@app.route('/photo/view')
def photo_view():

    # remove wrong chars
    photo_id0 = request.args.get('photo_id')
    photo_id1 = re.sub(r"[^0-9a-zA-z_\.\/\-]", "", photo_id0)
    sta = exists_photo(photo_id1)
    print("[DBG] %s : %s" % (photo_id1, sta))
    if (sta):
        filename = get_filename_photo(photo_id1, '.jpg')
        d = os.path.dirname(filename)
        f = os.path.basename(filename)
        print("[DBG] %s : %s" % (d, f))
        return send_from_directory(d, f)

    #
    body = render_template("photo/view.html")
    return body
```

- その他の関数
  - 文字列操作やファイル操作であるため、説明は省略

## templates/photo/list.html
- 画像ファイル一覧表示用 Flask テンプレート
  - 画像ファイル一覧を表形式(tableタグ)で表示
  - ボタンクリックで、該当画像表示(view処理)を実行(javascript連携)

## templates/photo/view.html
- 画像ファイル表示用 Flask テンプレート
  - 『該当画像なし』を表示

# アプリ起動
```
export PICAM_PORT=8080
export PICAM_DATA=/opt/picam_data
mkdir -p ${PICAM_DATA}
cd ${HOME}/picam_viewer/app
python picam_viewer.py
```

## ブラウザからのアクセス
- ブラウザを起動し以下のアドレスを参照する
  - http://サーバアドレス:8080/
- 現時点で、データがないためブラウザには、ほとんど何も表示されません（空のプルダウン程度が表示される）

---
# 記事リスト
1. [概要編](https://qiita.com/higuchi-toshio-intec/items/5d5499447d667e339b87)
2. [画像参照アプリの構築編](https://qiita.com/higuchi-toshio-intec/items/1deae0d03a74bafec8af)（← 今回の記事）
3. [ROSパッケージ作成編](https://qiita.com/higuchi-toshio-intec/items/44f1377c171738d9b49b)
4. [ROS Subscriber編](https://qiita.com/higuchi-toshio-intec/items/3d62bbfc5e520de9dce1)
5. [ROS Publisher編](https://qiita.com/higuchi-toshio-intec/items/0c136f4d90e70983a8a3)
6. [DockerImage 作成編](https://qiita.com/higuchi-toshio-intec/items/826b4c5407b05372b78c)
7. [RDBOX(k8s) ポート転送編](https://qiita.com/higuchi-toshio-intec/items/b3b79da5ca160ee418b0)
8. [RDBOX(k8s) Subscriber アプリ編](https://qiita.com/higuchi-toshio-intec/items/765d7ef1b6baf85d9f02)
9. [RDBOX(k8s) Publisher アプリ編](https://qiita.com/higuchi-toshio-intec/items/9c43e001d8098a6c7a40)
10. [雑記](https://qiita.com/higuchi-toshio-intec/items/5d80fd647514dfbd2938)