LoginSignup
22
15

More than 5 years have passed since last update.

Raspberry Pi内の画像をbase64でエンコードして→AWS IoT→S3に保存

Last updated at Posted at 2017-11-11

カメラ などで撮影した画像を AWS IoT 経由で S3 に保存してみたくて試してみました。
今回はホストPCからRaspberry Piにアップした画像を使っています。
プログラムはサンプルプログラムを使用しています。
まだAWSについて知識が浅いので、コメントいただけるとありがたいです!

【追記】
ちなみに、base64エンコードしなくてもバイナリデータのままで送信してS3に保存できます。
その方が、S3からダウンロードしてそのまま画像がみれます。

こちら参考にさせていただきました!

前提など

制約事項

参考の方にも記載がありますが、AWS IoTとの1回の送信は 最大128KBの制約 ありますので、注意してください!
AWS IoTの制限

【2018/01/19 追記】
128KB超えデータのアップロードについては、ラージアップロードパターンというものを使用するとよさそうです。
これはアップロードする前に毎回、AWS IoT、STSを使用してトークンを取得し、そのトークンを使用してS3へデバイスから直接アップロードするパターンです。
これにより、アクセスキーやシークレットキーをデバイス側に持たなくて済み、AWS IoTの証明書のみでアクセス管理ができる。
参考URL:AWSIoT ラージデータアップロードパターン実装

AWS IoTを使用することのメリット

【2018/01/19 追記】
あくまでも個人的な意見ですが、

  • AWS IoTをデバイスのIFにして、いくつもAWSへの送信パターン(※)がある場合
  • AWS IoTに登録されている証明書のみでアクセスができる(キーをいくつも管理しなくてもよくなる)

もし、デバイスからAWSへのアクセス権をなくしたい場合(デバイスの盗難など)、AWSコンソールからAWS IoTで管理している証明書を無効にするだけで、アクセス権をなくせます(デメリットにもなくかもですが・・・)。

戻す場合は、証明書を有効化すればまたアクセス可能となります。

※例
センシングデータ → AWS IoT → DynamoDB
画像データ → AWS IoT → S3(ちなみに128KB)
イベント発生 → AWS IoT → Lambda実行

使用するもの

前提条件

  • AWS側
  • Raspberry Pi側
    • OSインストールが完了し、ネットワーク、SSHの接続ができること

AWS 側の準備

準備を行います

  • S3に保存先のバケットを作成
  • AWS IoTでルールを作成

AWS IoTでルール、S3バケットを作成

AWS コンソールから「AWS IoT」をひらく
「ACT」をクリック
AWS_IoT_1.png

「作成」をクリック
AWS_IoT_2.png

「名前」「説明」を入力
AWS_IoT_3.png

「属性:*」「トピックフィルター:sdk/test/Python」を入力
※トピックは送信時に設定するtopicです
AWS_IoT_4.png

「アクションの追加」でS3アクションを追加
AWS_IoT_5.png

「S3」を設定して「アクションの設定」をクリック
AWS_IoT_6.png

S3アクションの詳細はこちらを参照
「新しいリソースを作成する」でS3バケットを追加
AWS_IoT_7.png

「バケットを作成する」をクリック
S3_Management_Console.png

「バケット名」を入力して「次へ」
S3_Management_Console_1.png

「次へ」
S3_Management_Console_2.png

「次へ」
S3_Management_Console_3.png

「バケットを作成」
S3_Management_Console_4.png

S3_Management_Console_5.png

「S3バケット」横の更新ボタンをクリックして、作成したS3バケットを選択
「新しいロールの作成」も行う
AWS_IoT_9.png

「IAMロール名」入力して「新しいロールの作成」をクリック
AWS_IoT_10.png

「キー:\${topic()}/${timestamp()}」を入力して「アクションの追加」をクリック
※キーはこちらを参照
※【追記】キーを「\${topic()}/${timestamp()}.png」にすればS3で画像データとして認識されます
※画像は「更新」になっている理由:新規登録後、キーをかえるために更新を行ったためです
AWS_IoT_14.png

「ルールを作成する」をクリックで完成です!
AWS_IoT_13.png

Raspberry Pi 側の準備

必要なライブラリ等をインストール

  • 仮想環境を作成
# テスト用のディレクトリ作成
pi@chinopi:~ $ mkdir aws_iot_test
pi@chinopi:~ $ 
pi@chinopi:~ $ cd aws_iot_test/
pi@chinopi:~/aws_iot_test $ 
# 仮想環境
pi@chinopi:~/aws_iot_test $ sudo apt-get install python3-venv
Reading package lists... Done
Building dependency tree       
Reading state information... Done
・
・
・
pi@chinopi:~/aws_iot_test $ 
# テスト用の仮想環境作成
pi@chinopi:~/aws_iot_test $ python3 -m venv env
pi@chinopi:~/aws_iot_test $ 
# 仮想環境のactivate
pi@chinopi:~/aws_iot_test $ source env/bin/activate
(env) pi@chinopi:~/aws_iot_test $ 
(env) pi@chinopi:~/aws_iot_test $ python -V
Python 3.4.2
(env) pi@chinopi:~/aws_iot_test $
  • SSLのバージョン確認

AWS IoT Device SDK for Python
README の「Installation - Minimum Requirements」を参照

# SSLのバージョン確認
(env) pi@chinopi:~/aws_iot_test $ python 
Python 3.4.2 (default, Oct 19 2014, 13:31:11) 
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 1.0.1t  3 May 2016'
>>> 
>>> exit()
(env) pi@chinopi:~/aws_iot_test $
(env) pi@chinopi:~/aws_iot_test $ pip install AWSIoTPythonSDK
Downloading/unpacking AWSIoTPythonSDK
  Downloading AWSIoTPythonSDK-1.2.0.tar.gz (67kB): 67kB downloaded
  Running setup.py (path:/tmp/pip-build-n3u557w8/AWSIoTPythonSDK/setup.py) egg_info for package AWSIoTPythonSDK

Installing collected packages: AWSIoTPythonSDK
  Running setup.py install for AWSIoTPythonSDK

Successfully installed AWSIoTPythonSDK
Cleaning up...
(env) pi@chinopi:~/aws_iot_test $ 
  • サンプルプログラムのclone、証明書等の配置ディレクトリの作成
(env) pi@chinopi:~/aws_iot_test $ git clone https://github.com/aws/aws-iot-device-sdk-python.git
Cloning into 'aws-iot-device-sdk-python'...
remote: Counting objects: 165, done.
remote: Total 165 (delta 0), reused 0 (delta 0), pack-reused 165
Receiving objects: 100% (165/165), 123.27 KiB | 170.00 KiB/s, done.
Resolving deltas: 100% (61/61), done.
Checking connectivity... done.
(env) pi@chinopi:~/aws_iot_test $ 
(env) pi@chinopi:~/aws_iot_test $
(env) pi@chinopi:~/aws_iot_test $ cd aws-iot-device-sdk-python/
(env) pi@chinopi:~/aws_iot_test/aws-iot-device-sdk-python $ ls
AWSIoTPythonSDK  CHANGELOG.rst  LICENSE.txt  MANIFEST.in  NOTICE.txt  README.rst  samples  setup.cfg  setup.py
(env) pi@chinopi:~/aws_iot_test/aws-iot-device-sdk-python $ 
# 証明書配置用のディレクトリ
(env) pi@chinopi:~/aws_iot_test/aws-iot-device-sdk-python $ mkdir certs
(env) pi@chinopi:~/aws_iot_test/aws-iot-device-sdk-python $ 

証明書等をRaspberry Pi に配置

  • SCPで証明書を使用して転送
# ホストPCで実行(プログラム実行時に使用)
$ ls
XXXXXXXXXX-certificate.pem.crt XXXXXXXXXX-private.pem.key     XXXXXXXXXX-public.pem.key      root-CA.crt
$ 
# 証明書
$ scp ./XXXXXXXXXX-certificate.pem.crt pi@chinopi.local:/home/pi/aws_iot_test/aws-iot-device-sdk-python/certs
・・・
$ 
# プライベートキー
$ scp ./XXXXXXXXXX-private.pem.key pi@chinopi.local:/home/pi/aws_iot_test/aws-iot-device-sdk-python/certs
・・・
$ 
# ルートCA証明書
$ scp ./root-CA.crt pi@chinopi.local:/home/pi/aws_iot_test/aws-iot-device-sdk-python/certs
・・・
$
  • テスト用の画像も転送(プログラム実行時に使用)
# ホストPCで実行
$ ls -la test.png
-rw-r--r--@ 1 chinoyuuji  staff  37362 11  7 18:25 test.png
$ 
$ scp ./test.png /home/pi/aws_iot_test/aws-iot-device-sdk-python/samples/basicPubSub
・・・
$ 

プログラム準備、実行

画像をbase64に変更

(env) pi@chinopi:~ $ cd aws_iot_test/aws-iot-device-sdk-python/samples/basicPubSub/ $
(env) pi@chinopi:~/aws_iot_test/aws-iot-device-sdk-python/samples/basicPubSub $ cp basicPubSub.py basicPubSub_base64.py
(env) pi@chinopi:~/aws_iot_test/aws-iot-device-sdk-python/samples/basicPubSub $ ls -la
total 72
drwxr-xr-x 2 pi pi  4096 Nov 10 16:12 .
drwxr-xr-x 6 pi pi  4096 Nov 10 13:28 ..
-rw-r--r-- 1 pi pi  4414 Nov 10 13:28 basicPubSubAsync.py
-rwxr-xr-x 1 pi pi  3834 Nov 10 13:28 basicPubSub_CognitoSTS.py
-rwxr-xr-x 1 pi pi  4149 Nov 10 16:12 basicPubSub_base64.py
-rwxr-xr-x 1 pi pi  3874 Nov 10 13:28 basicPubSub.py
-rw-r--r-- 1 pi pi 37362 Nov 10 15:17 test.png
(env) pi@chinopi:~/aws_iot_test/aws-iot-device-sdk-python/samples/basicPubSub $ cb basicPubSub.py basicPubSub_copy.py
(env) pi@chinopi:~/aws_iot_test/aws-iot-device-sdk-python/samples/basicPubSub $ vi basicPubSub_copy.py 

「★★・・・★★」部分を変更、追加
※【追加】bytearrayの部分をバイナリデータとすればそのままバイナリデータを送信できます

basicPubSub_base64.py

〜〜〜〜〜〜〜〜〜

from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import logging
import time
import argparse
# ★★追加★★
import base64

〜〜〜〜〜〜〜〜〜

time.sleep(2)

# Publish to the same topic in a loop forever
# ★★コメントにする★★
# loopCount = 0
# while True:
#     myAWSIoTMQTTClient.publish(topic, "New Message " + str(loopCount), 1)
#     loopCount += 1
#     time.sleep(1)
# ★★追加★★
binary = open('test.png', 'rb').read()
binary_base64 = base64.b64encode(binary)
myAWSIoTMQTTClient.publish(topic, bytearray(binary_base64), 1)

※ base64エンコードしたデータを送信しようとした時に以下エラーが発生したため、「bytearray」に変換しています

TypeError: payload must be a string, bytearray, int, float or None.

プログラム実行

実行形式はこちら

python basicPubSub_base64.py -e [エンドポイント] -r [ルートCA証明書] -c [証明書] -k [プライベートキー]

※ エンドポイントはこちらを参照:Raspberry Pi の接続

プログラム実行

(env) pi@chinopi:~/aws_iot_test/aws-iot-device-sdk-python/samples/basicPubSub $
(env) pi@chinopi:~/aws_iot_test/aws-iot-device-sdk-python/samples/basicPubSub $ python basicPubSub_base64.py -e XXXXXXXXXXXXXX.iot.ap-northeast-1.amazonaws.com -r ~/aws_iot_test/aws-iot-device-sdk-python/certs/root-CA.crt -c ~/aws_iot_test/aws-iot-device-sdk-python/certs/XXXXXXXXXX-certificate.pem.crt -k ~/aws_iot_test/aws-iot-device-sdk-python/certs/XXXXXXXXXX-private.pem.key
2017-11-11 12:33:45,590 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Initializing MQTT layer...
2017-11-11 12:33:45,609 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Registering internal event callbacks to MQTT layer...
・
・
・
2017-11-11 12:33:48,378 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - This custom event callback is for pub/sub/unsub, removing it after invocation...
(env) pi@chinopi:~/aws_iot_test/aws-iot-device-sdk-python/samples/basicPubSub $

S3に保存されたデータを確認

S3 からダウンロード

AWS コンソールのS3をひらく
作成したS3バケット名をクリック
S3_Management_Console_6.png

フォルダ名をクリックしていく
S3_Management_Console_7.png

S3_Management_Console_8.png

S3_Management_Console_9.png

S3_Management_Console_10.png

ファイルのチェックボックスをチェックして、ダウンロード
S3_Management_Console_12.png

ホストPCでデコードして画像をみてみる

$ 
$ ls -la 1510409639497
-rw-r--r--@ 1 chinoyuuji  staff  49816 11 11 23:16 1510409639497
$ python3
Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> import base64
>>> 
>>> text = open('1510409639497', 'rt').read()
>>> 
>>> binary = base64.b64decode(text)
>>> 
>>> f = open('test_1.png', 'wb')
>>> f.write(binary)
37362
>>> f.close()
>>> 

test_1.png をひらいて画像が表示されればOK!

22
15
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
15