Raspberry Pi で作る LED 警告灯ソリューション、Crystal Signal Pi のプリント基板キットが届いたので早速組み立て、AWS IoT の Thing Shadow と AWS Lambda の Schedule Event で通知するところまでやってみました。
Schedule Event で Lambda 関数が実行される毎に点灯の仕方を変えています。
Crystal Signal Pi とは
詳しくは Crystal Signal Pi 公式サイトを参照ください。
事前準備
本記事では主に AWS CLI を使ってリソースを作成していきます。
AWS CLI をアップデート
$ sudo pip install --upgrade awscli
バージョン確認
$ aws --version
aws-cli/1.11.32 Python/2.7.12 Darwin/15.6.0 botocore/1.4.89
AWS IoT 側の準備
Thing を作成
$ aws iot create-thing --thing-name crystalSignalPi
Shadow を登録
$ aws iot-data update-thing-shadow --thing-name crystalSignalPi \
--payload '{"state": {"desired" : {"blinkColor" : "green"}}}' \
outfile.json
AWS Lambda 側の準備
今回の AWS Lambda 関数作成に必要なものから作成していきます。
assume ロールの決定
$ cat << EOF > lambdaExecution.json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
IAM ロールの作成
$ aws iam create-role \
--role-name lambdaExecution \
--assume-role-policy-document file://lambdaExecution.json
ポリシーの適用
$ aws iam attach-role-policy \
--role-name lambdaExecution \
--policy-arn arn:aws:iam::aws:policy/AWSIoTDataAccess
Lambda 関数
$ cat << EOF > changeBlinkColor.js
console.log('Loading function');
var aws = require('aws-sdk');
var endpoint = 'XXXXXXXXXXXXX.iot.ap-northeast-1.amazonaws.com';
var thingName = 'crystalSignalPi';
exports.handler = function(event, context) {
var iotdata = new aws.IotData( { endpoint: endpoint } );
var params = { thingName: thingName };
iotdata.getThingShadow(params, function (err, data) {
if (!err) {
var payload = JSON.parse(data.payload);
var currentBlinkColor = payload.state.desired.blinkColor;
console.log("Current Color : " + currentBlinkColor);
var desiredBlinkColor;
if(currentBlinkColor == 'red') {
desiredBlinkColor = 'green';
} else {
desiredBlinkColor = 'red';
}
var desiredState = {
state: {
desired: {
blinkColor: desiredBlinkColor
},
reported: {
blinkColor: currentBlinkColor
}
}
};
var params = {
thingName: thingName,
payload: JSON.stringify(desiredState)
};
iotdata.updateThingShadow(params, function (err, data) {
if (!err) {
context.succeed();
} else {
context.fail(err);
}
});
} else {
context.fail(err);
}
});
};
EOF
$ zip changeBlinkColor.zip changeBlinkColor.js
Lambda 関数の作成
$ aws lambda create-function \
--function-name changeBlinkColor \
--zip-file fileb:///path/to/changeBlinkColor.js.zip \
--runtime nodejs4.3 \
--role arn:aws:iam::XXXXXXXXXXXX:role/lambdaExecution \
--handler changeBlinkColor.handler
Schedule 作成
$ aws lambda add-permission \
--function-name changeBlinkColor \
--statement-id "changeBlinkColor00" \
--action 'lambda:InvokeFunction' \
--principal events.amazonaws.com \
--source-arn arn:aws:events:ap-northeast-1:XXXXXXXXXXXX:rule/changeColorBatch
Event のルールを設定
$ aws events put-rule \
--name "changeColorBatch" \
--schedule-expression "cron(*/5 * * * ? *)" \
--state ENABLED
$ aws events put-targets \
--rule "changeColorBatch" \
--targets Arn=arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:changeBlinkColor,Id=XXXXX
Crystal Signal Pi を組み立てる
公式サイトのマニュアルを見ながら Crystal Signal Pi を組み立て、設定していきます。
Raspberry Pi と AWS IoT の連携
pip のインストール
$ sudo apt-get install python-pip
AWS IoT Device SDK for Pythonのインストール
$ sudo pip install AWSIoTPythonSDK
git のインストール
$ sudo apt-get install git
サンプルコードのダウンロード
$ git clone https://github.com/aws/aws-iot-device-sdk-python.git
$ cd aws-iot-device-sdk-python
$ sudo python setup.py install
IAM ユーザーの作成
デバイス用に IAM ユーザーを作成、Managed policy AWSIoTFullAccess をアタッチ
アクセスキーの設定
クレデンシャル情報を設定
サンプルコードをコピー
$ mkdir -p crystal-signal-pi
$ cd crystal-signal-pi
$ cp ../samples/basicShadow/basicShadowDeltaListener.py ./shadowDeltaListener.py
証明書の準備、配置
コピーしたサンプルコードと同じディレクトリに配置
コードを編集
# coding: utf-8
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient
import sys
import logging
import time
import json
import getopt
import pycurl
# Shadow JSON schema:
#
# Name: Bot
# {
# "state": {
# "desired":{
# "property":<INT VALUE>
# }
# }
#}
# Custom Shadow callback
def customShadowCallback_Delta(payload, responseStatus, token):
# payload is a JSON string ready to be parsed using json.loads(...)
# in both Py2.x and Py3.x
print(responseStatus)
payloadDict = json.loads(payload)
print("++++++++DELTA++++++++++")
property = "blinkColor"
blinkColor = str(payloadDict["state"][property])
print("property: " + blinkColor)
#print("version: " + str(payloadDict["version"]))
print("+++++++++++++++++++++++\n\n")
if blinkColor == "red":
url = "http://localhost/ctrl/?color=100,0,0&mode=1&repeat=0&period=250&json=1"
else:
url = "http://localhost/ctrl/?color=0,80,0&mode=1&repeat=0&period=1000&json=1"
curl = pycurl.Curl()
curl.setopt(pycurl.URL, url)
curl.setopt(pycurl.CUSTOMREQUEST, 'GET')
curl.perform()
# Read in command-line parameters
useWebsocket = True
host = "XXXXXXXXXXXXX.iot.ap-northeast-1.amazonaws.com"
rootCAPath = "rootCA.pem"
certificatePath = "XXXXXXXXXX-certificate.pem.crt"
privateKeyPath = "XXXXXXXXXX-private.pem.key"
thingName = "crystalSignalPi"
# Configure logging
logger = logging.getLogger("AWSIoTPythonSDK.core")
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("basicShadowDeltaListener", useWebsocket=True)
myAWSIoTMQTTShadowClient.configureEndpoint(host, 443)
myAWSIoTMQTTShadowClient.configureCredentials(rootCAPath)
# AWSIoTMQTTShadowClient configuration
myAWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20)
myAWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(10) # 10 sec
myAWSIoTMQTTShadowClient.configureMQTTOperationTimeout(5) # 5 sec
# Connect to AWS IoT
myAWSIoTMQTTShadowClient.connect()
# Create a deviceShadow with persistent subscription
Bot = myAWSIoTMQTTShadowClient.createShadowHandlerWithName(thingName, True)
# Listen on deltas
Bot.shadowRegisterDeltaCallback(customShadowCallback_Delta)
# Loop forever
while True:
pass
python-pycurl のインストール
$ sudo apt-get install python-pycurl
コードを実行
$ python shadowDeltaListener.py
おわりに
今回はまず、AWS IoT との連携までやってみました。
次回は光での通知だけでなく、Polly を使って音声と連携した使い方も試してみたいと思います。