tatata’s blog(備忘録)

自分の備忘録として書いています。

Amazon Echoで照明をオン・オフする 4(Alexa編)

今回は、AlexaスキルからLabmda経由で前回作成したSQSにメッセージを送って、照明をオン・オフする処理を作成する。

Lambda関数作成

Alexaスキルからの命令を受け取って、SQSにメッセージを投げるLambda関数を作成する。

f:id:ysysy:20180506190645p:plain

alexa-sdkをインストール

$ npm install --save alexa-sdk

次の2つのファイルを作成

index.js

const AWS = require('aws-sdk');
const Alexa = require('alexa-sdk');
let sqs = new AWS.SQS({region:'ap-northeast-1'});
let url = process.env.SQS_QUEUE_URL;
var state = '-1';
AWS.config.update({accessKeyId: 'KEY', secretAccessKey: 'SECRET'});

function changeState(state) {
        var params = {
        MessageBody: state,
        QueueUrl: url,
        DelaySeconds: 0,
        MessageAttributes: {
            LightStatus: {
              DataType: 'Number',
              StringValue: state
            },
        },
    };
    sqs.sendMessage(params, function(err, data) {
        if (err) console.log(err, err.stack);
        else     console.log(data);
    });
};

const handlers = {
    'turnOn' : function() {
        changeState('1');
        this.emit(':responseReady');
    },
    'turnOff' : function() {
        changeState('0');
        this.emit(':responseReady');
    }
};

exports.handler = function(event, context, callback) {
    const alexa = Alexa.handler(event, context, callback);
    alexa.appId = process.env.APP_ID // APP_ID is your skill id which can be found in the Amazon developer console where you create the skill.
    alexa.registerHandlers(handlers);
    alexa.execute();
};

package.json

{
  "name": "light",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "alexa-sdk": "^1.0.25"
  }
}

zipファイルにしてアップロードする

$ zip -r light.zip *

f:id:ysysy:20180506190651p:plain

環境変数の設定

APP_IDには後ほど作成するAlexaスキルのIDを、SQS_QUEUE_URLには前回作成したSQSキューのURLを設定する。

f:id:ysysy:20180506190654p:plain

Alexaスキル作成

Alexaコンソールにログインしてスキルを作成する。 ログインに使用するアカウントは、Amazon Echoを買ったamazon.co.jpのアカウントを使う。*1

developer.amazon.com

呼び出し名

「スキルの呼び出し名」にAlexaで呼び出すときの名前を設定する。ここでは、「ほげほげまん」とした。

f:id:ysysy:20180506185808p:plain

インテント

インテントには照明をオンにするときのフレーズを設定する。 この例では、「Alexa、ほげほげまんであかるくして」、「Alexa、ほげほげまんでつけて」と言うと照明がオンになる。

f:id:ysysy:20180506185812p:plain

同様に照明をオフにするときのフレーズを設定する。

f:id:ysysy:20180506185816p:plain

エンドポイント

ここに表示されている「スキルID」をLamda関数の環境変数APP_IDに設定する。 「デフォルトの地域」にLambda関数のARNを設定する f:id:ysysy:20180506185820p:plain

動作確認

照明オン・オフをAmazon Echoからできことを確認

照明オン

  • 「Alexa、ほげほげまんであかるくして」
  • 「Alexa、ほげほげまんでつけて」

照明オフ

  • 「Alexa、ほげほげまんでくらくして」
  • 「Alexa、ほげほげまんできって」
  • 「Alexa、ほげほげまんでけして」

Lambda関数で使ったnode.jsは詳しくないのでもっと良い方法があると思う。スキルの設定ももっとスマートな方法があるはず。でもこれで動くことは動く。

作成して時間が経っているので、記憶があやふやになり、あまり詳しく書けなかったのが反省。

*1:amazon.comのアカウントでログインしたら、Echoと関連づけられていなかった。

Amazon Echoで照明をオン・オフする 3(SQS編)

今回は、前回作成したプログラムを改良して、SQSからRaspberry Piにメッセージを取得して、照明をオン・オフする処理を作る。

SQSキュー作成

メッセージを入れるSQSのキューをAWSコンソールから作成

プログラム(turnOnOff.js)

SQSからメッセージを取得して、シリアルポート経由でArduinoに命令を送る常駐プログラムを作成

var AWS = require('aws-sdk');
var async = require('async');
var SerialPort = require('serialport');

// Raspberry Piのシリアルポートを指定
var port = new SerialPort('/dev/ttyACM0');

// 環境変数からAWSのアクセスキーを取得
let KEY = process.env.AWS_ACCESS_KEY;
// 環境変数からAWSのシークレットキーを取得
let SECRET = process.env.AWS_SECRET_KEY;
// 環境変数からSQSのキューURLを取得
let URL = process.env.SQS_QUEUE_URL;
// 認証情報をセット
AWS.config.update({accessKeyId: KEY, secretAccessKey: SECRET});

// SQSのリージョンを指定
var sqs = new AWS.SQS({region:'ap-northeast-1'});

// SQSの情報をセット
var params = {
  QueueUrl: URL,
  AttributeNames: [
    'ApproximateFirstReceiveTimestamp'
  ],
  MaxNumberOfMessages: 1,
  MessageAttributeNames: [
    'LightStatus' //メッセージの属性LightStatusの値で判断するため設定。任意の名前でOK
  ]
};

// 引数で渡ってきた値をシリアルポートに書く
function tunOnOff(state) {
  setTimeout(function() {
    port.write(state + "\n", function(err) {
      if (err) {
        return console.log('Error on write: ', err.message);
      }
      console.log('message written');
    });
  }, 2000);
};

// エラーが発生した場合はコンソールに出力
port.on('error', function(err) {
  console.log('Error: ', err.message);
});

// 処理開始
console.log('start');
setInterval(function() {
  sqs.receiveMessage(params, function(err, data) {
    if (err) {
      console.log(err, err.stack); // an error occurred
      console.log('error dayo');
    } else if (Array.isArray(data['Messages']) && data['Messages'].length > 0) {
      // SQSのメッセージの属性LightStatusが0の場合、シリアルポートに0を書き出す
      if (data['Messages'][0]['MessageAttributes']['LightStatus']['StringValue'] == '0') {
        tunOnOff('0');
      // SQSのメッセージの属性LightStatusが1の場合、シリアルポートに1を書き出す
      } else if (data['Messages'][0]['MessageAttributes']['LightStatus']['StringValue'] == '1') {
        tunOnOff('1');
      }

      // 取得したメッセージをキューから削除
      var deleteParams = {
        QueueUrl: URL,
        ReceiptHandle: data.Messages[0].ReceiptHandle
      };
      sqs.deleteMessage(deleteParams, function(err, data) {
        if (err) {
          console.log("Delete Error", err);
        };
      });
    }, 20000 );

環境変数設定

.bashrcに次の3行を追加

export AWS_ACCESS_KEY="<AWSのアクセスキー>"
export AWS_SECRET_KEY="<AWSのシークレットキー>"
export SQS_QUEUE_URL="<SQSのキューURL>"

動作確認

プログラム実行

Raspberry Piのコンソールよりプログラムを実行

$ node turnOnOff.js

SQSのキューにメッセージ送信

SQSのコンソールからメッセージ属性LightStatusを追加してメッセージを送信 f:id:ysysy:20180502162940p:plain

属性LightStatusの値が1だと照明がオンになり、0だと照明がオフになる。

node.jsは詳しくないので、ネットに転がっているコードを真似して作成したが、node.jsの非同期の考え方がいまいち理解できておらず、今回もコードがイケてない。コードを綺麗にしたいけど、時間がないのでこのまま。。。node-redでやればよかったかな。

次回はAlexaからSQSにメッセージを送信して、照明をオン・オフする。

Amazon Echoで照明をオン・オフする 2(Raspberry Pi編)

今回は、Raspberry Pi前回作成したArduinoに接続して、Raspbery PiからArduinoに照明のオン・オフを命令する処理を作る。

事前準備

  1. Raspberry PiArduinoをUSBで接続
  2. node.jsをインストール
  3. Node Serialportをインストール *1

www.npmjs.com

スクリプト作成

オンとオフで違うのはport.writeの引数(1または0)のみ

  • on.js (照明オン)
var SerialPort = require('serialport');
var port = new SerialPort('/dev/ttyACM0');

setTimeout(function() {
  port.write("1\n", function(err) {
    if (err) {
      return console.log('Error on write: ', err.message);
    }
    console.log('message written');
  });
}, 2000);


port.on('error', function(err) {
  console.log('Error: ', err.message);
})
  • off.js (照明オフ)
var SerialPort = require('serialport');
var port = new SerialPort('/dev/ttyACM0');

setTimeout(function() {
  port.write("0\n", function(err) {
    if (err) {
      return console.log('Error on write: ', err.message);
    }
    console.log('message written');
  });
}, 2000);


port.on('error', function(err) {
  console.log('Error: ', err.message);
})

動作確認

コマンドを実行して、照明をオン・オフできることを確認

# 照明オン
$ node on.js

# 照明オフ
$ node off.js

コードがイケてないけど、Raspberry Piから操作できるようになったのでよしとする。 次回は、SQSからメッセージを取得して、照明をオン・オフ。

*1:インストールにはまったけど、メモを取ってなかった

Amazon Echoで照明をオン・オフする 1(Arduino編)

Philips HueのようにWorks with Alexa認定商品だとAmazon Echoから照明のオン・オフができるけど、自宅の照明は対応していないので自分で作ってみた。

こんな感じで、Amazon EchoAWSRaspberry PiArduinoを組み合わせた。 f:id:ysysy:20180422142955p:plain

この記事ではまずArduinoから照明をオン・オフする機能について書く。

リモコンの信号解析

こちらの記事を参考にリモコン(Panasonic HK9327K)のボタンを押した時にどのような信号が出力されるか解析した。 deviceplus.jp

接続 f:id:ysysy:20180422143424p:plain

あまり覚えていないけど、Arduino-IRremoteのexampleにあるIRrecvDumpかIRrecvDumpV2をAruduinoに書き込んで、受光部に向けてリモコンのボタンを押すとシリアルモニタに信号が表示される。*1

github.com

# 調査結果
## 全灯ボタン
Encoding  : UNKNOWN
Code      : CA21A230 (32 bits)
Timing[83]:
     +3500, -1700     + 450, - 400     + 450, - 400     + 450, -1300
     + 450, -1250     + 450, - 400     + 450, -1300     + 450, - 400
     + 450, - 400     + 450, - 400     + 450, -1300     + 450, - 400
     + 450, - 400     + 450, -1300     + 450, - 400     + 450, -1250
     + 450, - 400     + 450, -1300     + 450, - 400     + 450, - 400
     + 450, -1300     + 450, - 400     + 450, - 400     + 450, - 400
     + 450, - 400     + 450, - 400     + 450, - 400     + 450, -1300
     + 450, -1300     + 450, - 400     + 450, -1250     + 450, - 400
     + 450, - 450     + 400, -1300     + 450, - 400     + 450, -1300
     + 450, - 400     + 450, - 400     + 450, -1300     + 450, - 400
     + 450, - 400     + 450
unsigned int  rawData[83] = {3500,1700, 450,400, 450,400, 450,1300, 450,1250, 450,400, 450,1300, 450,400, 450,400, 450,400, 450,1300, 450,400, 450,400, 450,1300, 450,400, 450,1250, 450,400, 450,1300, 450,400, 450,400, 450,1300, 450,400, 450,400, 450,400, 450,400, 450,400, 450,400, 450,1300, 450,1300, 450,400, 450,1250, 450,400, 450,450, 400,1300, 450,400, 450,1300, 450,400, 450,400, 450,1300, 450,400, 450,400, 450}; 

## お好みボタン
Encoding  : UNKNOWN
Code      : F6B92168 (32 bits)
Timing[83]:
     +3500, -1700     + 450, - 400     + 450, - 450     + 450, -1250
     + 450, -1300     + 450, - 400     + 450, -1250     + 450, - 450
     + 400, - 450     + 450, - 400     + 450, -1250     + 450, - 400
     + 450, - 450     + 400, -1300     + 450, - 400     + 450, -1300
     + 450, - 400     + 450, -1250     + 450, - 450     + 450, - 400
     + 450, -1250     + 450, - 400     + 450, - 400     + 450, - 450
     + 450, - 400     + 450, -1250     + 450, - 400     + 450, -1300
     + 450, -1300     + 400, - 450     + 450, -1250     + 450, - 400
     + 450, - 400     + 450, - 450     + 450, - 400     + 450, -1250
     + 450, - 400     + 450, - 400     + 450, -1300     + 450, - 400
     + 450, - 400     + 450
unsigned int  rawData[83] = {3500,1700, 450,400, 450,450, 450,1250, 450,1300, 450,400, 450,1250, 450,450, 400,450, 450,400, 450,1250, 450,400, 450,450, 400,1300, 450,400, 450,1300, 450,400, 450,1250, 450,450, 450,400, 450,1250, 450,400, 450,400, 450,450, 450,400, 450,1250, 450,400, 450,1300, 450,1300, 400,450, 450,1250, 450,400, 450,400, 450,450, 450,400, 450,1250, 450,400, 450,400, 450,1300, 450,400, 450,400, 450};

## 消灯ボタン
Timing[83]:
     +3500, -1700     + 450, - 400     + 450, - 400     + 450, -1300
     + 450, -1250     + 450, - 400     + 450, -1300     + 450, - 400
     + 450, - 400     + 450, - 400     + 450, -1300     + 450, - 400
     + 450, - 400     + 450, -1300     + 450, - 400     + 450, -1250
     + 450, - 450     + 450, -1250     + 450, - 400     + 450, - 400
     + 450, -1300     + 450, - 400     + 450, - 400     + 450, - 400
     + 450, - 400     + 450, -1300     + 450, -1300     + 400, -1300
     + 450, -1300     + 450, - 400     + 450, -1250     + 450, - 400
     + 450, - 450     + 450, - 400     + 450, -1250     + 450, -1300
     + 450, - 400     + 450, - 400     + 450, -1300     + 450, - 400
     + 450, - 400     + 450
unsigned int  rawData[83] = {3500,1700, 450,400, 450,400, 450,1300, 450,1250, 450,400, 450,1300, 450,400, 450,400, 450,400, 450,1300, 450,400, 450,400, 450,1300, 450,400, 450,1250, 450,450, 450,1250, 450,400, 450,400, 450,1300, 450,400, 450,400, 450,400, 450,400, 450,1300, 450,1300, 400,1300, 450,1300, 450,400, 450,1250, 450,400, 450,450, 450,400, 450,1250, 450,1300, 450,400, 450,400, 450,1300, 450,400, 450,400, 450}; 

信号出力

シリアルから1を入力すると「お好みボタン」、0を入力すると「消灯ボタン」を押した時と同じ信号を出力するようにする。 こちらの記事を参考に回路を作って動くには動いたけど、自分の部品構成ではこれで良いのかどうかよくわからず。抵抗の値が正しくないような気がする。。。

blogs.yahoo.co.jp

接続 f:id:ysysy:20180422154007p:plain

Arduinoに書き込むコードはこちら。いくつかのサイトを参考に作成。コードがいまいちだがひとまずOKとした。

#include <IRremote.h>

IRsend irsend;
const int KHZ = 38; // 38kHz carrier frequency for the NEC protocol
const unsigned int  IR_SIGNAL_ON[] = {3500,1700, 450,400, 450,450, 450,1250, 450,1300, 450,400, 450,1250, 450,450, 400,450, 450,400, 450,1250, 450,400, 450,450, 400,1300, 450,400, 450,1300, 450,400, 450,1250, 450,450, 450,400, 450,1250, 450,400, 450,400, 450,450, 450,400, 450,1250, 450,400, 450,1300, 450,1300, 400,450, 450,1250, 450,400, 450,400, 450,450, 450,400, 450,1250, 450,400, 450,400, 450,1300, 450,400, 450,400, 450};  // UNKNOWN F6B92168
const unsigned int  IR_SIGNAL_OFF[] = {3500,1700, 450,400, 450,400, 450,1300, 450,1250, 450,400, 450,1300, 450,400, 450,400, 450,400, 450,1300, 450,400, 450,400, 450,1300, 450,400, 450,1250, 450,450, 450,1250, 450,400, 450,400, 450,1300, 450,400, 450,400, 450,400, 450,400, 450,1300, 450,1300, 400,1300, 450,1300, 450,400, 450,1250, 450,400, 450,450, 450,400, 450,1250, 450,1300, 450,400, 450,400, 450,1300, 450,400, 450,400, 450};  // UNKNOWN 1B9C2A92

void setup() {
  Serial.begin(9600);
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);

}

void loop() {
  if (Serial.available() > 0) { // シリアル通信でデータが送られてくるまで待つ。
    char c = Serial.read(); // 一文字分データを取り出す。
    if (c == '1') { // 1が送られてきたらLEDを点灯させる。
      digitalWrite(LED_BUILTIN, HIGH);
      for (int i = 0; i < 3; i++) {
        irsend.sendRaw(IR_SIGNAL_ON, sizeof(IR_SIGNAL_ON) / sizeof(IR_SIGNAL_ON[0]), KHZ);
        delay(400);
      }
      
    } else if(c == '0') { // 0が送られてきたらLEDを消灯させる。
      digitalWrite(LED_BUILTIN, LOW);
      for (int i = 0; i < 3; i++) {
        irsend.sendRaw(IR_SIGNAL_OFF, sizeof(IR_SIGNAL_OFF) / sizeof(IR_SIGNAL_OFF[0]), KHZ);
        delay(400);
      }
    }
  }
  delay(1000);
}

動作確認

Arduinoに12VのACアダプタを接続して、シリアルモニタから1または0を入力して照明がオン・オフすることを確認する。*2

わかったこと

  • 赤外線LEDは940nmであること。他の波長ではダメ。
  • 赤外線LEDはパワーが弱いものだと動作しない。最初使っていたものはダメだったので、買い直した。
  • 今回使ったLEDは、ACアダプタから電源を供給する必要がある。
  • MOSFETを使うことで電流を増幅することができる。
  • V=IRの計算式はわかるが、実現したい回路を構成が今の知識ではよくわからない。
  • 誤った回路にするとパーツが壊れる。LEDが何個か壊れた。

次回は、Raspberry Piからのオン・オフ操作

*1:リモコンはPanasonic製なのにPanasonicとは認識されなかった。

*2:ACアダプタがないと電力が足りないため動作しない。

Raspberry Pi Zero Wにカメラをつけてみた

Raspberry Pi Zero Wにカメラをつけて、cronで定期的に部屋の中を撮影してみました。

Raspberry Pi Zero Wにカメラをつける

用意するもの

組み立てる

コネクタを使ってRaspberry Piとカメラを接続しケースに収めます。公式ケースはカメラがきれいに収まるようになっています。

FRISKと並べてみました。FRISKより一回り程度大きなサイズです。 f:id:ysysy:20170326215332j:plain

カメラを有効化する

rasp-configを起動します。

$ sudo raspi-config

「5 Interfacing Options」を選択します。 f:id:ysysy:20170326211005p:plain

「P1 Camera」を選択します。 f:id:ysysy:20170326211118p:plain

「Yes」を選択します。 f:id:ysysy:20170326211210p:plain

「Ok」を選択します。 f:id:ysysy:20170326211300p:plain

「Finish」を選択してraspi-configを終了します。 f:id:ysysy:20170326211404p:plain

Webサーバーを導入する

Webサーバーとしてnginxを導入

$ sudo apt-get install nginx

/etc/nginx/sites-available/defaultに60から62行目を追加して、ファイルの一覧を表示できるようにします。

     54         # deny access to .htaccess files, if Apache's document root
     55         # concurs with nginx's one
     56         #
     57         #location ~ /\.ht {
     58         #       deny all;
     59         #}
     60         location /pic {
     61           autoindex on;
     62         }
     63 }

nginxを再起動して設定を有効化します。

$ sudo service nginx restart

写真を保存するディレクトリを作成

$ sudo mkdir /var/www/html/pic
$ sudo chown pi.www-data

撮影用スクリプトを作成する

以下のスクリプトを作成します。今回はファイル名をpic.shとしました。

#!/bin/bash
/usr/bin/raspistill -w 480 -h 360 -ex auto -awb auto -rot 270 -o /var/www/html/pic/$(date +%Y%m%d%H%M).jpeg

スクリプトに実行権限を付与します。

chmod +x pic.sh

cronに登録する

5分ごとに撮影用スクリプトを実行するようcrontabに以下の一行を追加します。

*/5 * * * * /home/pi/pic.sh

ブラウザから確認

http::///pic にアクセスするとファイルの一覧が表示されます。 f:id:ysysy:20170326213946p:plain

感想

リビングに置いていると不在時の様子がわかるので、いつ誰が何をしていたかわかり意外に面白いです。当然、家族の許可がないとできませんが。。。知人に話したら不在時のペットの様子の確認に使ってみたいと言っておりました。確かに誰もいない部屋のペットがどんな行動をしているかは気になりますね。

*1:カメラにコネクタが付属していますが、Raspberry Pi Zeroには接続できないので別途購入する必要があります。ちなみに公式ケースにはケースに収まる短いケーブルが付属しています。私は知らずに長いケーブルを買ってしまいました。

Raspberry Pi Zero WからBluetoothでJBL Flip 3に音を出してみた

Raspberry Pi Zero WからBluetoothJBL Flip 3に音を出せるようにしてみました。

モジュールインストール

 $ sudo apt-get install pulseaudio-module-bluetooth bluez-tools

グループ設定

 $ sudo gpasswd -a pi pulse
 $ sudo gpasswd -a pi lp
 $ sudo gpasswd -a pulse lp
 $ sudo gpasswd -a pi audio
 $ sudo gpasswd -a pulse audio

Bluetoothの設定*1

 $ sudo sh -c "echo 'extra-arguments = --exit-idle-time=-1 --log-target=syslog' >> /etc/pulse/client.conf"
 $ sudo hciconfig hci0 up
 $ sudo hciconfig hci0 class 0x240414
 $ sudo reboot

ペアリング

 $ sudo bluetoothctl
 [NEW] Controller XX:XX:XX:XX:XX:XX RaspberryPi [default]
 [bluetooth]# agent KeyboardOnly
 Agent registered
 [bluetooth]# default-agent
 Default agent request successful
 [bluetooth]# scan on
 Discovery started
 [CHG] Controller  Discovering: yes
 [bluetooth]# pair XX:XX:XX:XX:XX:XX
 [agent] Enter PIN code: 0000  # 0000を入力
 [CHG] Device XX:XX:XX:XX:XX:XX Paired: yes
 Pairing successful
 [CHG] Device XX:XX:XX:XX:XX:XX Connected: no
 [CHG] Device XX:XX:XX:XX:XX:XX RSSI: -60
 [bluetooth]# trust XX:XX:XX:XX:XX:XX
 [bluetooth]# connect XX:XX:XX:XX:XX:XX
 [bluetooth]# exit

Pulseaudioの起動と設定

 $ pulseaudio --start

このコマンドで値を確認

 $ pacmd list-sinks

確認した値を引数として渡す

 $ pacmd set-default-sink bluez_sink.XX_XX_XX_XX_XX_XX

音量調整

 $ alsamixer

再生

 $ mplayer hoge.mp3

Raspberry Piのパワーがないためか、設定が悪いためか音質はあまりよくありませんでした。それとこの設定だけだと再起動すると設定が消えますが、今回は試験的に設定しただけなので設定を永続化する方法まで調べておりません。

参考にしたサイト

OpenWhiskからつぶやけないorz

前回作成した天気予報を取得する仕組みからTwitterにつぶやくプログラムを作ろうとしました。

Twitterの開発者用API取得

Twitterの開発者用のAPIを取得します。

Twitterにアクセスして、[Create New App]をクリックします。

[Name]、[Description]、[Website]への入力し、[Deveopper Aggreement]に同意して、[Create your Twiiter applicaiton] をクリックします。

[Cretae my access toke] をクリックして、アクセストークンを生成したら、[Consumer Key (API Key) ]、[Consumer Secret (API Secret)]、[Access Token]、[Access Token Secret]を控えておきます。

必要なモジュールのインストール

node.js、npmを事前にインストールしておきます。

TwitterAPIをコールするモジュールtwittを導入します。

$ npm install twitt

プログラム作成

index.jsという名前で以下のファイルを作成します。

var Twit = require('twit');
var client = new Twit({
    consumer_key: '先ほど控えた値を指定',
    consumer_secret: '先ほど控えた値を指定',
    access_token: '先ほど控えた値を指定',
    access_token_secret: '先ほど控えた値を指定'
});

function main(params) {
  msg=params.payload;
  //msg='ローカルでバッグ用メッセージ';
  client.post('statuses/update', { status: msg }, function(error, tweet, response) {
    if(error) throw error;
    console.log(tweet);     // Tweet body.
    console.log(response);  // Raw response object.
    return tweet;
  });
}

module.exports.main = main;
// ローカルで実行する場合は以下のコメントを外す
//main(params);

package.jsonの作成

package.jsonという名前で以下のファイルを作成します。

{
  "name": "TweetWeather",
  "main": "index.js",
  "dependencies" : {
    "twit" : "2.2.5"
  }
}

Bluemixへアクションを登録

作成したファイルをZIP化します。

$ zip -r action.zip *

[https://console.ng.bluemix.net/openwhisk/learn/cli:title]より、OpenWhiskのコマンドラインツールをダウンロードします。

プログラムをアップロードして、Bluemix上にアクションを作成します。ここではアクション名をTweetWeatherにしました。

先ほどダウンロードしたツールを次のように実行することでアクションを登録できます。

$ wsk action create TweetWeather –kind nodejs:6 action.zip

前回作成したシーケンスの最期にこのアクションをつなげると、日本語に翻訳した天気予報をtweetできます。と言いたいのですが、OpenWhiskからはなぜかTweetできませんでした。。。ローカルからだとつぶやけるのですが。

次のように意図的にエラーになる行を追加するとつぶやけるので、プログラムの問題だと思います。node.jsをよくわかっていないために正しいプログラムを書けていないようです。

    return tweet;
  });
  throw error;  //意図的にエラーになる行を追加
}

node.jsの勉強が必要ですね。