2015年12月25日

【Python3】AWS 「API Gateway」「Lambda」「SES」を使って、RaspberryPiでのセンサー検知をメール通知してみた


◆今日のゴール

前回同様、RaspberryPiに赤外線センサーを付けて、人が近づいた事を検知します。
検知をしたら、AWSの「API Gateway」「Lambda」「SES」を使って、メールで通知するようにします。

前回は、node.jsを使いましたが、今回はpython3を使ってやります。
python2系だと、SSLのバージョンでエラーが発生するので、python3系を使います。

AWS.png


前半のAWSの設定は、前回と同様です。


Pythonのプログラムを見たい場合はこちら。


必要な道具
・赤外線モーションセンサー PIR Infrared Motion Sensor


AWSのアカウント
利用にあたり、AWSの利用料金がかかる場合があります。


スポンサードリンク
◆手順
  1. Amazon SES(Simple Email Service)のセットアップ
  2. AWS IAM(Identity and Access Management)でポリシー・ロールの作成
  3. AWS Lambdaの関数作成とAPI Gatewayの設定(APIキーの発行)
  4. 【Python3】でRaspberryPiで、検知したらAPIをコールするプログラムを作成
  5. 動かしてみる
1、Amazon SES(Simple Email Service)のセットアップ

ここでは、送信元と送信先となるeメールアドレスの認証(verify)作業を行います。
今回は、送信元と送信先を同一アドレスにしますので、1つのアドレスに対してのみ認証作業を行いますが、送信元・送信先のメールアドレスを分けたい場合や、複数の宛先に送りたい場合は、そのメールアドレスに対しても認証作業を行ってください。

【補足】SESはデフォルトで、Sandboxという環境下で動いています。SESをSandboxの外に出す申請をすることで、認証していない宛先にもメールを送信することができるようになります。

Amazon AWSのコンソール画面にログインして、SESを開きます。
今回、リージョンは、「オレゴン(us-west-2)」とします。

SESのメニューから「Email Addresses」をクリックします。
ses001.png

「Verify a New Email Address」ボタンをクリックします。
ses002.png

今回使用するメールアドレスを入力します。
ses003.png

Statusが「pending verification」(認証待ち)となっているアドレスが追加されます。
ses004.png

メールアドレス宛にAWSからメールが届きます。
「Amazon SES Address Verification Request in region US West (Oregon)‏」

ses005.png

メールの本文に記載されているURLをクリックすると、認証(verify)が完了し、更新するとステータスが「pending verification」から「verified」に変わります。
ses006.png
以上で、メールアドレスの認証は完了です。
他のメールアドレスも登録したい場合は同様の手順を繰り返してください。

2、AWS IAMでポリシー・ロールの作成

SESでメールを送信する権限をもつポリシー・ロールを定義します。
AWSコンソール画面でIAM(Identity and Access Management)を開き、メニューから「ポリシー」をクリックします。ポリシー一覧画面が開きます。「ポリシーの作成」ボタンをクリックします。
iam001.png
「独自のポリシーを作成」を「選択」します。
iam002.png
ポリシー名に「RaspiSesSendMail」
ポリシードキュメントを下記の通り、入力して「ポリシーの作成」をクリックします。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ses:SendEmail",
                "ses:SendRawEmail"
            ],
            "Resource": "*"
        }
    ]
}
iam003.png
続いて、このポリシーをアタッチしたロールを作ります。
メニューから「ロール」をクリックしロール一覧画面を開きます。
「新しいロールの作成」をクリックします。
iam005.png
ロール名に「raspiSES」と入力します。
iam006.png
ロールタイプの選択で「AWSサービスロール」>「AWS Lambda」を「選択」します。
iam007.png
ポリシーのアタッチで、先ほど作成したポリシー「RaspiSesSendMail」にチェックを入れて「次のステップ」をクリックします。
iam008.png
最後に確認画面が出ますので、「ロールの作成」をクリックします。
iam009.png
これで、「raspiSES」というロールが作られました。
iam010.png

3、AWS Lambdaの関数作成とAPI Gatewayの設定(APIキーの発行)

AWSコンソール画面でLambdaを開きます。
ブループリント(青写真)を選ぶ画面がでますが、ここでは「Skip」を押して、白紙の状態から始めます。
lam001.png

【Configure Function】Name*「raspiSendMail」、Runtime*「Node.js」とします。
lam002.png

Lambda Function Codeは下記の通り入力します。メールアドレスは手順1でverifyしたメールアドレスに書き換えてください。
console.log('Loading function');
var aws = require('aws-sdk');
var ses = new aws.SES({
    apiVersion: '2010-12-01',
    region: 'us-west-2' // SES の設定をオレゴンでおこなった場合。
});

var to = ['toAddress@hogehoge.com']; // SESでverify済みのメールアドレス。(送信元)
var from = 'fromAddress@hogehoge.com';  // SESでverify済みのメールアドレス。(送信先)

// メールの本文
var text = "\
こんにちは\n\
\n\
Raspberry piです。\n\
\n\
赤外線センサーが検知しました。\n\
このメールはSESで配信しています。\n\
\n\
\
";

exports.handler = function(event, context) {
    console.log("Incoming: ", event);

    var eParams = {
        Destination: {
            ToAddresses: to
        },
        Message: {
            Body: {
                Text: {
                    Data: text,
                    Charset: 'iso-2022-jp'
                }
            },
            Subject: {
                Data: 'RaspberryPiが人感赤外線センサーで検知しました。',
                Charset: 'iso-2022-jp'
            }
        },
        Source: from
    };

    console.log('===SENDING EMAIL===');
    var email = ses.sendEmail(eParams, function(err, data){
        if(err){
            console.log("===EMAIL ERR===");
            console.log(err);
            context.fail(new Error('mail error occured'));
            
        } else {
            console.log("===EMAIL SENT===");
            console.log(data);
            context.succeed('SUCCESS');
        }
    });
    console.log("EMAIL CODE END");
};
【Lambda function handler and role】でハンドラーとロールを下記の通り設定します。
Handler * 「index.handler」(デフォルトのまま)
Role * 「raspiSES」(手順2で作ったロールを設定します。【重要!】)

Advanced Settingsはお好みで変更してください。

「Next」をクリックします。
lam003.png

確認画面がでますので「Create function」をクリックします。
lam004.png
下記の画面に遷移しますので、「API endpoints」のタブをクリックします。
lam005.png
「Add API endpoint」をクリックします。
lam006.png
【API endpoint type】に「API Gateway」を選択します。
lam007.png

下記の通り入力し「Submit」をクリックします。(今回は、アクセスキーでAPIの認証を行います。)
【API endpoint type】API Gateway
【API name】Raspi
【Resource name】/mail
【Method】POST
【Deployment Stage】prod
【Security】Open with access key
lam008.png

「Submit」をクリックと下記の通り、「API」が作成されます。
【API endpoint URL】がAPIのendpointになります。このURLは次の手順で使用します。
lam009.png

上記画面で【Method】「POST」のリンクをクリックします。API Gatewayの管理画面に遷移します。
api001.png
メニューから「APIs」>「API Keys」をクリックします。 api002.png
新しくAPI Keyを生成します。Name「raspi」、Enabledにチェックを入れ「Save」をクリックします。
api003.png
【API Stage Association】
で下記の通り選択し「Add」をクリックします。
Select API「Raspi」
Select stage「prod」

「Add」をクリックするとStages Enabledに追加されます。
ここの画面で表示されている「API Key」は次の手順で使用します。
api004.png

AWSのセットアップはこれで終了です。
「API endpoint URL」、「API Key」は次の手順で使用します。

4、【Python3】でRaspberryPiで、検知したらAPIをコールするプログラムを作成

ここからは、Raspberry Piで作業します。
今回はpython3を使用します。

ちなみに、Python2系とPython3系では、printの書き方が違います。 Python2
print "raspberry pi"
Python3は括弧が必要です。
print("raspberry pi")

今回は、httplib2というモジュールを使うので事前にインストールします。
sudo apt-get install python3-httplib2
続いて、下記の通り赤外線センサーを接続します。
VCCに「RaspberryPiの5V」
OUTに「RaspberryPiのGPIO26番」
GNDに「RaspberryPiのGND」


赤外線センサーで検知したら、APIを呼び出すプログラムをPythonで書きます。
$ sudo vi motion_mail.py
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import time
import RPi.GPIO as GPIO
import httplib2

# センサーのGPIOピンの番号
pir_pin = 26

sleeptime = 100000
waiting_time = 1

GPIO.setmode(GPIO.BCM)
GPIO.setup(pir_pin, GPIO.IN)


header = {
  "x-api-key" : "手順3で発行したAPI Key",
  "Content-type" : "application/json",
  "Accept" : "application/json"
}
url = "手順3で発行したAPI endpoint URL"

def motion_detected(pir_pin):
  print ("検知")

  h = httplib2.Http()

  resp, content = h.request(url, "POST", headers = header)

  print (resp.status)
  print (resp.reason)

  time.sleep(waiting_time)

# コールバック登録
GPIO.add_event_detect(pir_pin, GPIO.RISING, callback=motion_detected)

try:
  while True:
    print ("App Start")
    print ("ctrl+c  :  if you want to stop app")
    time.sleep(sleeptime)
except KeyboardInterrupt:
  print ("Quit")
finally:
  print ("clean up")
  GPIO.cleanup()
上記の様に、編集したら保存します。
18行目は「手順3で発行したAPI Key」に置き換えてください。
22行目は「手順3で発行したAPI endpoint URL」に置き換えてください。

5、動かしてみる

下記、コマンドでプログラムを実行します。
$ sudo python3 motion_mail.py
下記の様に待機状態になります。センサーに手をかざしてみましょう。
$ sudo python3 motion_mail.py
App Start
ctrl+c  :  if you want to stop app
検知するとAPIが呼び出され200が返ってきます。
メールを確認してみましょう!届いていれば成功です!
$ sudo python3 motion_mail.py
App Start
ctrl+c  :  if you want to stop app
検知
200
OK
プログラムを終了させるには、ctrl+cを押します。
 $ sudo python3 motion_mail.py
App Start
ctrl+c  :  if you want to stop app
検知
200
OK
^CQuit
clean up

以上で終了です。
Raspberry PiのpythonからAWS API GatewayのREST APIを呼び出すことができました。



posted by Raspberry Pi at 11:09 | Comment(0) | Raspberry Pi | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。