AWS IoT エンタープライズボタン Raspberry Piで写真を撮ろう

社内に例のボタンが先日届いたので使ってみました。

よく見る使い方ですが、ポチっと押すとラズパイに繋げたWebカメラが写真を撮り、
S3にアップロードしたりSlackに投稿したりするのを試してみましょう。

 

目次

撮影テスト
AWS IoTの設定
実行スクリプトの編集
Lambda関数の変更
IoT 1-Clickの設定
slackへの投稿

 

撮影テスト

今回はfswebcamを使って写真を撮ります。

ラズパイへsshし、apt-get install fswebcamでfswebcamをインストールし、
fswebcam test.jpgでテスト撮影してみましょう。

 

AWS IoT エンタープライズボタン

 

無事写真が撮れたようです。

 

AWS IoTの設定

今回は以前のブログで作成したモノやスクリプトそのまま使い回しちゃいます。
ので、モノの状態を管理してくれるAWS IoTのThing Shadowを使います。
状態のRunningが1の場合、写真撮って0に戻します。

モノの設定等は以下の記事に記載してあります。

 

AWS IoT – インスタンスの起動状態をRaspberry Piに繋げたLEDで監視しよう

xp-cloud.jp

 

写真撮ってアップロードするだけなのでShadow stateを使用したこの方法はあまりスマートではないのですが……
ボタンでstateの切り替えを応用したら色々と面白い事が出来そうですね。

上記環境より変更するのは実行スクリプトとLambdaになります。

 

実行スクリプトの編集

まずは画像アップロード用のバケットをs3に作成しましょう。

今回はboto3を使うので、amユーザーを用意、boto3とawscliをインストールし、
aws configure行います。

 

runningが1の時写真撮ってs3上げる様にちょこっと編集加えます。

 

from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient

import json
import time
import datetime
import logging
import subprocess
import boto3
s3 = boto3.resource('s3')
bucketName = "xp-rpi-pic"

def updateState():
    report_json = '{"state":{"desired": {"running": 0}}}'
    deviceShadowHandler.shadowUpdate(report_json, None, 5)

def take_pic(payload, response, token):

    payloadDict = json.loads(payload)

    if int(payloadDict["state"]["running"]) == 1 :
        today = datetime.datetime.today()
        filedate = today.strftime("%Y%m%d_%H%M%S")
        filename = "%srpipic.jpg" % filedate
        cmd = "fswebcam %s" % filename
        subprocess.call(cmd,shell=True)
        s3.Bucket(bucketName).upload_file(filename,filename)

    updateState()

host = "xxxxxxxxxxxxx.iot.ap-northeast-1.amazonaws.com"
port = 8883
clientId = "xxxxxxxx"
thingName = "xxxxxxx"
rootCAPath = "xxxxxxx"
certificatePath = "xxxxxxx"
privateKeyPath = "xxxxxxx"

#logger = logging.getLogger("core") # Python 3
logger = logging.getLogger("AWSIoTPythonSDK.core") # Python 2
logger.setLevel(logging.DEBUG)
streamHandler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
streamHandler.setFormatter(formatter)
logger.addHandler(streamHandler)

# Init AWSIoTMQTTShadowClient
myAWSIoTMQTTShadowClient = None
myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient(clientId)
myAWSIoTMQTTShadowClient.configureEndpoint(host, 8883)
myAWSIoTMQTTShadowClient.configureCredentials(rootCAPath, privateKeyPath, certificatePath)

# AWSIoTMQTTShadowClient configuration
myAWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20)
myAWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(10) # 10 sec
myAWSIoTMQTTShadowClient.configureMQTTOperationTimeout(5) # 5 sec

# Connect to AWS IoT
myAWSIoTMQTTShadowClient.connect()

deviceShadowHandler= myAWSIoTMQTTShadowClient.createShadowHandlerWithName(thingName, True)

deviceShadowHandler.shadowRegisterDeltaCallback(take_pic)

while True:
    pass

 

Lambda関数の変更

前回はインスタンスの状態を反映させてましたが、今回はボタン押したらrunningを1にしたいだけです。

 

import boto3
import json

def lambda_handler(event, context):
    
    state = "1"
        
    client = boto3.client('iot-data')
    response = client.update_thing_shadow(
        thingName='xxxxxxx',
        payload=json.dumps({"state":{"desired": {"running": state}}})
    )

IoT 1-Clickの設定

後はボタンにLambda関数を紐づけます

バイスの登録等は以下の記事にあります。

AWS IoT Enterprise Buttonを使ってみよう

xp-cloud.jp

 

AWSコンソールのIoT 1-Clickに移動し
プロジェクトを作成し……

 

AWSコンソールのIoT 1-Clickに移動

 

Lambda関数を紐づけ……

 

Lambda関数を紐づけ

 

プレイスメントを作成し、デバイスに紐づければ設定完了です。

 

プレイスメントを作成

 

Slackへの投稿

折角なのでSlackへの投稿も試してみました。

Slack Appsよりbotを作成し、tokenをメモし、指定のチャンネルにbotを招待します。
channelsはチャンネルのurlを見ればすぐ分かります。

import requestsし、s3にアップロードする箇所を変更しましょう。

 

files = {'file': open(filename, 'rb')}
param = {
    'token': "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    'channels': "xxxxxx"
}
requests.post(url="https://slack.com/api/files.upload",params=param, files=files)

これでボタンをポチポチしますとSlackに写真が投稿されるはずです。

 

Slackに写真が投稿

Slackに写真が投稿

Slackに写真が投稿

 

 

 

AWS相談会