プログラミング素人が傘持参忘れ防止センサーを作ってみた


Protooutstudioという、プログラミングスクールではなく、プロトタイピングをアウトプットするというスクールに受講生の記事です。
第6回宿題「GW or 初夏にちなんだアウトプット」の制作物として、傘忘れ防止センサーを作ってみました。

const Obniz = require("obniz");
global.fetch = require("node-fetch");
let weahterFlag = "mess"; //分岐用のフラグ
let todayWeather = ""; //分岐用のフラグ

//天気APIを取得する関数を定義しておく
async function callApi() {
  let res = await fetch(
    "http://api.openweathermap.org/data/2.5/forecast?q=tokyo&appid=自分のID" //GETリクエスト
  );
  let resjson = await res.json();
  todayWeather = resjson.list[4].weather[0].main;
}

var obniz = new Obniz("xxxx-xxxx"); // Obniz_IDに自分のIDを入れます
obniz.onconnect = async function () {
  // ディスプレイ処理
  obniz.display.clear(); // 一旦クリアする
  obniz.display.print("umbrella check"); 

  // 超音波距離センサーを呼び出す
  var hcsr04 = obniz.wired("HC-SR04", {
    gnd: 8,
    echo: 9,
    trigger: 10,
    vcc: 11,
  });
  //スピーカーを呼び出す
  var speaker = obniz.wired("Speaker", { signal: 0, gnd: 1 });

  // setIntervalでセンサーから拾う処理の間隔を作る。
  setInterval(async function () {
    //アラート音を流している間は距離情報を拾わないでいいのでフラグの値で分岐させる
    if (weahterFlag === "mess") {
      //距離情報を取得
      var distance = await hcsr04.measureWait();

      // 小数点以下が精密ですごいので整数に丸める
      distance = Math.floor(distance);
      console.log(distance);

      //取得した距離情報が50cm以内だったら人が通ったと判断してAPI取得する
      if (distance < 500) {
        callApi();

        //APIで取得した値が雨だったらアラート音を流す
        if (todayWeather === "Rain") {
          //音を流している間はフラグ情報を変更しておく
          weahterFlag = "alert";

          //アラート音
          await speaker.play(1046.502); // C6 ド 「お」
          await obniz.wait(300);
          await speaker.stop();
          await obniz.wait(100);
          await speaker.play(1318.51); // E6 ミ 「も」
          await obniz.wait(800);
          await speaker.stop();
          await obniz.wait(100);
          await speaker.play(1046.502); // C6 ド 「い」
          await obniz.wait(350);
          await speaker.stop();
          await speaker.play(880.0); // A5 ラ 「で」
          await obniz.wait(300);
          await speaker.stop();
          await speaker.play(783.991); // G5 ソ 「は」
          await obniz.wait(900);
          await speaker.stop();
          await obniz.wait(100);
          await speaker.play(659.255); // E5 ミ 「い」
          await obniz.wait(200);
          await speaker.stop();
          await obniz.wait(100);
          await speaker.play(698.456); // F5 ファ 「つ」
          await obniz.wait(200);
          await speaker.stop();
          await obniz.wait(100);
          await speaker.play(659.255); //  E5 ミ 「の」
          await obniz.wait(200);
          await speaker.stop();
          await obniz.wait(100);
          await speaker.play(698.456); // F5 ファ 「ひ」
          await obniz.wait(200);
          await speaker.stop();
          await obniz.wait(100);
          await speaker.play(1046.502); // C6 ド 「も」
          await obniz.wait(700);
          await speaker.stop();
          await obniz.wait(300);
          await speaker.play(1174.659); // D6 レ 「あ」
          await obniz.wait(180);
          await speaker.stop();
          await obniz.wait(100);
          await speaker.play(1046.502); // C6 ド 「め」
          await obniz.wait(1000);
          await speaker.stop();
          //音を流しきったらフラグ情報を元に戻す
          weahterFlag = "mess";
        } else {
        }
      } else {
      }
    } else {
    }
  }, 2000); // 2000ミリ秒 = 1秒
};

console.log("server litening...");

動かすことができました!

※尚、この動画撮影時は天気が終日曇りだったため
 スピーカーを鳴らすための条件分岐を「Rain」ではなく「Clouds」にしていました

JavaScriptでは「Aが完了したらBの処理をする」という同期的処理を書くのが難しいと
懸念していましたが、「前の処理を待ってから実行させたい」関数には
とりあえず全部awaitをくっつけたらうまく動いてしまっており自分の理解度は不完全燃焼です。

「JS 同期処理」「JS async await」などでWebやYoutube検索していますが
未だに理解できる記事が見つからず・・・
「JSはシングルスレッドで非同期処理」ということは理解したのですがそこから同期的処理をPromiseやasync/awaitを使ってどうコードに落とし込むかとう解説に移るとどの記事も急に難易度が上がりついていけなくなる・・・

「サルでもわかるJS async await」を引き続き探します。