背景
皆さんテレワークで、仕事中に、届け物が来て、わざわざインターホンの場所に向かって
やり取りしないといけないことはないですか?
特に会議中にこのイベントが発生すると大変ですよね^^;
ゴール
switchbot を使って、インターホンを押されたら
- 通話/終話を押して、カメラをオンにする
- 解錠ボタンを押す
- 通話/終話を押して、カメラをオフにする
これを自動化したいです。
直面した問題
switchbotは
url = "https://api.switch-bot.com/v1.0/devices/${deviceid}/commands";
でAPI呼び出しできます。
インターホンをトリガーとして
- switchbot(下)に通話/終話を押させて、カメラをオンにする
- N秒待って、声をかける
- switchbot(上)に解錠ボタンを押させる
- N秒待つ
- switchbot(下)に通話/終話を押させて、カメラをオフにする
1-5をシーケンシャルに実行する、webアプリを作りたいです
めんどくさいのでHTMLのアンカータグの中でこんな感じで呼び出したいです
<a href="javascript:opengate();">Open Gate</a>
つまりopengateはこんな感じで呼び出したいです。
const nsec = 10;
fetch('switchbot(下)のAPI');
_sleep(nsec);
fetch('switchbot(上)のAPI');
_sleep(nsec);
fetch('switchbot(下)のAPI'))
awaitとPromiseを使ったsleepの方法は見つけましたが
アンカータグの中にawait書いたらasyncの中ではないので怒られてしましました
普通にasyncつかったり色々試せばいいのですが、めんどくさいので手っ取り早く下記で解決しました。
解決策 (ものすごく前置きが長くなってしまいましたが実際に作ったものは下記です)
/**
*
* function _sleep
*
* @param {number} sec - number of secs to wait
* @param {function} cb - function to be executed after waiting
*
*/
const _sleep = (sec, cb) => {
// setTimeout ID
let id = 0;
// wait function
const wait = () => {
// if sec is expired and cb is a "function"
if (sec-- <= 0 &&
"function" === typeof cb) {
cb();
return;
}
// clear current timer and set next timer
if (id > 0) clearTimeout(id);
id = setTimeout(wait, 1000);
};
// set first timer
id = setTimeout(wait, 0);
};
最終的なopengateはこんな感じで実装しました
const opengate = () => {
const nsec = 10;
fetch('switchbot(下)のAPI');
_sleep(nsec, () => {
fetch('switchbot(上)のAPI');
_sleep(nsec, () => fetch('switchbot(下)のAPI'))
});
};
一般的な使い方
console.log("start");
_sleep(2, () => {
console.log("end")
});