Alexaに気温と二酸化炭素濃度を教えてもらう
NestJSの練習がてら、家にあるセンサー情報を集約するAPIを作成した。
APIは↓のように最新のセンサー情報を返すだけのシンプルなものになっている。
{
temperature: 28.15,
humidity: 67.6152,
pressure: 1011.04,
pm25: 0,
co2: 913
}
今回はセンサー情報取得APIを使って、Alexaにセンサー情報を教えてもらえるようにする。
Alexa Skillの作成
- Alexa Developer Consoleにアクセス
- 「スキルの作成」を選択
- スキル名に呼び出したいワードを入力(今回は「気温」で呼び出せるようにした)
- ホスティング先は「Alexa-Hosted」を選択
- テンプレートは「Hello Worldスキル」を選択
実装
- 「コードエディタ」メニューを開く
- package.jsonのdependenciesにaxiosを追加
"dependencies": {
"axios": "^0.20.0",
"ask-sdk-core": "^2.6.0",
"ask-sdk-model": "^1.18.0",
"aws-sdk": "^2.326.0"
}
- index.jsはHello WorldテンプレートをベースにLaunchRequestHandlerのみ編集
- センサー情報を取得して応答するように変更し、repromptを外して一回のみ起動するように
const Alexa = require('ask-sdk-core');
const axios = require("axios");
const getSensorData = async () => {
try {
const response = await axios.get(
"https://{sensor-api-url}"
);
return response.data;
} catch (error) {
console.error(error);
}
};
const LaunchRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
},
async handle(handlerInput) {
const sensor = await getSensorData();
const speakOutput = `リビングのCO2濃度は${sensor.co2}ppmです。温度は${Math.round(sensor.temperature * 10) / 10}度、湿度は${Math.round(sensor.humidity * 10) / 10}パーセントです。気圧は${Math.round(sensor.pressure)}ヘクトパスカルです。`;
return handlerInput.responseBuilder
.speak(speakOutput)
.getResponse();
}
};
const HelpIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
const speakOutput = 'You can say hello to me! How can I help?';
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
const CancelAndStopIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& (Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.CancelIntent'
|| Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.StopIntent');
},
handle(handlerInput) {
const speakOutput = 'Goodbye!';
return handlerInput.responseBuilder
.speak(speakOutput)
.getResponse();
}
};
const SessionEndedRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'SessionEndedRequest';
},
handle(handlerInput) {
// Any cleanup logic goes here.
return handlerInput.responseBuilder.getResponse();
}
};
const IntentReflectorHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest';
},
handle(handlerInput) {
const intentName = Alexa.getIntentName(handlerInput.requestEnvelope);
const speakOutput = `You just triggered ${intentName}`;
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`~~~~ Error handled: ${error.stack}`);
const speakOutput = `Sorry, I had trouble doing what you asked. Please try again.`;
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};
exports.handler = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
)
.addErrorHandlers(
ErrorHandler,
)
.lambda();
- コードの実装が終わったら「デプロイ」を実行
確認
- 「テスト」メニューを開き、ステータスを「開発中」に変更する
- Alexaシミュレーターに「気温」を入力すると、センサー情報を教えてくれる
開発中のスキルはEchoやEcho Dotでも有効になるので、この状態で「Alexa 気温」と言えばセンサー情報を教えてくれる。