カテゴリー: Node.js

Node.js覚書 外部ファイルの変数定義を参照する

Map変数の設定するデータの量が多すぎて、別のファイルに移せないかなぁと思って調べた。

呼出元

変数

var exp = require('./mapxxx.js');
var mapX = exp.data;

呼出先

ここでは、mapxxx.jsとして保存。
変数定義後、exports.ホゲホゲ = 定義した変数 としておけば、呼出元で使えるようになる。

var maps = new Map([
    ['D01', 'DDDDDD'],
    ['E02', 'EEEE'],
    ........
]);

exports.data = maps;

最後の「exports.***」を忘れて、「うまくいかないぃ~」と思っていたが、こんなにあっさりできるとは。

AWS覚書 Lambda関数を作る(2)~コード編集

SDKを入れたZipをアップロードすると、index.jsがないぜ!とエラーが出るので、ファイルツリーの表示欄を右クリックして、New Fileを選択。
できたファイルの名前をindex.jsに変更して、この中に処理を書いていく。
同じ要領で、package.jsonファイルも作っておく。
このとき、node_modulesフォルダとindex.js、package.jsonは同じフォルダ内に配置する。(違う場所に作ってもD&Dでファイル移動できる。)

index.jsサンプル

LaunchRequestHandlerは、呼出名のみ言われたときの処理。
*******IntentHandlerは、*******Intentに引っかかったときの処理。(*******は任意で。)
その他、HelpやErrorのIntentHandlerは処理部分をLaunchRequestHandlerと同じように記載していく。
今回は、DBアクセスなどがないので、軽量SDK「ask-sdk-core」を利用する。

const Alexa = require('ask-sdk-core');

// --------------------------------------------------------------------
const LaunchRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
  },
  handle(handlerInput) {
    return handlerInput.responseBuilder
                       .speak('返答内容')
                       .reprompt('質問内容')
                       .getResponse();
  }
};

// customize intent ***************************
const *******IntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
      && handlerInput.requestEnvelope.request.intent.name === '*******Intent';
  },
  handle(handlerInput) {
    
    var intent = handlerInput.requestEnvelope.request.intent;
    var dat = intent && intent.slots && intent.slots..*****. && intent.slots.*****.value;
    
    return handlerInput.responseBuilder.speak(speechText)
                                       .withSimpleCard('タイトル', '返答内容')
                                       .getResponse();
  },
};
// customize intent ***************************

const HelpIntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
      && handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
  },
  handle(handlerInput) {
      ・・・・(省略)・・・・
  },
};

const CancelAndStopIntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
      && (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
        || handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
  },
  handle(handlerInput) {
      ・・・・(省略)・・・・
  },
};

const SessionEndedRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
  },
  handle(handlerInput) {
      ・・・・(省略)・・・・
  },
};

const ErrorHandler = {
  canHandle() {
    return true;
  },
  handle(handlerInput, error) {
      ・・・・(省略)・・・・
  },
};

// --------------------------------------------------------------------
let skill;
exports.handler = async function (event, context) {
    if (!skill) {
      skill = Alexa.SkillBuilders.custom()
                                          .addRequestHandlers( LaunchRequestHandler,
                                                               *******IntentHandler,
                                                               HelpIntentHandler,
                                                               CancelAndStopIntentHandler,
                                                               SessionEndedRequestHandler
                                          )
                                          .addErrorHandlers(ErrorHandler)
                                          .create();
    }

    const response = await skill.invoke(event, context);
    return response;
};

package.jsonサンプル

nameはLambda関数の名前でOK。versionは関数のバージョン。dependenciesに利用するSDKを設定。

{
  "name": "****",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "ask-sdk-core": "^2.7.0"
  }
}

処理を記述後、Alexaからの呼出で想定通りの返答がなされていればOK。
もし、うまくいかないときは、Alexa Developer コンソールのテスト画面に表示される「スキルI/O」の「JSON入力」に出力されるJSONをコピーして、Lambda関数のテストイベントの設定に貼り付けてテストしてみる。
すると、結果のログにエラー内容が出力されるので、そのエラー内容で処理の記載を変更してやればよい。

AWS覚書 Lambda関数を作る(1)~Alexa SDK for Node.js v2

いつの間にかVersion2が出てた。
alexa-sdkからask-sdkに変わってた。

ということで、せっかくなので対応したLambda関数を作ってみようと思ったのだが、SDKを取得するのに相変わらずLinux環境が要るのだ。
簡単にできますよぉ~などという謳い文句とは裏腹に面倒なのだ。

しかし、普段Linuxを使うことのない私にとっては「いい勉強だ」などと半分自分に嘘をつきながら、SDKを取得してみた。
Linuxの環境はAWS EC2インスタンスで用意。
AWSのEC2(Amazon Linux)が便利なところは、ブラウザ上でコマンドが打てる点だ。気が利いている。
(とはいうものの、ブラウザを放置していると、コマンドが打てなくなるという不具合なのか、セッション切れなのかよくわからない現象が起こるので注意が必要。)

起動したら、npmまで入ってない・・・トホホ。
しょうがないからいろいろ入れることに。
※ここから下のコマンドは、上記の通りEC2インスタンス(Amazon Linux)をブラウザでコマンド実行例。

NodeBrewのインストール

NodeBrewはNode.jsのバージョン切替用ツールらしい。そして、NodeBrewを使ってNode.jsのいろんなバージョンを取得し、バージョン切替が簡単にできるのである。
すごいなぁ・・・などと感心。

curl -L git.io/nodebrew | perl - setup
export PATH=$HOME/.nodebrew/current/bin:$PATH
source ~/.bashrc
nodebrew help

で、NodeBrewのヘルプが見られたら、NodeBrewのインストールは完了。これでnpmも入る。

Node.jsのインストール

ここではversion8で利用予定のversion8.10.*のインストールを行う。

nodebrew install v8.10
nodebrew use v8.10
node -v

インストールして、8.10のバージョンを使うよ!と宣言後、nodeコマンドでインストールしたNode.jsのバージョンを確認。

ask-sdkをnpmを使ってインストール

npm install ask-sdk
npm install ask-sdk-v1adapter
npm install ask-sdk-core
npm uninstall aws-sdk

上は例。要らないものは入れなくていい。取得したモジュールはすべてnode_modulesフォルダ内に入る。
AWS-SDKがあると容量が増えてLambda関数にアップロードできなくなるので、削除しておくこと。

ask-sdkをZip圧縮後、S3へアップロード

cd ./
zip -r alexa_ask_sdk.zip node_modules

上の階層に行って、node_modulesフォルダを丸ごとZIP圧縮。
Zipの中身を確認するときは、以下のようにless文を使う。

less alexa_ask_sdk.zip

(コマンド終了は:q)

次はS3へアップロード。これはAWS CLIを使う。
{****}はバケット名。

aws s3 cp alexa_ask_sdk.zip s3://{****}/alexa.zip

S3にアップロードしたzipをLambda関数の関数コードのところで取り込めば、ようやくコードの編集が始められる。
続きは(2)へ。