Espruino on ESP32 で LINE(その2)
Espruino on ESP32 で Twitter(その3) - いっぺーちゃんの いろいろやってみよ~ のLINE版も作っておきます。
ボタンを押したらLINEにメッセージが飛ぶ、LINEボタンです。
こんな感じです。
var access_token = '取得したアクセストークン'; var messages = [ "%E3%81%8A%E3%81%AF%E3%82%88%E3%81%86", // おはよう "%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF", // こんにちは "%E3%81%93%E3%82%93%E3%81%B0%E3%82%93%E3%81%AF", // こんばんは "%E3%81%8A%E3%82%84%E3%81%99%E3%81%BF", // おやすみ ]; if (typeof(ESP32) ==='function') { // platform is espruino on ESP32 // Wi-Fi アクセスポイントへの接続 var wifi = require('MyWifi'); // set time zone fixed to 'JST' E.setTimeZone(9); // Initialize for switch var sw1 = Pin(21); sw1.mode("input" ); } else { throw "not ESP32"; } // モジュール読み込み var tiny_line = require("tiny_line"); // 初期化 var tl = new tiny_line(access_token, true); tl.on("connect", function() { console.log("%%%% CONNECTED %%%%"); }); tl.on("response", function(code, msg, data) { if (code == 200) { console.log("%%%% RESPONSE : " + code.toString() + " : " + msg + " %%%%"); } else { console.log("%%%% RESPONSE ERROR!!! : " + code.toString() + " : " + msg + " %%%%"); console.log("#### RESPONSE ####"); console.log(data); console.log("############"); } }); tl.on("end", function() { console.log("%%%% END %%%%"); }); function button_down(e) { var msg; var date = new Date(); h = date.getHours(); if (h >=4 && h < 12) { msg = messages[0]; // おはよう } else if (h >=12 && h < 17){ msg = messages[1]; // こんにちは } else if (h >=17 && h < 21){ msg = messages[2]; // こんばんは } else { msg = messages[3]; // おやすみ } tl.notify(msg, true); } setWatch(button_down, sw1, {repeat:true, edge:"falling", debounce:100});
解説を、と思ったけど解説するまでもありませんね。
Twitter用の処理(モジュール読み込みとか初期化とか送信処理など)をLINE用に置き換えただけです。
日本語が使えるようになったので、送信文字列は日本語にしておきました。
Espruino on ESP32 で 今更だけど時刻変更
テスト用に時刻変更しようと思ったら、時刻設定方法ってどうだっけ?とすぐに出てこなかったので、メモ。
以下のように実行すればOK
setTime(Date("2017-07-30T21:00:00").ms/1000)
Date.msで得られる値はミリ秒で、setTime()に設定する値は秒なので、1000で割る。
Dateは年月日区切りは「-」で、時分秒区切りは「:」。その間に「T」を入れる。
Espruino on ESP32 で LINE(その1)
Twitterへのアクセスにも飽きてきたので、今回はLINEにメッセージを投げてみます。
LINEにはWebサービスから簡単にメッセージを送信できる、LINE Notifyというサービスがあります。これを使用すると簡単にLINEにメッセージを送信できます。
LINE Notifyでメッセージを送信するには、アクセストークンを取得する必要があります。
例によって、先人の知恵を拝借してアクセストークンを取得しましょう。
[超簡単]LINE notify を使ってみる - Qiita
自分にだけメッセージを送信したい場合は、トークルームではなく
「1:1でLINE Notifyから通知を受け取る」
を選択します。
通知先は変更できません。変更するにはアクセストークンを再発行してください。
アクセストークンを他人に知られると、勝手にメッセージが送られることがあるので、注意しましょう。
アクセストークンを無効にするには、LINEのマイページにある、「連携中のサービス」から対象のサービスの解除ボタンをクリックしてください。
それでは、LINE Notifyにメッセージを送信するモジュールです。
以下をtiny_line.jsというファイル名でオンボードストレージの /node_modules ディレクトリに格納してください。
var tls = require("tls"); if (typeof(E) ==='function') { // platform is espruino var platform = 'espruino'; } else { // platform is node.js var platform = 'node'; var events = require('events'); var util = require('util'); } // ######## percent encording ################################ var RFC3986_encode = function(str) { // var ret = encodeURIComponent(str); // change according to RFC3986 /* ********** RegEx are not supported in Espruino var ret = encodeURIComponent(str).replace(/[!*'()]/g, function(p) { return "%" + p.charCodeAt(0).toString(16); }); ********** */ var tmp = encodeURIComponent(str); var ret = ""; for (var i = 0; i < tmp.length; i++) { var c = tmp[i]; if ((c==="!") || (c==="*") || (c==="'") || (c==="(") || (c===")")) { ret += '%'+c.charCodeAt(0).toString(16); } else { ret += c; } } return ret; } // ######## tiny_line class ################################ var tiny_line = function(access_token, _DEBUG_) { this.access_token = access_token; this._DEBUG_ = _DEBUG_; if (platform == 'node') { // for EventEmitter events.EventEmitter.call(this); } } if (platform == 'node') { // for EventEmitter util.inherits(tiny_line, events.EventEmitter); } // ######## debug print ################################ tiny_line.prototype.debug_print = function(str) { if (this._DEBUG_) { //console.log(Date().toString()); console.log(str); } } // ######## make request message ################################ tiny_line.prototype.makeRequestMessage = function(method, server, endpoint, message){ method = method.toUpperCase(); // to upper // make message body var body = 'message=' + message; // make request var request = method + ' ' + endpoint + ' HTTP/1.1\n'; // make message header var header = 'Host: ' + server + '\n' + 'User-Agent: espruino line Bot v0.1\n' + 'Accept: */*\n' + 'Connection: close\n' // これがないとレスポンス受信後も接続状態が保持されてしまう + 'Authorization: Bearer ' + this.access_token +'\n' + 'Content-Type: application/x-www-form-urlencoded\n' + 'Content-Length: ' + body.length.toString() + '\n'; // request message var ret = request + header + '\n' + body + '\n'; return ret; } // ######## Send message ################################ tiny_line.prototype.sendmessage = function(host, msg) { var _self = this; var client = tls.connect(host, function() { client.on('data', function(data) { var rcv_header = data.toString(); // 文字列に変換 var p0 = rcv_header.indexOf('\n'); // 最初の改行の位置 var line = rcv_header.slice(0, p0); // 最初の1行取り出し var p1 = line.indexOf(' ') + 1; // 最初のスペースの次(エラーコードの位置) var p2 = line.indexOf(' ', p1) + 1; // 二個目のスペースの次(エラーメッセージの位置) var err_code = parseInt(line.slice(p1, p2)); var err_msg = line.slice(p2); _self.emit("response", err_code, err_msg, rcv_header); }); client.on('end', function() { _self.emit("end"); }); _self.emit("connect"); client.write(msg); }); } // ######## notify API ################################ tiny_line.prototype.notify = function(msg, encoded) { if (!msg) { throw new Error("message is required."); } var server = 'notify-api.line.me'; var host = { host: server, port: 443}; // メッセージがエンコードされていなければエンコードする if (!encoded) { msg = RFC3986_encode(msg); } var reqMessage = this.makeRequestMessage('POST', server, '/api/notify', msg); this.debug_print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); this.debug_print(reqMessage); this.debug_print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); this.sendmessage(host, reqMessage); } module.exports = tiny_line; module.exports.RFC3986_encode = RFC3986_encode;
準備ができたら、以下のプログラムを実行してみましょう。
var access_token = '取得したアクセストークン'; if (typeof(ESP32) ==='function') { // platform is espruino on ESP32 // Wi-Fi アクセスポイントへの接続 var wifi = require('MyWifi'); } if (typeof(E) ==='function') { // platform is espruino // set time zone fixed to 'JST' E.setTimeZone(9); } // モジュール読み込み var tiny_line = require("tiny_line"); // 初期化 var tl = new tiny_line(access_token, true); tl.on("connect", function() { console.log("%%%% CONNECTED %%%%"); }); tl.on("response", function(code, msg, data) { if (code == 200) { console.log("%%%% RESPONSE : " + code.toString() + " : " + msg + " %%%%"); } else { console.log("%%%% RESPONSE ERROR!!! : " + code.toString() + " : " + msg + " %%%%"); console.log("#### RESPONSE ####"); console.log(data); console.log("############"); } }); tl.on("end", function() { console.log("%%%% END %%%%"); }); // メッセージ送信 tl.notify("good morning! (or afternoon)", false);
プログラムを実行すると、LINEに以下のようなメッセージが送信されます。
「[トークン名] good morning! (or afternoon)」
以下、プログラムの説明です。
Twitterのときにも使った、ESP32専用設定、Espruino専用設定の部分です。
if (typeof(ESP32) ==='function') { // platform is espruino on ESP32 // Wi-Fi アクセスポイントへの接続 var wifi = require('MyWifi'); } if (typeof(E) ==='function') { // platform is espruino // set time zone fixed to 'JST' E.setTimeZone(9); }
モジュールを読み込みます。
// モジュール読み込み var tiny_line = require("tiny_line");
tiny_lineのインスタンスを生成します。
第1パラメータは↑で取得したアクセストークンです。
第2パラメータはモジュール内部のdebug_print (今回はtypo直しました)を表示するか否かを指定しています。
色々表示されてうっとうしい場合はfalseにしてください。
// 初期化 var tl = new tiny_line(access_token, true);
接続処理時のイベントハンドラです。イベントは"open"、"response"、"end"があります。
"response"イベントのパラメータは
code エラーコード
msg エラーメッセージ
data 受信データ全体
です。
tl.on("connect", function() { console.log("%%%% CONNECTED %%%%"); }); tl.on("response", function(code, msg, data) { if (code == 200) { console.log("%%%% RESPONSE : " + code.toString() + " : " + msg + " %%%%"); } else { console.log("%%%% RESPONSE ERROR!!! : " + code.toString() + " : " + msg + " %%%%"); console.log("#### RESPONSE ####"); console.log(data); console.log("############"); } }); tl.on("end", function() { console.log("%%%% END %%%%"); });
メッセージの送信処理です。
第1パラメータが送信する文字列、
第2パラメータが文字列がパーセントエンコード済みか否かを示すフラグです。これがfalse または省略されていると、送信文字列をnotify関数内部でエンコードします。
// メッセージ送信 tl.notify("good morning! (or afternoon)", false);
メッセージ送信部分を以下のように変更すると、
「[トークン名] 現在の時刻は Sat Jul 29 2017 11:15:37 GMT+0900 です」
のような日本語を含んだメッセージを送信することもできます。
var date = new Date(); date_str = tiny_line.RFC3986_encode(date.toString()); var str1 = "%E7%8F%BE%E5%9C%A8%E3%81%AE%E6%99%82%E5%88%BB%E3%81%AF%20"; // 現在の時刻は var str2 = "%20%E3%81%A7%E3%81%99"; // です tl.notify(str1 + date_str + str2, true);
notify関数の第1パラメータにパーセントエンコード済みの送信文字列を、第2パラメータにtrueを指定します。
パーセントエンコードはRFC2396でも大丈夫なようですが、念のためRFC3986にしてあります。
全角文字を含む静的な文字列のパーセントエンコードは、以下のサイトなどで行えます。
http://www.tagindex.com/tool/url.html
(文字コードで「UTF-8」を選択してから「エンコードする」ボタンをクリックしてください)
動的に変更したい半角文字列はtiny_line の RFC3986_encode 関数がエクスポートされているので、それを使えばOK。
Espruino on ESP32 で Twitter(その5)
前回 と Espruino on ESP32 でLチカ - いっぺーちゃんの いろいろやってみよ~ を組み合わせて、TwitterからLEDを制御してみましょう。
以下にそのプログラムを示します。
consumer_key = '取得した Consumer key'; consumer_secret = '取得した Consumer secret'; access_token = '取得した Access Token'; access_secret = '取得した Access Token Secret'; if (typeof(ESP32) ==='function') { // platform is espruino on ESP32 // Wi-Fi アクセスポイントへの接続 var wifi = require('MyWifi'); // Initialize for LED1 var led1 = Pin(23); led1.mode("output"); led1.reset(); var led_on = function() { led1.set(); }; var led_off = function() { led1.reset(); }; } else { var led_on = function() { console.log("LED ON"); }; var led_off = function() { console.log("LED OFF"); }; } if (typeof(E) ==='function') { // platform is espruino // set time zone fixed to 'JST' E.setTimeZone(9); } // モジュール読み込み var tiny_twitter = require("tiny_twitter"); // 初期化 var tw = new tiny_twitter(consumer_key, consumer_secret, access_token, access_secret, true); tw.on("connect", function() { console.log("%%%% CONNECTED %%%%"); }); tw.on("response_header", function(data, code, msg) { if (code != 200) { console.log("%%%% RESPONSE ERROR!!! " + code.toString() + " : " + msg); } console.log("%%%% RESPONSE_HEADER %%%%\n" + data + "\n%%%%%%%%%%%%%%%%%%%%%%%%%"); }); tw.on("data", function(data) { console.log("%%%% DATA %%%%"); // console.log(JSON.stringify(data, null, '\t')); if (data.text) { console.log(data.text); if (data.text.indexOf('LED') >= 0) { if (data.text.indexOf('ON') >= 0) { led_on(); } else if (data.text.indexOf('OFF') >= 0) { led_off(); } } } else { console.log("** NO TEXT **"); } console.log("%%%%%%%%%%%%%%%%%%%%%%%%%"); }); tw.on("end", function() { console.log("%%%% END %%%%"); }); // オプション指定 param = {"with":"user"}; // twitterに接続 tw.userstream(param);
前回との差分です。
ESP32のときは、LED用の端子の初期化とそれをON/OFFする関数を定義しています。
// Initialize for LED1 var led1 = Pin(23); led1.mode("output"); led1.reset(); var led_on = function() { led1.set(); }; var led_off = function() { led1.reset(); };
それ以外の場合は、LED制御ができないので、コンソールにON/OFFを表示する関数を代替処理として定義しています。
var led_on = function() { console.log("LED ON"); }; var led_off = function() { console.log("LED OFF"); };
また、データ受信時のイベントハンドラ内で、メッセージ本体内に「LED」と「ON」が含まれていたらLEDをONする関数をコール、
「LED」と「OFF」が含まれていたらLEDをOFFする関数をコールする処理を追加しています。
「LED ON OFF」や「LED not ON」 のような意地悪なメッセージは考慮していません(この実装ではどちらもONとして扱われる)。
if (data.text.indexOf('LED') >= 0) { if (data.text.indexOf('ON') >= 0) { led_on(); } else if (data.text.indexOf('OFF') >= 0) { led_off(); } }
プログラムを実行したら、ここで使用しているアカウントで、ブラウザやスマホから「LED ON 1」とtweetしてみましょう。
LEDが点灯したと思います。
大文字、小文字は区別されますので、すべて大文字にしてください。
しつこいようですが、全角文字ではダメです。
最後の「1」は連続してtweetするときに同じ文にならないように追加しているだけなので、何でもかまいません。
連続してtweetするときはこの部分を変更してtweetしてください。
「LEDON」のように空白を挟まない場合や「ON LED」と順序を逆にした場合でもOKです。
次に「LED OFF 1」とtweetするとLEDが消灯します。
オプションを以下のようにすると、
ハッシュタグ「#ESP32_LED_CONTROL」が付いた自分以外からのtweetでもLEDをコントロールすることができます。
(文字列を見ているだけなので、ハッシュタグである必要はないですが)
param = {"with":"user", "track":"#ESP32_LED_CONTROL"};
ESP32 に赤外線LEDつけて、リモコン処理を代替できるようにすると、TwitterからエアコンのON/OFFができる、なんて夢が広がりますね(←勝手にエアコンONされて、電気代がぁぁぁ、って心配が。。。)
twitterに関する記事はこれでおしまい。
Espruino on ESP32 で Twitter(その4)
前々回、前回とtweetする方のプログラムだったので、今回はtweet内容を受信するプログラムを試してみます。
最初に注意事項です。あまりたくさんのtweetを一度に受信してしまうと、メモリ不足で落ちてしまいます。
ここでは、Streaming API の User streams を使用します。
User streams というのは、大雑把に言うと自分のタイムラインに流れてくるメッセージを監視するものです。
取得対象はその時点で流れてくるメッセージなので、過去にtweetされたメッセージは取得できません。
APIの詳細は User streams — Twitter Developers を参照してください。
それでは、以下のプログラムを実行してみましょう。
consumer_key = '取得した Consumer key'; consumer_secret = '取得した Consumer secret'; access_token = '取得した Access Token'; access_secret = '取得した Access Token Secret'; if (typeof(ESP32) ==='function') { // platform is espruino on ESP32 // Wi-Fi アクセスポイントへの接続 var wifi = require('MyWifi'); } if (typeof(E) ==='function') { // platform is espruino // set time zone fixed to 'JST' E.setTimeZone(9); } // モジュール読み込み var tiny_twitter = require("tiny_twitter"); // 初期化 var tw = new tiny_twitter(consumer_key, consumer_secret, access_token, access_secret, true); tw.on("connect", function() { console.log("%%%% CONNECTED %%%%"); }); tw.on("response_header", function(data, code, msg) { if (code != 200) { console.log("%%%% RESPONSE ERROR!!! " + code.toString() + " : " + msg); } console.log("%%%% RESPONSE_HEADER %%%%\n" + data + "\n%%%%%%%%%%%%%%%%%%%%%%%%%"); }); tw.on("data", function(data) { console.log("%%%% DATA %%%%"); // console.log(JSON.stringify(data, null, '\t')); if (data.text) { console.log(data.text); } else { console.log("** NO TEXT **"); } console.log("%%%%%%%%%%%%%%%%%%%%%%%%%"); }); tw.on("end", function() { console.log("%%%% END %%%%"); }); // オプション指定 param = {"with":"user"}; // twitterに接続 tw.userstream(param);
初期化までと、接続時、ヘッダ受信時、切断時のイベントハンドラは前回と同じです。
データ受信時のイベントハンドラでは受信したメッセージ本体だけを表示するように変更してあります。
受信したデータ全部を表示したいときは、以下の部分を有効化してください。
console.log(JSON.stringify(data, null, '\t'));
あとは、オプションを指定してuserstreamを実行しています。
このプログラムは接続すると、サーバ側から切断されるか、リセットするまで接続を保持します。
このモジュールは簡易的な実装なので、能動的な接続の切断や再接続については考慮されていません。
プログラムを実行すると、以下のように表示されるでしょう。
%%%% CONNECTED %%%%
%%%% RESPONSE_HEADER %%%%
HTTP/1.1 200 OK
~中略~
%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% DATA %%%%
** NO TEXT **
%%%%%%%%%%%%%%%%%%%%%%%%%
最初に「** NO TEXT **」と表示されるのは、friends list というのが送られてくるからです。フォローしている人の一覧のようです。
この状態で、ここで使用しているアカウントで、ブラウザやスマホからtweetしてみましょう。
%%%% DATA %%%% hogehoge1 %%%%%%%%%%%%%%%%%%%%%%%%%
こんな表示が出ると思います。
え?こんな表示が出た?
%%%% DATA %%%% dDc_・ %%%%%%%%%%%%%%%%%%%%%%%%%
それは、日本語をtweetしたからでしょう。
Espruinoは日本語に対応していないので、半角文字しか認識できません。
ちなみに、↑が出たときは「ついったー」とtweetしました。
オプション指定を以下のようにすると、自分のtweetとフォローしている人のtweetが取得できます。
(タイムラインの表示とほぼ同じ)
param = {"with":"followings"};
また、以下の指定では、自分のtweetすべてとキーワード"hogehoge"を含むtweet(フォローしている人以外も)が取得できます。
param = {"with":"user", "track":"hogehoge"};
trackに指定するキーワードは空白区切り、またはカンマ区切りで複数指定することができます。
空白区切り | "track":"hogehoge fugafuga" | hogehoge と fugafuga の両方を含む |
カンマ区切り | "track":"hogehoge,fugafuga" | hogehoge か fugafuga のどちらか一方を含む |
"track"に"test"のような一般的なキーワードを指定すると、たくさんのtweetが取得できてしまい、メモリ不足で落ちますので、注意してください。
複数のアカウントからのメッセージを取得したいような場合、ユニークなキーワードを含めてtweetするような運用にするのが良いでしょう。
また、キーワードには "#hoge" のように、ハッシュタグを指定することもできます。
しつこいようですが、Espeuinoは日本語に対応していないので、日本語のキーワードは指定できません。
「自分のtweet かつ、キーワード○○を含む」というような指定はできないようです。このような条件を実現するには、一旦自分のtweetをすべて取得して、
その中でメッセージに○○を含むかどうか確認するしか方法はないようです。
次回 に続く。。。
Espruino on ESP32 で Twitter(その3)
Espruino on ESP32 でぽちっとな - いっぺーちゃんの いろいろやってみよ~ と Espruino on ESP32 で Twitter(その2) - いっぺーちゃんの いろいろやってみよ~ を組み合わせてTweetボタンを作ってみましょう。
大雑把に言うと Espruino on ESP32 でぽちっとな - いっぺーちゃんの いろいろやってみよ~ でスイッチのステータスを表示していた部分をtweet処理に変えるだけです。
以下、そのソースです。
consumer_key = '取得した Consumer key'; consumer_secret = '取得した Consumer secret'; access_token = '取得した Access Token'; access_secret = '取得した Access Token Secret'; if (typeof(ESP32) ==='function') { // platform is espruino on ESP32 // Wi-Fi アクセスポイントへの接続 var wifi = require('MyWifi'); // set time zone fixed to 'JST' E.setTimeZone(9); // Initialize for switch var sw1 = Pin(21); sw1.mode("input" ); } else { throw "not ESP32"; } // モジュール読み込み var tiny_twitter = require("tiny_twitter"); // 初期化 var tw = new tiny_twitter(consumer_key, consumer_secret, access_token, access_secret, true); tw.on("connect", function() { console.log("%%%% CONNECTED %%%%"); }); tw.on("response_header", function(data, code, msg) { if (code != 200) { console.log("%%%% RESPONSE ERROR!!! " + code.toString() + " : " + msg); } console.log("%%%% RESPONSE_HEADER %%%%\n" + data + "\n%%%%%%%%%%%%%%%%%%%%%%%%%"); }); tw.on("data", function(data) { console.log("%%%% DATA %%%%"); console.log(JSON.stringify(data, null, '\t')); // エラー時はdata.errors.code data.errors.message に情報が入る console.log("%%%%%%%%%%%%%%%%%%%%%%%%%"); }); tw.on("end", function() { console.log("%%%% END %%%%"); }); function button_down(e) { var msg; var date = new Date(); h = date.getHours(); if (h >=4 && h < 12) { msg = 'Good morning, everyone!!'; } else if (h >=12 && h < 17){ msg = 'Good afternoon, everyone!!'; } else if (h >=17 && h < 21){ msg = 'Good evening, everyone!!'; } else { msg = 'Good night, everyone!!'; } tw.tweet(msg, {"trim_user":true,"include_entities":false}); } setWatch(button_down, sw1, {repeat:true, edge:"falling", debounce:100});
このプログラムを実行すると、Pin21に接続されたスイッチを押すたびにその時刻に応じた挨拶がtweetされます。
スイッチを押してからtweet完了まで4~5秒程度かかります。
tweet完了前に再度スイッチを押したときの動作は未確認です(メモリ不足で落ちそうな気がするけど)。
tweet開始~endイベントまで次のtweet要求をブロックすれば良いのかな?
ま、ぽんぽん押さなければ良いだけなので、そのままにしておこう。
以下処理の説明です。
ESP32の場合はWi-Fiに接続してタイムゾーンを設定し、スイッチ用の端子を初期化します。
それ以外の環境ではスイッチが使えないのでエラー終了します。
if (typeof(ESP32) ==='function') { // platform is espruino on ESP32 // Wi-Fi アクセスポイントへの接続 var wifi = require('MyWifi'); // set time zone fixed to 'JST' E.setTimeZone(9); // Initialize for switch var sw1 = Pin(21); sw1.mode("input" ); } else { throw "not ESP32"; }
モジュール読み込み~イベントハンドラは前回と同じです。
スイッチが押されたときのハンドラです。
現在時刻を取得し、時刻に応じた挨拶をtweetしています。
時刻の区切りには異論もあるでしょうけど。。。
日本語が使えれば、もうちょっと気の利いたtweetができるんですが。。。。
function button_down(e) { var msg; var date = new Date(); h = date.getHours(); if (h >=4 && h < 12) { msg = 'Good morning, everyone!!'; } else if (h >=12 && h < 17){ msg = 'Good afternoon, everyone!!'; } else if (h >=17 && h < 21){ msg = 'Good evening, everyone!!'; } else { msg = 'Good night, everyone!!'; } tw.tweet(msg, {"trim_user":true,"include_entities":false}); }
スイッチにハンドラを割り当てます。
今回はスイッチが押されたときだけ処理したいので、「edge:"falling"」としています。
setWatch(button_down, sw1, {repeat:true, edge:"falling", debounce:100});
これで、わざわざESP32からtweetする価値が出てきたかな?
温度センサの値を読んで、定期的(10分に1回とか)にtweetする、なんて使い方もできそうですね。
次回に続く。。。
Espruino on ESP32 で Twitter(その2)
以下がtwitterにアクセスするためのモジュールです。
さらっと書いてますが、血と汗と涙の結晶です。
====2017/08/03追記 ここから====
Espruino on ESP32 で Twitter にも日本語を - いっぺーちゃんの いろいろやってみよ~で新しいバージョンを公開しました
====2017/08/03追記 ここまで====
====2017/08/03削除 ここから====
zipファイルを解凍してオンボードストレージの /node_modules ディレクトリに格納してください。
====2017/07/30追記 ここから====
Node.jsで実行するとエラーになりました。
Espruino用HMACSHA1モジュールの仕様を変更したのを忘れてました(^^ゞ
以下の修正で使用できるようになります。
--- tiny_twitter.js.old2 2017-07-30 11:37:47.540869675 +0900 +++ tiny_twitter.js 2017-07-30 11:40:36.641894478 +0900 @@ -113,7 +113,11 @@ // make signature var signing_key = RFC3986_encode(this.consumer_secret) + '&' + RFC3986_encode(this.access_secret); // console.log("key:" + signing_key); - var sig = hmacsha1.b64(signing_key, sigbase_str); + if (platform == 'node') { + var sig = hmacsha1(signing_key, sigbase_str); + } else { + var sig = hmacsha1.b64(signing_key, sigbase_str); + } this.degug_print('sig: ' + sig); var oauth_head = ' OAuth oauth_consumer_key="' + RFC3986_encode(this.consumer_key) + '",\n'
====2017/07/30追記 ここまで====
====2017/08/03削除 ここまで====
また、twitterにアクセスするにはアカウントのほか、4つのキーを取得する必要があります。
(Consumer key、Consumer secret、Access Token、Access Token Secret)
自分で手順書くのが面倒なので、先人の成果をパクり、、いやいや参照させて頂くことにします。
ここの手順に従ってキーを取得してください。
TwitterのAPIを使用するために必要なキーを取得する手順 - Hello API
これらのキー(特にsecretと付く方)はパスワードみたいなものなので、取り扱いには十分注意しましょう。
普段使っているアカウントでいきなり変なtweetをすると、フォロワーがびっくりするので、別のアカウントを用意するのが良いかもしれません。
まずはtweetしてみます。
以下のプログラムを実行してみましょう。
consumer_key = '取得した Consumer key'; consumer_secret = '取得した Consumer secret'; access_token = '取得した Access Token'; access_secret = '取得した Access Token Secret'; if (typeof(ESP32) ==='function') { // platform is espruino on ESP32 // Wi-Fi アクセスポイントへの接続 var wifi = require('MyWifi'); } if (typeof(E) ==='function') { // platform is espruino // set time zone fixed to 'JST' E.setTimeZone(9); } // モジュール読み込み var tiny_twitter = require("tiny_twitter"); // 初期化 var tw = new tiny_twitter(consumer_key, consumer_secret, access_token, access_secret, true); tw.on("connect", function() { console.log("%%%% CONNECTED %%%%"); }); tw.on("response_header", function(data, code, msg) { if (code != 200) { console.log("%%%% RESPONSE ERROR!!! " + code.toString() + " : " + msg); } console.log("%%%% RESPONSE_HEADER %%%%\n" + data + "\n%%%%%%%%%%%%%%%%%%%%%%%%%"); }); tw.on("data", function(data) { console.log("%%%% DATA %%%%"); console.log(JSON.stringify(data, null, '\t')); // エラー時はdata.errors.code data.errors.message に情報が入る console.log("%%%%%%%%%%%%%%%%%%%%%%%%%"); }); tw.on("end", function() { console.log("%%%% END %%%%"); }); // tweetする var message = "test tweet"; var param = {"trim_user":true,"include_entities":false}; tw.tweet(message, param);
成功すれば、「test tweet《改行》(Thu Jul 24 2017 12:29:46 GMT+0900)」のようにtweetされるはずです。
もちろん、ESP32がインターネットにアクセスできるWi-Fiルータにつながってなければ、失敗します。
もし、時刻があってないと(そんなに厳密でなくてもかまいません。何時間とか何日レベルでずれている場合)は、エラーになりますので、時刻合わせを行っておいてください。
tweetするメッセージに時刻を追加するようにしてあります。これは同じメッセージを短い時間内にtweetすると「それ、さっき呟いたやんけ~」とエラーになるため、それを回避するためにtweet処理の中で時刻を付加しています。
調子に乗って何回もtweetしてると、アカウントをロックされることがありますので、注意してください。
以下処理の説明です。
ESP32の場合はWi-Fiに接続します。
接続状態を維持しているならここはなくても構いません。前に書いたMyWifi.jsを使用しています。
ESP32上のEspruinoだと、「ESP32」というbuilt-in moduleが存在するので、それで判断しています。
if (typeof(ESP32) ==='function') { // platform is espruino on ESP32 // Wi-Fi アクセスポイントへの接続 var wifi = require('MyWifi'); }
Espruinoの場合はタイムゾーンを設定します。
Espruinoだと、「E」というbuilt-in moduleが存在するので、それで判断しています。
ここはLinux版Espruinoの場合も実行されます。
Espruinoでしか使わないならいきなりタイムゾーン設定でも構いません。
if (typeof(E) ==='function') { // platform is espruino // set time zone fixed to 'JST' E.setTimeZone(9); }
なぜ、こんなコードを入れているのか?
いい質問ですねぇ~。
このプログラム、実はnode.jsでも動くんです。
デバッグしやすいので、最初node.jsでデバッグしてた名残です。
せっかくなので、残しておきました。
node.js⇔Linux版Espruinoを行き来しながらデバッグして、最後にESP32で動作確認、な感じでデバッグしてました
モジュールを読み込みます。
これをしないと始まりません。
var tiny_twitter = require("tiny_twitter");
tiny_twitterのインスタンスを生成します。
パラメータの最初の4つは↑で取得したキーです。最後のパラメータはモジュール内部のdegug_print (あ、typoだ。めんどいからそのままで)を表示するか否かを指定しています。
色々表示されてうっとうしい場合はfalseにしてください。
var tw = new tiny_twitter(consumer_key, consumer_secret, access_token, access_secret, true);
サーバに接続されたときのイベントハンドラです。
特に処理はないので、接続した旨表示しているだけです。
tw.on("connect", function() { console.log("%%%% CONNECTED %%%%"); });
受信データのうち、ヘッダ部分を受信したときのイベントハンドラです。
codeが200以外のときは、接続エラーなので、エラーと表示しています。
また、デバッグ用にヘッダ全体を表示しています。
tw.on("response_header", function(data, code, msg) { if (code != 200) { console.log("%%%% RESPONSE ERROR!!! " + code.toString() + " : " + msg); } console.log("%%%% RESPONSE_HEADER %%%%\n" + data + "\n%%%%%%%%%%%%%%%%%%%%%%%%%"); });
受信データのうち、データの中身を受け取ったときのイベントハンドラです。
データはJSON形式で送られてくるので、JSON.stringifyで文字列化して表示しています。
tw.on("data", function(data) { console.log("%%%% DATA %%%%"); console.log(JSON.stringify(data, null, '\t')); // エラー時はdata.errors.code data.errors.message に情報が入る console.log("%%%%%%%%%%%%%%%%%%%%%%%%%"); });
サーバとの接続が切断されたときのイベントハンドラです。
特に処理はないので、切断した旨表示しているだけです。
tw.on("end", function() { console.log("%%%% END %%%%"); });
実際にtweetする部分です。
paramは APIリファレンス を参照してください。指定しても動くかどうかわかりませんが。。。
この設定だと、受信するデータがちょっと小さくなります。
var message = "test tweet"; var param = {"trim_user":true,"include_entities":false}; tw.tweet(message, param);
今回はここまで。
次回に続く。。。