「1/2」簡単なロボット操作用ウェブアプリケーションを作ってます。「RaspberryPi3B+とDjangoChannels」


#イントロ
始めまして。s_rae です。
頑張ってプログラミングの勉強をしています。

最近簡単なロボットを作ってみました。
ホイールが2つとBluetoothモジュールをつけてあるロボットです。

アプリ開発の練習としてそのロボットを操作できるインタフェースを作ろう！と思いました。

RaspberryPi3B+にDjango+DjangoChannelsでバックエンドを作り、PyBluezでBluetoothのメッセージを送れるようにしました。

コード説明: https://qiita.com/s_rae/items/97a9845f3192f6ef4af1

まだ未完成のものですが途中までの過程でもよろしければ見て下さい。
また、母国語が日本語ではないので少し不自然かも知れませんがご了承下さい。
##お試し

####必要なもの
 - RaspberryPi3B+
    - Raspberry Pi OS (32-bit) Lite
    - Python3.7.3以上
    - pip
    - git

 - Bluetoothシリアル通信可能なロボット・IoT機器（まだ繋げられるものはすごく限定されていますがいずれいろんな機器を繋げられるようにすることが目標です。）

 - ホームサーバーなのでラズパイとクライアント側は同じネットワークに接続して下さい。

(OSの設置方法はRaspberryPiの公式ホームページを参考して下さい。Raspberry Pi Imagerを使ったら手軽に設置できます。)
####設置方法

まずはsshでラズパイにアクセスして下さい。私はLinuxのshell(bash)を使ってます。

```bash
$ ssh pi@ラズパイのIPアドレス
```

リポジトリーからcloneしてください。

```bash
$ cd ~
$ git clone https://github.com/samanthanium/dullahan_local.git
$ cd dullahan_local
```

redisをインストールして下さい。

```bash
$ wget http://download.redis.io/releases/redis-6.0.5.tar.gz
$ tar xzf redis-6.0.5.tar.gz
$ cd redis-6.0.5
$ make
```

必要なパッケージをダウンロードしてください。

```bash
$ pip install -r requirements.txt
```

プロジェクトのsettings.pyを見つけて下さい。

```bash
$ cd dullahan
```

好きなテキストエディターを使ってsettings.pyのALLOWED_HOSTSにラズパイのIPアドレスを入力して下さい。

```python:settings.py
...
ALLOWED_HOSTS = ['ラズパイのIPアドレス']
...
```

最後にテストサーバーを起動してみて下さい。

```bash
$ cd ../ #~/dullahan_local

$ python manage.py migrate

$ redis-server &
$ python manage.py runserver IPアドレス:8080 &
$ python manage.py runworker background-tasks
```

#作成過程
###目標設定
1. ラズパイとロボットをBluetoothで繋げる
2. クライアント側にキレイな操作画面を見せる
3. なんとかしてリアルタイムでロボットを操作する

ここまで出来れば第一段階成功！と思いました。

また、今Pythonを勉強し始めたところだったのでとにかくPythonで作りたいと決定しました。
###調べ段階
私が作ろうとするのはチャットシステム（？）に似てると思いました。
Robotとクライアント側がmessageを送ったり受け取ったりする感じです。

![IMG_20200702_192959120.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666250/6813c5f4-c91b-efb0-0ab7-b8d4cca2dacd.jpeg)

ここで人気のWebSocketプロトコルを使えば出来るかも！と思いました。

WebSocketはTCPの上に行われるfull-duplex(全二重?)通信です。
HTTPのようにメッセージを送るたびに通信を切るのではなく通信を保持します。

Django ChannelsはHTTP基盤のDjangoフレームワークにWebSocketの通信手段を加えます。

DjangoとDjango Channelsを使うことでHTTPでクライアントにキレイなインタフェースを転送し、WebSocketでメッセージをリアルタイムで交換できることがわかりました。

クライアント側からWebSocketメッセージをもらったらDjangoChannelsはconsumerクラス(そのメッセージを処理するclass)にメッセージを送ります。
consumer達でgroupを作りそのgroup内でメッセージを共有することも可能です。
###仕組み
色々調べて読んだ結果こんな仕組みを考えました。

![IMG_20200702_172226007.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666250/750acf1a-ec3b-05fa-952c-76d24871d83a.jpeg)

クライアント側のメッセージ処理するconsumerはロボットのconsumerがあるバックグラウンドワーカーにそのメッセージを飛ばします。

ロボットのconsumerはBluetoothでロボットにメッセージをまた送ります。ロボットからメッセージをもらうときはほぼ逆パターンで行われます。

#####ここで注意したことは：
バックグラウンドワーカーを使うことでロボットのセンサーデーターを持続的にもらうことができます。

ロボットもgroupに追加してしまうと何回も同じメッセージがロボットに送られることがあるのでこのような感じにしました。多くの改善すべき点の一つです。

###結果
こんな感じのアプリケーションになりました。
#####ホーム画面
![11-dul.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666250/d2db5554-dab2-0984-cddf-1dcdb736f8d0.png)


#####デバイス登録画面
![3-dul.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666250/244afd7d-d8fd-32e5-9849-595589a9b3ec.png)

#####コントロール画面
![6-dul.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666250/4a25f16a-c5a7-4cd7-268d-c4069b29cef5.png)

#####＋ロボット

このリンクで動作が見れます！（画像クオリティー低いです）
https://youtu.be/UL7yFSde5Hw
#所感
PythonもDjangoも自分にとって新しいものでしたので作るのにジタバタしてしまったのが残念です。

なんとか動けばいいと思って作ったらあとでコードを読み返す時大変でした。

これからも色々直して機能を追加しようと思います。

でもロボットが動いたときはとても嬉しかったです！

ここまで読んでくださりありがとうございます！