Raspberry Pi Camera with enebular


Raspberry Pi Camera with enebular

はじめに

この記事では、デバイスで定期的にカメラを撮像し、S3へ格納するフローを作成していきます。

Raspberry Pi 4で遊んで見たかっただけ
もしかしたら養殖支援システムで使うかもしれないので、その勉強用とメモです。

準備

  • デバイス
  • OSセットアップ
    • Raspbian (今回はRaspbian Buster 2019-09-26を利用)
  • AWS アカウント
    • A.IoT Core でThingsを作成できる、IAM と Credential情報(enebular-agentで使用)
    • B.enebularのフローデプロイで使用するConnection用 IAM と Credential情報 (後述)
    • C.フローの処理の中でS3バケットへ格納ための IAM と Credential情報 (後述)

権限設定

カメラデバイスを有効にする

$ sudo raspi-config 

┌─────────┤ Raspberry Pi Software Configuration Tool (raspi-config) 
│ 〜 中略 〜
│  5 Interfacing Options  Configure connections to peripherals              

┌─────────┤ Raspberry Pi Software Configuration Tool (raspi-config) 
│  P1 Camera      Enable/Disable connection to the Raspberry Pi Camera         

          ┌──────────────────────────────────────────────────────────┐
          │                                                          │ 
          │ Would you like the camera interface to be enabled?       │ 
          │               <Yes>                  <No>                │ 
          │                                                          │ 
          └──────────────────────────────────────────────────────────┘ 

<Yes> を選択

enebular-agentインストール

Raspberry Piにログインして enbular-agentをインストール手順に従ってインストールします。

$ wget -qO- https://enebular.com/agent-install | \
  sudo -E bash -s -- \
  --aws-iot-thing-name=enebular-agent-my-camera \
  --aws-access-key-id=AKIA**************** \
  --aws-secret-access-key=**************************************** \
  --aws-iot-region=ap-northeast-1 \
  --user=pi \
  --remote-maintenance-user-password=enebular

インストール時のログ
=================================================================================================================
 enebular-agent installation:
   - Device name:         tomono-pi4-suisui
   - System:              Linux 4.19.75-v7l+ armv7l GNU/Linux
   - Install user:        pi
   - Install destination: /home/pi/enebular-runtime-agent
   - Agent port:          awsiot
   - Agent version:       latest-release

... (省略)...

=================================================================================================================
 enebular-agent has been successfully installed ✔
   - Version: 2.9.1
   - Location: /home/pi/enebular-runtime-agent
   - User: pi
   - Service name: enebular-agent-pi

 AWS IoT Thing enebular-agent-my-camera has been created.
 enebular-agent is running as a system service.
 To check the status of agent, run the following command on the target device:
   sudo journalctl -ex -u enebular-agent-pi.service
=================================================================================================================
See details in full install log file: /tmp/enebular-agent-install-log.orIrop

Connection を作成

続いて、enebularからデプロイするためのAWS IoT CoreへのConnectionを作成します。

空のフローの状態で、Deploy ができることを確認しておきます。

Flow を作成

以下のnodeモジュールをenebularフローエディタ上のadminタブからインストールします。
- node-red-contrib-camerapi
- node-red-contrib-aws

次に、ノードを以下のように配置して接続していきます。

また、適宜デバッグ出力ノードを入れます。

  • ノード設定
    1. 入力 - inject : 定期実行
    2. その他 - exec : ホスト名取得
    3. 機能 - switch : 実行環境判定
    4. Raspberry Pi - camerapi takephoto : 撮影
    5. 機能 - function :S3オブジェクト情報へ変換
    6. AWS - AWS S3 : S3 PutObject

各ノードを以下の設定をしていきます。
なお、特に記載していないものはデフォルトのままです。

1. 定期実行

設定 設定値
Node-RED起動の {N} 秒後、以下を行う チェック
{N} 秒後 0.1
繰り返し 指定した時間間隔
時間間隔 1
時間間隔

2. ホスト名取得

設定 設定値
コマンド hostname
引数 msg.payload チェックを外す

3.実行環境判定

ここで、実行ホスト名による分岐を行います。
この処理が無いと、enebularをホスティングしているサーバーで定期的に実行され 空(0バイト)の画像がS3バケットに格納されてしまいます。
条件1にこのフローがエッジデバイス上で実行されている場合の条件を、
条件2でサーバーで動いている場合に分けます。

次に注意するポイントとして、一つ前の「ホスト名取得」の実行結果msg.payloadに改行コードが入っています。
単純な文字列比較(==)の場合\をエスケープしてくれる(改行コードを入れられないという制約がある)ため、JSONataの$trim関数で改行コードを除いて比較を行います。

設定 設定値
条件1 JSONata式 : $trim(payload)="{Raspberry Piのホスト名}"
条件2 その他
終了条件 最初に合致した条件で終了

4. 撮影

設定 設定値
File Mode Buffered Mode
Image Resolution 320x240 (※任意の値に設定してください)

今回は解像度について、アップロードのテストのため最小の解像度を選択しています。
ファイルサイズと予算にあった設定を行ってください。

5. S3オブジェクトへ変換

S3バケットへ格納するキー名(Key)と中身(Body)を設定します。

const now = new Date();
const filename = ('0000' + (1900 + now.getYear())).slice(-4) + 
  ('00' + (1 + now.getMonth())).slice(-2) + 
  ('00' + now.getDate()).slice(-2) +
  ('00' + now.getHours()).slice(-2) + 
  ('00' + now.getMinutes()).slice(-2) + 
  ('00' + now.getSeconds()).slice(-2) + 
  '.jpg';

msg = msg || {};
msg.Key = 'test/' + filename;
msg.Body = msg.payload;

return msg;

6. S3 PutObject

あらかじめS3バケットの PutObject の権限を持ったIAMユーザー(準備.C)のCredential情報を入力していきます。
また、S3には格納用のS3バケットを作成しておきます。
- AWS設定

設定 設定値
Region ap-northeast-1 (※任意のリージョンを設定)
Access Id AKIA*************
Secret Key ************
設定 設定値
Operation PutObject
Bucket {バケット名}
Key test/dummy

実行結果

期待通り、1分置きに画像が格納されている。

撮影した画像の結果

まとめ

細かいハマりポイントを除けば比較的簡単に環境を構築できました。
エッジ側で機械学習したモデルを使って処理させたりしたら、面白いことできそう。