Alexa SDK for Node.js Ver2を使って、nodemailerによるメール送信とJSONによるサーバとのデータの受渡しを行います。「Alexa SDK for Node.js Ver2をAWS Lambdaにデプロイ」で Alexa SDK for Node.js Ver2をAWS Lambdaにデプロイしました。この「node_modules」にメーラライブラリ「nodemailer」を追加してデプロイします。ここでは、次のスクリプトを作成します。
- メーラライブラリ「nodemailer」によるメール送信
- JSONによるサーバへのデータ送信
- JSONによるサーバからのデータ受信
今回のスクリプトではASK SDK v1アダプター「ask-sdk-v1adapter」を使用します。これはV2でメール送信とJSONによるデータの受け渡しの方法が調べきれなかったためです。V2でスクリプトを作成すると、応答が返ってくる前にスクリプトが終了してしまします。
メーラライブラリ「nodemailer」のデプロイ
Raspberry piに作成したカスタムスキルを開発するローカルな開発環境で、次のコマンドでASK SDK v1アダプター「ask-sdk-v1adapter」とメーラライブラリ「nodemailer」をインストールし、作成したフォルダ/ファイルをzipファイルとして圧縮します。ただし、「aws-sdk」はフォルダが大きいため、Web上の「コードをインラインで編集」が利用できないので、削除してAWS Lambdaにデプロイは行いません。
$ npm install --save ask-sdk-v1adapter ask-sdk $ npm install nodemailer $ npm install nodemailer-smtp-transport
メーラライブラリ「nodemailer」によるメール送信
AWS Lambdaのindex.jsに次のスクリプトを記述し、メーラライブラリ「nodemailer」によりメールの送信が完了すると、Amazon Echoに「メールを送信しました」と発話させます。
- 2行目:ASK SDK v1アダプター「ask-sdk-v1adapter」を指定します。
- 6-10行目:ASK SDK v1アダプター「ask-sdk-v1adapter」で動作させるときはこのように変更します。
- 28-34行目:メールサーバへの接続情報を設定します。
- 29-44行目:送信するメールの内容を設定します。
index.js
'use strict';
const Alexa = require('ask-sdk-v1adapter');
var APP_ID = undefined;
exports.handler = function (event, context, callback) {
var alexa = Alexa.handler(event, context);
alexa.APP_ID = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};
var handlers = {
'LaunchRequest': function () {
this.emit('GetNewFactIntent');
},
'GetNewFactIntent': function () {
var te = this;
var targetEmail = 'xxxx';
var fromEmail = 'xxxx';
var sesAccessKey = 'xxxx';
var sesSecretKey = 'xxxx';
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var transporter = nodemailer.createTransport(smtpTransport({
host: 'xxxxx',
port: 587,
auth: {
user: sesAccessKey,
pass: sesSecretKey
}
}));
var text = 'Tomoでございます。';
var mailOptions = {
from: fromEmail,
to: targetEmail,
subject: '問い合わせ',
text: text
};
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
console.log(error);
}
te.emit(':tell', 'メールを送信しました');
});
}
};
AWS Lambda画面右上の「テスト」ボタンをクリックして作成した「index.js」を実行すると、次のような応答がAWS Lambda画面上に表示されます。また、Amazon開発者コンソールに紐づいたAmazon Echoからどのような音声を入力しても、「メールを送信しました」とAmazon Echoが答え、指定したメールの宛先にメールが届きます。
Response:
{
"version": "1.0",
"response": {
"shouldEndSession": true,
"outputSpeech": {
"type": "SSML",
"ssml": "メールを送信しました "
}
},
}
JSONによるサーバへのデータ送信
AWS Lambdaのindex.jsに次のスクリプトを記述し、httpライブラリ「http」によりJSON形式のデータをWebサーバに送信し、送信が完了すると、Amazon Echoに「データを送信しました」と発話させます。
- 2行目:ASK SDK v1アダプター「ask-sdk-v1adapter」を指定します。
- 6-10行目:ASK SDK v1アダプター「ask-sdk-v1adapter」で動作させるときはこのように変更します。
- 23-26行目:送信するデータをJSON形式で記述します。
- 29-38行目:対象リソースの通信オプション「options」を使ってHTTPのパラメータ設定します。
index.js
'use strict';
const Alexa = require('ask-sdk-v1adapter');
var APP_ID = undefined;
exports.handler = function (event, context, callback) {
var alexa = Alexa.handler(event, context);
alexa.APP_ID = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};
var handlers = {
'LaunchRequest': function () {
this.emit('GetNewFactIntent');
},
'GetNewFactIntent': function () {
let http = require('http');
const HOST = `xxxx`;
const PATH = `xxxx/postdata.php`;
let postData = {
"name": "TomoSoft8",
"comment": "good soft"
};
let postDataStr = JSON.stringify(postData);
let options = {
host: HOST,
port: 80,
path: PATH,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': postDataStr.length
}
};
let req = http.request(options, (res) => {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log('BODY: ' + chunk);
this.emit(':tell', 'データを送信しました');
});
});
req.on('error', (e) => {
console.log('problem with request: ' + e.message);
});
req.write(postDataStr);
req.end();
}
};
webサーバに置かれ、AWS Lambdaのindex.jsのスクリプトから呼ばれる「postdata.php」を次に示します。index.jsのスクリプトから呼ばれと、ファイル「samplepost.txt」に入力情報を保存し、JSON形式で渡された情報を応答として返します。
postdata.php
<?php
try {
$headers = getallheaders();
$post_body = file_get_contents('php://input');
$fp = fopen("samplepost.txt", "w");
foreach ($headers as $name => $value) {
fwrite($fp,"$name: $value\n");
}
fwrite($fp,"$post_body\n");
fclose($fp);
$obj = json_decode($post_body); // オブジェクト形式
if ($obj === NULL) return;
var_dump($obj);
echo "<br>";
echo $obj->{'payload'}->{'channels'}[0]->{'value'};
echo "<br>";
echo $obj->{'datetime'};
echo "<br>";
} catch (PDOException $e){
var_dump($e->getMessage());
}
?>
AWS Lambda画面右上の「テスト」ボタンをクリックして作成した「index.js」を実行すると、次のような応答がAWS Lambda画面上に表示されます。console.logコマンドにより、応答のステータス、ヘッダ、戻り値を表示します。また、Amazon開発者コンソールに紐づいたAmazon Echoからどのような音声を入力しても、「データを送信しました」とAmazon Echoが答え、指定したWebサーバにデータが届きます。
Response:
{
"version": "1.0",
"response": {
"shouldEndSession": true,
"outputSpeech": {
"type": "SSML",
"ssml": "データを送信しました "
}
},
}
Function Logs:
2018-07-21T04:11:59.611Z STATUS: 200
2018-07-21T04:11:59.611Z HEADERS: {"server":"nginx","date":"Sat, 21 Jul 2018 04:11:59 GMT","content-type":"text/html; charset=UTF-8","transfer-encoding":"chunked","connection":"close","x-powered-by":"PHP/7.1.19"}
2018-07-21T04:11:59.613Z BODY: object(stdClass)#1 (2) {
2018-07-21T04:11:59.613Z BODY: ["name"]=>
string(9) "TomoSoft8"
["comment"]=>
string(9) "good soft"
}
ファイル「samplepost.txt」に保存された入力情報を次に示します。JSON形式でデータが渡されていることがわかります。
samplepost.txt
Host: tomosoft.jp
X-Real-Ip: 18.179.31.112
X-Forwarded-Proto: http
Listen-Ipaddr: 49.212.207.43
Content-Length: 42
Content-Type: application/json
{"name":"TomoSoft8","comment":"good soft"}
JSONによるサーバからのデータ受信
AWS Lambdaのindex.jsに次のスクリプトを記述し、httpライブラリ「http」によりJSON形式のデータをWebサーバに送信し、送信が完了すると、Amazon Echoに「データを送信しました」と発話させます。
- 2行目:ASK SDK v1アダプター「ask-sdk-v1adapter」を指定します。
- 6-10行目:ASK SDK v1アダプター「ask-sdk-v1adapter」で動作させるときはこのように変更します。
- 23-31行目:対象リソースの通信オプション「options」を使ってHTTPのパラメータ設定します。
- 41行目:JSON形式で受信したデータを使って、発話を編集します。
index.js
'use strict';
const Alexa = require('ask-sdk-v1adapter');
var APP_ID = undefined;
exports.handler = function (event, context, callback) {
var alexa = Alexa.handler(event, context);
alexa.APP_ID = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};
var handlers = {
'LaunchRequest': function () {
this.emit('GetNewFactIntent');
},
'GetNewFactIntent': function () {
let http = require('http');
const HOST = `xxxx`;
const PATH = `xxxx/getdata.php`;
let options = {
host: HOST,
port: 80,
path: PATH,
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
};
let req = http.request(options, (res) => {
res.setEncoding('utf8');
res.on('data', (chunk) => {
var parsedValue = JSON.parse(chunk);
var key1 = "price";
console.log(parsedValue);
console.log(parsedValue[key1]);
this.emit(':tell', String(parsedValue['price']) + 'えんです');
});
}).on('error', (e) => {
console.log(e.message); //エラー時
this.emit(':tell', 'エラーです' + e.message);
});
req.end();
}
};
webサーバに置かれ、AWS Lambdaのindex.jsのスクリプトから呼ばれる「getdata.php」を次に示します。index.jsのスクリプトから呼ばれと、JSON形式で情報「'{“price”:500, “item”:”card” , “date”:”2018/11/05″}’」を返します。
getdata.php
<?php
try {
// ヘッダーを指定
header( "Content-Type: application/json; charset=utf-8" ) ;
$fp = fopen("sampleget.txt", "w");
fwrite($fp,"123\n");
fclose($fp);
$post_body = '{"price":500, "item":"card" , "date":"2018/11/05"}';
echo $post_body ;
} catch (PDOException $e){
var_dump($e->getMessage());
}
?>
AWS Lambda画面右上の「テスト」ボタンをクリックして作成した「index.js」を実行すると、次のような応答がAWS Lambda画面上に表示されます。Webサーバから受信したデータを、console.logコマンドにより表示します。また、Amazon開発者コンソールに紐づいたAmazon Echoからどのような音声を入力しても、指定したWebサーバからデータを受信し、受信したデータから「500えんです」とAmazon Echoが答えます。
Response:
{
"version": "1.0",
"response": {
"shouldEndSession": true,
"outputSpeech": {
"type": "SSML",
"ssml": "500えんです "
}
},
}
2018-07-21T04:35:46.326Z { price: 500, item: 'card', date: '2018/11/05' }
2018-07-21T04:35:46.327Z 500