Androidスマホで簡易監視カメラをつくる

# はじめに
こちらは[SORACOM Advent Calendar 2021](https://qiita.com/advent-calendar/2021/soracom) 12日目の記事です。
非常にハイレベルな投稿が続く中、図々しく2年連続ヒヨッコ投稿で失礼します。

本記事は [IoTLT広島特別編 with HiBiS](https://iotlt.connpass.com/event/227874/) のLTで発表した装置の実装方法について説明しています。
イベントの様子、内容については以下をご覧ください。

- [イベントの動画（YouTube）](https://www.youtube.com/watch?v=qeuLgFWURoo&t=2623)
- [発表資料（Speaker Deck）](https://speakerdeck.com/ozk009/sumahodejian-dan-iot)
- [紹介ブログ](https://fugiters.net/blog/index.php/2021/11/14/sp_iot/)

# 概要
最近、AndroidスマホでNode-REDを動かすことができる、RedMobileというものを教えてもらいました。
https://play.google.com/store/apps/details?id=com.okhiroyuki.redmobile

有償ではありますが、500円とお求めやすい価格で優秀なアプリだと思います。
このアプリを使い、定周期で画像を撮影して、SORACOMで可視化する以下のような簡易の監視カメラを作ってみたので、紹介させていただきます。
https://soracom.jp/recipes_index/2956/

# 前提
当方、以下の構成です。

- Androidスマホ：Redmi 9C（Xiaomi製）
- Androidバージョン：10
- インターネット接続環境：自宅Wi-Fi（SORACOMへの接続は後述の[SORACOM Arc](https://soracom.jp/services/arc/)を使用）

# 準備
以下を事前にやります。

1. スマホにGoogleプレイからRedMobileをインストールする
1. [しょーちゃんさんの手順](https://zenn.dev/showm001/articles/2021-06-24-01)を参考に、スマホにWireGuardをインストール、QRコードで設定し、SORACOM Arcに接続できるようにしておく
1. RedMobileはスマホがスリープになると動かないようなので、スリープをオフにしておく

# RedMobileの起動と編集画面の表示
RedMobileを起動し、Startをタップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/4622d8c1-8cdd-e2ae-26c1-9b368d23257f.png)
Node-REDが起動され、「http://（ローカルIP）:1880/red」と表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/2eec4719-60c6-4981-80b9-9bc2dcea0cc1.png)
同一ネットワークのパソコンでブラウザを起動し、先ほどの 「http://（ローカルIP）:1880/red」 にアクセスするとNode-REDの編集画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/bd498e30-ae7a-73e6-f2eb-234c9fe2db64.png)

# カメラの撮影と確認
以下にRedMobileで写真を撮影するサンプルが提供されています
https://gist.github.com/okhiroyuki/e9035569976b5e6e439b232f79abe40e
これを[インポート](https://nodered.jp/docs/user-guide/editor/workspace/import-export)（Node-RED日本ユーザ会へのリンク）すると以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/e3762966-06d2-28ea-867f-d117e5ecf251.png)

このフローで1～3を順にクリックすると撮影ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/51821305-1f08-1a1d-0a56-46a01b3f43f4.png)
さらにWebブラウザから「http://（ローカルアドレス）/api/image」にアクセスすると撮影した画像が表示できます。
・・できるはずでした。

### ハマりポイント1
この状態で撮影しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/2bec0cdc-c912-eb3b-3c24-8567ed04115e.png)

しかし「http://（ローカルアドレス）/api/image」にアクセスしても正しく画像が表示されません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/f3294fbb-3887-390a-bbde-b396abf07dce.png)
なんとなくデバッグメッセージ見てると画像データがうまく渡ってなさそうってことで以下のfunctionノードを変更してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/0f0cc28e-2556-c826-5302-bb6eb50be797.png)
変更内容は以下の通り。

```
変更前：flow.set("image",msg.payload[0]);
変更後：flow.set("image",msg.payload.split(",")[1]);
msg.payload = flow.get("image");
return msg;
```

変更後にデプロイして再度撮影してブラウザでアクセス・・
やったー！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/21989529-37d3-4dba-4e87-6702db9f7421.png)


# 撮影画像のダッシュボード表示
Node-REDにはダッシュボード機能を使い、スマホで撮影画像を確認できるようにしてみます。
dashboardのtemplateノードを追加し、functionノードに接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/de8c71f6-9182-2105-15a4-affdb749650e.png)

templateノードのグループを設定し、HTMLコードを記述します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/1926baf8-19fa-5c4e-fccb-7a6b156c270a.png)
HTMLコードは以下です。

```
<div>
      <img src="data:image/jpeg;base64,{{msg.payload}}" width="144" height="312">
</div>
```
※widthとheightは適宜変更してください。

スマホのRedMobileでダッシュボードを起動するには以下のアイコンをタップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/7db9e9b7-df7c-b6e6-5b08-30b7fee1a050.png)

デプロイして撮影・・
やったー！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/d522acd7-359c-7494-b0d7-a0f161beae97.png)

# SORACOMへのアップロード
以降はWireGuardを起動し、SORACOM Arcに接続して作業します。
## Harvest Filesへのアップロード
### SIMグループ設定
[こちらの手順](https://soracom.jp/recipes_index/2956/#_SORACOM_Harvest_Files)を参考にバーチャルSIMのSIMの所属グループを作成し、バーチャルSIMに割り当てます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/ab0b893c-f24c-021c-f9bb-418fd99376db.png)
デフォルトパスは「/sp/:time.jpg」にしました。
### ノード追加
Node-REDのfunctionノードの後ろにhttp requestノードを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/9db4f599-1569-4a7e-1e30-27aec974368c.png)
メソッドは「POST」、URLは「http://harvest-files.soracom.io」です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/33a6b4bd-3000-1179-cdcf-0a9815829345.png)
### ハマりポイント2
Harvest Filesに上げたJPEGファイルが正しく表示されませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/804fd249-df2e-deed-7a11-1e6ee44e2836.png)

結論から言うと、Content-Typeヘッダの追加とデータの変換（base64のデコード）が必要だったようで、functionノードとhttp requestノードの間にchangeノードとfunctionノードを追加したらうまくいきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/51632750-8c34-7fb5-5226-ffacf3bce373.png)
※さらっと書いてますが、基礎知識不足でかなりハマりました・・
changeノードでは「msg.headers.Content-Type」に「image/jpeg」を代入。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/8b815823-3170-9632-d86e-a641633a87f2.png)
functionノードは「msg.payload = new Buffer(msg.payload, 'base64');」を追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/beaa69b7-b504-9b44-aaba-443fc47d664b.png)

## Lagoonで可視化
[こちらの手順](https://soracom.jp/recipes_index/2956/#SORACOM_Harvest_Files_SORACOM_Lagoon_Harvest_Data)を参考にSORACOM Harvest FilesとSORACOM Lagoonを連動させ、つづけてLagoonで可視化できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/12203b3f-6de5-044b-e227-3ee740cb2243.png)
やりました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/decf74cf-e9ec-da2d-7685-12e355a5d149.png)

# 定期実行設定
これだとNode-REDのinjectノードを手動クリックでしか動かないので、自動定期実行するようにします。
やり方は簡単でcameraのノードを直結して、最初のinjectノードを定期実行にするだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/9a51d7ba-7fef-c83b-2fca-aa9c2aa87fe6.png)
例えば10分毎に写真を撮影する場合は以下とのなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/65c329b4-9466-a2b2-44a2-09f71cd50e27.png)

# 応用
実際に[イベント](https://iotlt.connpass.com/event/227874/)で発表したものは光センサーと連動させたものでした。

## Node-RED
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/af29c54e-de8b-ddc5-461f-d48f90a5e318.png)

## ダッシュボード（スマホ画面）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/df9f9d85-7b72-c340-6fb4-b05a45c226dd.png)

## SORACOM Lagoon
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/e3fef124-965f-103e-5a1a-ea194cd5ca4e.png)

また機会があれば実装方法をご紹介できればと思います。
そのほかにもスマホには以下のようなたくさんのセンサーが搭載されています。

- モーションセンサー
- ジャイロセンサー
- 音センサー
- GPS

写真やセンサーの組み合わせることで可能性が広がり、アイデア次第でいろいろできそうだと思いました。

# Special thanks
この記事はすべて以下のしょーちゃんさんのブログから始まりました。
https://zenn.dev/showm001/articles/2021-08-12-01
また[SORACOM UGのもくもく会](https://soracomug-tokyo.connpass.com/)では直接ご本人からアドバイスをいただくことができました。
参考にした[ソラコムのIoTレシピ](https://soracom.jp/recipes_index/2956/)も非常に丁寧で実用的です。
しょーちゃんさんおよび関係者の皆様、心より感謝申し上げます。
すべてのご縁に感謝しつつ、2年連続MVCの@1stshipさんにおつなぎします・・