ログインしたあなたが操る[リアル]クリスマスツリー(後編)


## やったこと

『これ↓の作り方を紹介する』の後編です。前編はこちら → [前編](https://qiita.com/zgw426/items/b5e5b62ea86b1974136d)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">哀愁のクリスマスツリーをデスクトップアプリにした。LINEアカウントでログオンできる認証機能付き。どれだけ機能を豪華にしてもツリーの寂しさは埋まらない。あと、クリスマス終わってた。。 <a href="https://t.co/Laoo09NYlY">pic.twitter.com/Laoo09NYlY</a></p>&mdash; j4amountain (@zsipparu) <a href="https://twitter.com/zsipparu/status/1209937872645550080?ref_src=twsrc%5Etfw">December 25, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 実装したことと実装手段

実装した機能と実装手段を紹介します。今回は、③④の実装手順を紹介します。（①②については、前編を参照ください → [前編](https://qiita.com/zgw426/items/b5e5b62ea86b1974136d) ）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/3fa24643-df25-4136-1283-4130ff973943.png" width="400">

## 参考

- [obniz ゆるメカトロ車 LEGO構成をレシピを整えたメモ](https://www.1ft-seabass.jp/memo/2019/12/17/obniz-car-recipe/)
    - obnizでモータ―制御のスクリプトを参考（丸コピー）にさせて頂きました。
- [第8回: MJPG-streamerのインストール](https://blue-black.ink/?page_id=2245)
    - MJPG-streamerのインストールと再生方法の手順があります

---

では作っていきます。

## 回るツリーを実装しよう

写真下部にある赤い四角の物体がモーターです。これを使ってツリーを回します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/8f72d0d2-11d0-ebcc-6470-45e3c8c4af2d.jpeg" width="400">

ツリーの土台とモーターを繋げるためにLEGOを使います（LEGOテクニックという種類を使いました）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/e75fbbe2-10bd-5078-0f29-2f27ee25251c.jpeg" width="400">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/766b9e3c-9ce3-4715-b84d-4259ffbef30b.jpeg" width="400">

土台の底にLEGOをビニールテープでくっつけます。ツリーはガラス製なので、外れないようビニールテープでぐるぐる巻きにします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/6a6507d4-dcb6-a0e7-e046-cb487c3b967b.jpeg" width="350">


モーターの制御は、obnizを使います。obnizはクラウド経由で操作できるIoTデバイスです。電子工作に苦手な人でも簡単にLEDやモーターなどをobnizを使って制御できます。obnizを操作するスクリプトはhtmlファイルで書くことができます。

最初に、obnizに関するモジュールを読み込みます。

```html
<script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
<script src="https://unpkg.com/obniz@2.4.0/obniz.js" crossorigin="anonymous"></script>
```

次にボタンを作ります。

```html
<button class="btn btn-primary btn-lg active" id="forward">回転</button><BR />
<button class="btn btn-primary btn-block" id="reverse">逆回転</button><BR />
<button class="btn btn-success btn-block " id="powerup">荒ぶる</button><BR />
<button class="btn btn-success btn-block" id="powerdown">通常</button><BR />
<button class="btn btn-secondary btn-block" id="stop">止まる</button>
```

モーター動作のJavaScriptを書きます。1行目の`Obniz_ID`には、お持ちのobnizのIDを設定します。

```javascript
var obniz = new Obniz("Obniz_ID"); // 持っているobnizのIDを設定
obniz.onconnect = async function () {      
    var motor2 = obniz.wired("DCMotor", {forward:10, back:11});
    obniz.display.clear();
    obniz.display.print("Hello World");

    $('#forward').click(function () {
    motor2.reverse();
    obniz.display.clear();
    obniz.display.print("forward");
    });

    $('#reverse').click(function () {
    motor2.forward();
    obniz.display.clear();
    obniz.display.print("reverse");
    });
    
    $('#powerup').click(function () {
    motor2.power(100);
    obniz.display.clear();
    obniz.display.print("powerup");
    });

    $('#powerdown').click(function () {
    motor2.power(30);
    obniz.display.clear();
    obniz.display.print("powerdown");
    });
    
    $('#stop').click(function () {
    motor2.stop();
    obniz.display.clear();
    obniz.display.print("stop");
    });
};
```

## 回るツリーを配信しよう

ラズベリーパイ(Raspberry Pi 4 Model B)に MJPG-streamerをインストールし、ストリーミングサーバーにします。それをツリーの前に設置します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/0f82ca44-5634-7a02-0197-1699c06469da.jpeg" width="400">

MJPG-streamerをインストールします。

```console
$ sudo apt-get install build-essential libjpeg8-dev imagemagick libv4l-dev cmake -y
$ git clone https://github.com/jacksonliam/mjpg-streamer.git
$ cd mjpg-streamer/mjpg-streamer-experimental
```

makeコマンドでエラーが発生しないように、CMakeLists.txtを編集します。
以下の行の先頭に`#`を追加してコメントアウトします。

```
#add_subdirectory(plugins/input_opencv)
```

準備が整ったのでインストールを開始します。

```console
$ make
$ sudo make install
```

※なんかよくわからないのですが、↓ のようにするといいらしいです。

```console
$ ~/mjpg-streamer/mjpg-streamer-experimental
$ cp input_raspicam.so ../
```

これでインストールが完了しました。ではストリーミングを開始します。

```console
# ストリーミング起動
$ /usr/local/bin/mjpg_streamer -i "input_raspicam.so -x 640 -y 480 -fps 15 -q 80" -o "output_http.so -p 8090 -w /usr/local/share/mjpg-streamer/www" 
```

ブラウザでストリーミングサイトのURL（`http://{{raspberrypi-IP}}:8090/`）開くと、このようなサイトが開きます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/92be1b6b-5900-49db-7411-44b3182b7b48.png" width="350">


URLを変更することで、装飾なしの静止画や映像を表示することもできます。

|URL|概要|
|---|---|
|http://{{raspberrypi-IP}}:8090?action=snapshot|ブラウザ開いた時の静止画|
|http://{{raspberrypi-IP}}:8090?action=stream|ストリーミング|

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/81794a17-e8d5-9c2a-c73f-d46ff82ac10d.png" width="350">


## 自作サイトにストリーミング配信を実装しよう


JavaScriptのストリーミングサイト（`http://{{raspberrypi-IP}}:8090/?action=stream`）のhtmlソースが参考になります。
以外だったのがimgタグが使われていました。しかも、`src`には静止画のURLが設定されています。なぜストリーミングという動画系を配信するサイトにimgタグを使うのか？、なぜ静止画のURLを使うのか？これでは静止画が表示されそうですが、実際には動画が表示されます。不思議でしたがソースを読むとわかってきました。

```html:javascript.html
<img src="./?action=snapshot" width="512px" height="384px" />
```

スクリプト部分に、このような関数が定義されています。どうやらパラパラ漫画のように、画像ファイルを頻繁に更新して動画のように見せているようです。ほぉー

```js
function createImageLayer() {
    var img = new Image();
    img.style.position = "absolute";
    img.style.zIndex = -1;
    img.onload = imageOnload;
    img.onclick = imageOnclick;
    img.width = 512;
    img.height = 384;
    img.src = "./?action=snapshot&n=" + (++imageNr);
    var webcam = document.getElementById("webcam");
    window.info = document.getElementById('info').firstChild;
    window.ravgFps = document.getElementById('ravgfps').firstChild;
    window.ravgMs = document.getElementById('ravgms').firstChild;
    webcam.insertBefore(img, webcam.firstChild);
    document.getElementById('fN').firstChild.nodeValue = fN;
}
```

動画系の描画はvideoタグと思っていたのですが、videoタグはChromeで表示されないなどある (*1) ので、videoタグよりimgタグを使った方が閲覧できるブラウザが多そうです。
ということで、この仕組みはありがたく利用させていただきました。

(*1) video.js でChromeでも描画できます。詳細はこちらに書きました → [ラズパイ4とGStreamerでストリーミングサーバーを作ろう](https://qiita.com/zgw426/items/aba3db7d639a8b1a8981#%E3%82%B9%E3%83%88%E3%83%AA%E3%83%BC%E3%83%9F%E3%83%B3%E3%82%B0%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AB%E3%81%97%E3%82%88%E3%81%86)