Obniz×LINE Botで酔い具合を教えてくれる優しいBotを作りたかったんだけど…

<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2775528/c81c48d5-ed6a-cedb-673a-8d0e13c232b9.png">

## おさけのみたい
お酒が好きです。この世に「太る」という概念が無いなら毎日揚げ物とビールで乾杯したいタイプです。
とは言ってもまじめな現代社会。心置きなくお酒が飲めるタイミングは休日前の夜などに限られています。
明日に響かないくらいのお酒がどれくらいかわからないので、obnizにアルコールの度数を測ってもらい、どれくらいお酒に酔ってるか教えてくれるLINE Botを作りたいと思います。

## 完成したけど…あれ？
とゆーことで完成しました！
LINEに話しかけたらObnizが起動してアルコールセンサーが作動します。
アルコールセンサーは過熱に時間がかかるので準備ができたらお知らせしてくれる機能付きです。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">LINEで連絡したら空気中のアルコールを測ってくれる「のめるくん」を作成しました！<br>アルコールを検知すると鋭い音が鳴ります(試聴注意)<br>これできっと二日酔いはないはず…！<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://twitter.com/hashtag/linedc?src=hash&amp;ref_src=twsrc%5Etfw">#linedc</a> <a href="https://twitter.com/hashtag/obniz?src=hash&amp;ref_src=twsrc%5Etfw">#obniz</a> <a href="https://t.co/zTJs0IOZty">pic.twitter.com/zTJs0IOZty</a></p>&mdash; あべれん (@rencoln1229) <a href="https://twitter.com/rencoln1229/status/1582014801680945153?ref_src=twsrc%5Etfw">October 17, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

とりあえず完成記念という体の宴会をスタートしていきましょう！いや～うれしいな～！我ながら天才だな～！
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2775528/0299fe20-a12a-06e5-6953-db42ac1a30b3.png">
※イメージ図です。

よし！そろそろだいぶ飲んだし、のめる君が止め時を教えてくれるはず！
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2775528/77e9b09c-ea8b-5a47-43b7-cad539fabdcb.jpeg">

あ、あれ？なんかのめるくん、こんな感じだったっけ？
ほんとにまだ飲めるのかな？というか、それテキーラじゃないの？？？
と、とりあえずおすすめされたし飲んでみるか…
・
・
・
さすがにもう限界かな！のめる君、そろそろ僕を止めておくれ！
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2775528/171203aa-7aaf-34f7-f2a5-0180c7a8165f.jpeg">
…私が悪かったです！もう許してください…orz

## という制作をしたかったのですが途中で詰まってしまいました…
ここまで読んでくださりありがとうございます。
見出しの通りですが、アルコールを検知するところまでは実装ができたのですが
アルコールの情報を取得し、LINEに通知する部分で詰まってしまい時間切れでした。
ですが、ここまでやったことは記事にしたいと思います！

**環境**
- [Visual Studio Code 1.71.2](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)
- [node.js v18.7.0](https://nodejs.org/ja/)
- [LINE Developers](https://developers.line.biz/en/)

**使用した機材や配線**
- obniz Board 1Y
- ミニブレッドボード　BB－601（白）
- アルコールセンサー　MQ3
- 超音波距離センサー　HC－SR04[101-60-142 / 20-019-100-A]

組み立てるとこんな感じになります。
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2775528/9dc95e0b-23e0-6538-5684-26649f4d4aff.png">

**ソースコード**
```javascript:nomerukun
'use strict';

// ########################################
//               初期設定など
// ########################################

const Obniz = require('obniz');
const obniz = new Obniz('********');

// パッケージを使用します
const express = require('express');
const line = require('@line/bot-sdk');
const axios = require('axios');

// ローカル（自分のPC）でサーバーを公開するときのポート番号です
const PORT = process.env.PORT || 3000;

// Messaging APIで利用するクレデンシャル（秘匿情報）です。
const config = {
  channelSecret: '****************',
  channelAccessToken: '****************'
};

// ########## ▼▼▼ サンプル関数 ▼▼▼ ##########
const sampleFunction = async (event) => {
  return client.replyMessage(event.replyToken, [{
    type: 'text',
    text: 'ちょっと待っててね…'
  }, {
    type: 'text',
    text: 'センサーを起動しているよ'
  }, {
    type: 'text',
    text: 'ブザーが鳴ったら息を吹きかけてみて!'
  },
  ]); //画像
};
// ########## ▲▲▲ サンプル関数 ▲▲▲ ##########

obniz.onconnect = async function () {
  obniz.display.clear();
  obniz.display.print("YONETSUCHU!");

  //MQ3ガスセンサのライブラリを使用する
  const mq3 = obniz.wired("MQ3", { vcc: 3, gnd: 0, do: 1, ao: 2 });
  const speaker = obniz.wired("Speaker", { signal: 10, gnd: 11 });

  //予熱が必要になる環境によるが60秒～120秒必要
  await mq3.heatWait(60);
  obniz.display.clear();
  //臭いを取れる準備が出来たら画面でお知らせ
  obniz.display.print("ObnizReady");

  //臭いを取れる準備が出来たら音で
  speaker.play(262); //ど
  obniz.wait(500);
  speaker.play(294); //れ
  obniz.wait(500);
  speaker.play(330); //み
  obniz.wait(500);
  speaker.play(349); //ふぁ
  obniz.wait(500);
  speaker.play(392); //そ
  obniz.wait(500);
  speaker.play(440); //ら
  obniz.wait(500);
  speaker.play(494); //し
  obniz.wait(500);
  speaker.play(523); //ど
  obniz.wait(500);
  speaker.stop();

  mq3.onchangeanalog = function (value) {
    if (value < 1) {
      //臭いを検知後、再度図れる状態になった処理
      client.pushMessage(event.source.userId, {
        type: 'text',
        text: 'まだまだ飲めそうですね！！！',
    });
    } else if(1 <= value && value < 2) {
      client.pushMessage(event.source.userId, {
        type: 'text',
        text: 'まだまだ飲めそうですね！',
    });
    }
  }
  await obniz.wait(100);
  console.log(value);
}

// ########################################
//  LINEサーバーからのWebhookデータを処理する部分
// ########################################

// LINE SDKを初期化します
const client = new line.Client(config);

// LINEサーバーからWebhookがあると「サーバー部分」から以下の "handleEvent" という関数が呼び出されます
async function handleEvent(event) {
  // 受信したWebhookが「テキストメッセージ以外」であればnullを返すことで無視します
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }
  // サンプル関数を実行します
  return sampleFunction(event);
}

// ########################################
//          Expressによるサーバー部分
// ########################################

// expressを初期化します
const app = express();

// HTTP POSTによって '/webhook' のパスにアクセスがあったら、POSTされた内容に応じて様々な処理をします
app.post('/webhook', line.middleware(config), (req, res) => {

  // 検証ボタンをクリックしたときに飛んできたWebhookを受信したときのみ以下のif文内を実行
  if (req.body.events.length === 0) {
    res.send('Hello LINE BOT! (HTTP POST)'); // LINEサーバーに返答します（なくてもよい）
    console.log('検証イベントを受信しました！'); // ターミナルに表示します
    return; // これより下は実行されません
  } else {
    // 通常のメッセージなど … Webhookの中身を確認用にターミナルに表示します
    console.log('受信しました:', req.body.events);
  }

  // あらかじめ宣言しておいた "handleEvent" 関数にWebhookの中身を渡して処理してもらい、
  // 関数から戻ってきたデータをそのままLINEサーバーに「レスポンス」として返します
  Promise.all(req.body.events.map(handleEvent)).then((result) => res.json(result));
});

// 最初に決めたポート番号でサーバーをPC内だけに公開します
// （環境によってはローカルネットワーク内にも公開されます）
app.listen(PORT);
console.log(`ポート${PORT}番でExpressサーバーを実行中です…`);
```

## 今後の課題
アルコールセンサーで検知を行うことができましたが、このままだと値を取得し続けてしまうので改善が必要そうです。
またアルコールセンサーの値に応じてコメントを出しわけるなども実装し、のめるくんとしてのひとまずの完成を迎えたいなと思います。

## おまけ
MQ3をもっていなかったために、秋葉原に購入しに行きました。
購入した際のツイートがこちらです。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">アルコールセンサーを購入しました！<br>(ピン全然抜けない…)<a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://t.co/52iCHFXO2y">pic.twitter.com/52iCHFXO2y</a></p>&mdash; あべれん (@rencoln1229) <a href="https://twitter.com/rencoln1229/status/1581522047469248513?ref_src=twsrc%5Etfw">October 16, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

これもアルコールセンサーであることは間違いないのですが、はんだ付けを行うことが前提の購入だったみたいで、はんだ付けが身近ではない私ではこのパーツたちを使ってあげることができませんでした…。(パーツ買えばなんとかなると思っていた私のミスです。)
obnizに初めて触る方は公式サイトから同じものを購入するのがおすすめです！(今更)
**[obniz Parts Liblaly](https://obniz.com/ja/sdk/parts?q=)**