obnizとサーバーレスを組み合わせるTips
obnizとサーバーレスを組み合わせるTips:
これはobniz advent calendarの25日目の記事です。
obnizとサーバーレスとの組み合わせ方ということで、lambdaとかで使うときに気をつけないといけないtipsを書いていこうかなと思います。ちょっと技術よりになります。
スマートスピーカーとかIFTTTとか、イベントきっかけに動かすときにサーバーレス便利ですよね。
でも、普通のプログラムと違うところがいくつか出てくるので、注意が必要です。
この記事のコードはaws lambdaでのプログラムを書いています。他のサーバーレスも同じだと思いますが挙動違い等あったらコメントで教えてください。
サーバーレスでobnizを使う場合、一番気にしないといけないのがこの部分になります。
大抵のサーバーレスは30秒とかのタイムアウトがあり、それ以上プログラムを続けて動かすことができません。
obniz.jsはデフォルトのままだとwebsocketでずっとプログラムを動かそうとしてしまうので、きちんと明示的にobnizへの接続を切る必要があります。
コメントで1)〜3)と書きましたが、この順番がまた重要です。
2)でobnizとの接続を切ると、obniz側がプログラムが終了したとおもってリセット(QRコードの画面)になります。"Hello World"を表示した瞬間に接続を切ってQR画面になると"Hello World"が表示されるのが一瞬すぎて見えないので、1)のwaitを2秒間入れています。
3)のレスポンスを返すのは
lambdaにレスポンスを返すと、強制的にプログラムが終了してしまう(ことがある)ので、これより後にプログラムを書くのは危険です。実行されない可能性があります。
※ココらへんはサーバーレスのサービスごとの仕様によるので、レスポンス返した後も動くものもあるようです
2秒だけじゃなくもっと表示したい場合、
設定100秒とかにで変えることもできますが、その分lambdaの時間を使うのでお金がかかります。CPUもメモリも使ってないただの待ち時間にお金を払うのはちょっと気が引けます。
というわけで、obniz側の設定で乗り切りましょう。
obnizにはプログラム終了後もそのまま出力を維持するコマンド
対象はDisplayとPWMとIOのアウトプットと限定的ですが、lambdaのプログラムが終了後も動かすことができます
これを実行すると、lambdaが終了しても画面に"Hello World"が出たままになります。
消したい場合はobnizの電源を抜き差しするのが手っ取り早いです。
そうするとQRコードが表示される画面に戻ります。
もしくは別のところで
上では
ではobnizがオフラインだったらどうなるでしょうか。ずっとobnizを探し続けて、lambdaのタイムアウトまで探し続けます。ちょっと料金がもったいないですよね。
探す時間を5秒までにしてみます
Javascriptに詳しい方は
ちょと難しくなりました。
obnizには
この関数がasync関数なので、awaitが使えるように全体を
そして
あとは返り値である
さて、サーバーレスとobnizを連動させるときはいろいろ工夫の余地があるのがわかったでしょうか。
とりあえず動く!というところから、順番にステップアップしていければと思います。
これはobniz advent calendarの25日目の記事です。
obnizとサーバーレスとの組み合わせ方ということで、lambdaとかで使うときに気をつけないといけないtipsを書いていこうかなと思います。ちょっと技術よりになります。
サーバーレスとの連携について
スマートスピーカーとかIFTTTとか、イベントきっかけに動かすときにサーバーレス便利ですよね。でも、普通のプログラムと違うところがいくつか出てくるので、注意が必要です。
この記事のコードはaws lambdaでのプログラムを書いています。他のサーバーレスも同じだと思いますが挙動違い等あったらコメントで教えてください。
終了を明確にする
サーバーレスでobnizを使う場合、一番気にしないといけないのがこの部分になります。大抵のサーバーレスは30秒とかのタイムアウトがあり、それ以上プログラムを続けて動かすことができません。
obniz.jsはデフォルトのままだとwebsocketでずっとプログラムを動かそうとしてしまうので、きちんと明示的にobnizへの接続を切る必要があります。
// aws lambda code var Obniz = require("obniz"); exports.helloHandler = function(event, context, callback) { var obniz = new Obniz("obniz_id_here"); obniz.onconnect = async function () { obniz.display.clear(); obniz.display.print("Hello World"); await obniz.wait(2000); // 1) 2秒間待つ obniz.close(); // 2) ここで明示的に接続を切っている callback(null, "success"); // 3) lambdaにレスポンスを返す }; };
2)でobnizとの接続を切ると、obniz側がプログラムが終了したとおもってリセット(QRコードの画面)になります。"Hello World"を表示した瞬間に接続を切ってQR画面になると"Hello World"が表示されるのが一瞬すぎて見えないので、1)のwaitを2秒間入れています。
3)のレスポンスを返すのは
obniz.close()
よりも後である必要があります。lambdaにレスポンスを返すと、強制的にプログラムが終了してしまう(ことがある)ので、これより後にプログラムを書くのは危険です。実行されない可能性があります。
※ココらへんはサーバーレスのサービスごとの仕様によるので、レスポンス返した後も動くものもあるようです
永続的に動作するようにする
2秒だけじゃなくもっと表示したい場合、wait
を10秒とか20秒とかにするのもありですが、lambdaの起動制限(3秒)に引っかかります。設定100秒とかにで変えることもできますが、その分lambdaの時間を使うのでお金がかかります。CPUもメモリも使ってないただの待ち時間にお金を払うのはちょっと気が引けます。
というわけで、obniz側の設定で乗り切りましょう。
obnizにはプログラム終了後もそのまま出力を維持するコマンド
resetOnDisconnect
があります。対象はDisplayとPWMとIOのアウトプットと限定的ですが、lambdaのプログラムが終了後も動かすことができます
// aws lambda code var Obniz = require("obniz"); exports.helloHandler = function(event, context, callback) { var obniz = new Obniz("obniz_id_here"); obniz.onconnect = async function () { obniz.resetOnDisconnect(false); // 1) プログラム終了後も動くようにする obniz.display.clear(); obniz.display.print("Hello World"); obniz.close(); // 2) ここで明示的に接続を切っている callback(null, "success"); // 3) lambdaにレスポンスを返す }; };
消したい場合はobnizの電源を抜き差しするのが手っ取り早いです。
そうするとQRコードが表示される画面に戻ります。
もしくは別のところで
obniz.resetOnDisconnect(true);
とすることでリセットするように戻すことができます。
obnizがofflineのときの挙動を書く
上ではobniz.onconnect
で接続がうまく行った時にいろいろ実行していました。ではobnizがオフラインだったらどうなるでしょうか。ずっとobnizを探し続けて、lambdaのタイムアウトまで探し続けます。ちょっと料金がもったいないですよね。
探す時間を5秒までにしてみます
Javascriptに詳しい方は
Promise.race
とか使えばいいのですが、複雑になるので別の方法で行います。// aws lambda code var Obniz = require("obniz"); exports.helloHandler = function(event, context, callback) { (async function(){ // 1) 全体を (async function(){ ... })(); で囲む var obniz = new Obniz("obniz_id_here"); let connected = await obniz.connectWait({timeout:5}); // 2) onconnectをconnectWaitに変える if(connected){ // 3) if文でobnizがオンラインかどうかを判定する obniz.resetOnDisconnect(false); obniz.display.clear(); obniz.display.print("Hello World"); obniz.close(); callback(null, "success"); }else{ callback(new Error("obniz is not online")); })(); // 1) 全体を (async function(){ ... })(); で囲む };
obnizには
obniz.connectWait
という関数もあり、こちらはタイムアウトを設定できるようになっています。この関数がasync関数なので、awaitが使えるように全体を
(async function(){ ... })();
で囲っていますそして
obniz.connectWait
の引数に{timeout:5}
と、5秒タイムアウトを設定しています。あとは返り値である
connected
を判定してobnizがオンラインかどうかを見ています。
まとめ
さて、サーバーレスとobnizを連動させるときはいろいろ工夫の余地があるのがわかったでしょうか。とりあえず動く!というところから、順番にステップアップしていければと思います。
コメント
コメントを投稿