果物の甘さを最大限に感じつつ、かまいたちで笑い転げて1日を終えたい（obniz×LINEBot）

こんにちは～

みなさん果物はお好きですか？

私は1人暮らしを始めてもう10年くらいになっているのですが、
毎晩必ずと言っていいほど、果物を食べて寝ています。

**そんな毎晩のルーティーンである
果物タイムで果物の甘さを最大限に感じつつ、今日も楽しかったと思えるために
obnizと温度センサー、LINEBotを使って作ってみました！**


## どんな実装をしたのか

**①果物をより甘く感じるために温度センサーで食べごろ温度を測る**
果物はそれぞれ甘味を感じやすい温度があるらしいです！
なので果物を食べる前に温度センサーで温度を測り、
甘い果物を食べられるようにしました。

今回はすいか・桃・マンゴーの適温を知れるよう設定しました。


**②今日も楽しかったと思えるために芸人の力を借りる**
大好きな芸人「かまいたち」が温度判定結果を画像で返すように設定。
でも、かまいたちはしゃべらないと面白くない！！！！
「食べてええで」の判定をしてくれたら
かまいたちのYoutube動画をランダムに送ってくれてるよう設定しました。


## 完成したものはこちら
https://twitter.com/nghrhtm1/status/1553608672886272000


「もも食べていい？」とLINEで送信して適正温度だったら
LEDが緑に光り、かまいたちから「たべてええで！」と返信が来ます！
果物タイムを楽しむためのYouTube動画もランダムで送られてきます！


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/06b24ac9-a444-f18b-4031-243930b4f815.png" width="600" height="200">


まだ果物が冷えてなかったら・・・
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/8b3159dc-1976-0761-02d6-8af12fc08218.png" width="600" height="200">
山内くんのシュールな画像とLEDが赤色に光り、
まだ冷やした方がいいことを知らせてくれます。




そして冷やしすぎも厳禁です!!
冷やしすぎたら甘さを感じにくい果物もあるので気をつけないといけません。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/65ff4197-9e64-a9d0-6b59-39d0898c2f16.png" width="600" height="200">




## せっかくなので、温度の違う桃の食べ比べをしてみる！


今回食べ比べたのは山梨県産の桃2個入り

左側が2日間冷蔵庫の中で冷やした桃（20.5℃）
右側が2日間常温で管理して、甘味を感じやすいと言われる温度の桃（25.3℃）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/c2e50abe-c70f-59f9-14bd-8779b97b2da5.png" width="600" height="200">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/e3cb8be5-113b-3418-9c0a-883ffeb42ac2.png" width="600" height="200">



**ちなみに桃は、温度が上がるにつれて酸味が減り、甘味が減るそうです。**
 [参考ページ：あま〜い桃を食べるには、桃の温度が重要だった！？](https://aissy.co.jp/ajihakase/blog/archives/13896)



### いざ実食！！！！

**先に食べたのは冷蔵庫でキンキンに冷やした桃**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/ea6f6bad-491a-87aa-28f3-6fd69fa05ada.png" width="600" height="200">

うん！いつも通り！（私は毎日果物をキンキンに冷やしているから気にならない。）


**次に食べたのが常温で甘味を感じやすいといわれている温度の桃**

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/22569ab7-dfaf-58a3-388f-733eb11d2175.png" width="600" height="200">

**うん！先ほどの桃よりも甘い！**
もちろん全部あまーい！！という感じでは無いけど、
**先ほどよりも甘いと感じる回数が多いし、特に酸味が少ないのは私でもわかった！**

良い感じ！！！！

## これで果物タイムは理想に近づいた！！（感想）
実装は結構大変だったし、温度センサーが正常に反応しなかったり
ドタバタしたけど・・・

よりおいしく果物を食べれたから嬉しい！！
そしてより美味しくなった果物は一瞬でなくなる（笑）

かまいたちのYoutube動画は洗い物をするときのBGM化したけど
めんどくさい洗い物も楽しい時間になる！！
（笑い転げてはいない笑）

てことで終わります！
最後まで読んでいただきありがとうございました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/19cbd83e-628a-41a4-337e-81e5d40f39df.png" width="600" height="200">


## 作り方

<details><summary>実際に作成したコードはこちら</summary>

```js


​"use strict";

// obniz呼び出し
const Obniz = require("obniz");
const obniz = new Obniz("*********"); // Obniz_ID に自分のIDを入れます

const express = require("express");
const line = require("@line/bot-sdk");
const PORT = process.env.PORT || 5000;

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

const app = express();
// LINEクライアントに接続
const client = new line.Client(config);

// 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)
  );
});
async function handleEvent(event) {
  if (event.type !== "message" || event.message.type !== "text") {
    return Promise.resolve(null);
  }
  let video_url_list = [
    "https://www.youtube.com/watch?v=kkXgr5jb5xM",
    "https://www.youtube.com/watch?v=2SEWTr1mmIE",
    "https://www.youtube.com/watch?v=tUDroDs3pZ8",
  ];
  const message = event.message.text;
  const watermelon_text = "すいか食べていい？";
  const mango_text = "マンゴー食べていい？";
  const peach_text = "もも食べていい？";

  if (
    message === watermelon_text ||
    message === mango_text ||
    message === peach_text
  ) {
    let max_temp = 0;
    let min_temp = 0;
    if (message === watermelon_text) {
      max_temp = 15;
      min_temp = 10;
    } else if (message === mango_text) {
      max_temp = 15;
      min_temp = 10;
    } else if (message === peach_text) {
      max_temp = 30;
      min_temp = 20;
    }
    console.log("max_temp: " + max_temp + ", min_temp: " + min_temp);
    getAskObnizTempsens(
      event.source.userId,
      max_temp,
      min_temp,
      video_url_list
    ); //処理が終わったらプッシュメッセージ

    // 今日も1日お疲れさま
  } else if (message === "ごちそうさまでした！") {
    client.replyMessage(event.replyToken, {
      type: "image",
      originalContentUrl:
        "https://bespoke-blini-aa8f32.netlify.app/otukaresama.jpg",
      previewImageUrl:
        "https://bespoke-blini-aa8f32.netlify.app/otukaresama.jpg",
    });
  }
}
// obniz接続
obniz.onconnect = async function () {
  obniz.display.clear();
  obniz.display.print("obniz meets LINE Bot!");
};
const getAskObnizTempsens = async (
  userId,
  max_temp,
  min_temp,
  video_url_list
) => {
  // 温度センサの利用
  const tempsens = obniz.wired("LM60", { gnd: 0, output: 1, vcc: 2 });
  // RGB LEDを利用
  const rgbled = obniz.wired("WS2811", { gnd: 9, vcc: 10, din: 11 });

  // 同期で取得
  const temp = await tempsens.getWait();
  if (temp < max_temp && temp > min_temp) {
    // たべてええで！
    rgbled.rgb(0, 250, 0);
    await client.pushMessage(userId, {
      type: "image",
      originalContentUrl: "https://bespoke-blini-aa8f32.netlify.app/okj.jpg",
      previewImageUrl: "https://bespoke-blini-aa8f32.netlify.app/okj.jpg",
    });
    await client.pushMessage(userId, {
      type: "text",
      text: video_url_list[Math.floor(Math.random() * video_url_list.length)],
    });
  } else if (temp >= max_temp) {
    // もっと冷やして！の画像
    rgbled.rgb(250, 0, 0);
    await client.pushMessage(userId, {
      type: "image",
      originalContentUrl: "https://bespoke-blini-aa8f32.netlify.app/ng.jpg",
      previewImageUrl: "https://bespoke-blini-aa8f32.netlify.app/ng.jpg",
    });
  } else {
    // 冷やしすぎ！の画像
    rgbled.rgb(0, 191, 250);
    await client.pushMessage(userId, {
      type: "image",
      originalContentUrl: "https://bespoke-blini-aa8f32.netlify.app/ng2.jpg",
      previewImageUrl: "https://bespoke-blini-aa8f32.netlify.app/ng2.jpg",
    });
  }

  // ターミナル表示
  console.log("obniz temp:", temp);
  // obnizディスプレイ表示
  obniz.display.clear();
  obniz.display.print(temp + "C");
};
app.listen(PORT);
console.log(`ポート${PORT}番でExpressサーバーを実行中です…`);

```
</details>
​

**使用したもの**

*  [obniz](https://akizukidenshi.com/catalog/g/gM-14930/)
*  [高精度ＩＣ温度センサー](https://akizukidenshi.com/catalog/g/gI-02490/)
*  [フルカラーLED 8㎜](https://akizukidenshi.com/catalog/g/gI-08411/)
*  [Node.js](https://nodejs.org/ja/)
*  [Messaging API](https://nodejs.org/ja/)
* [Netlify](https://www.netlify.com/)

**画像のURL発行の仕方**
[スーパーの鮮魚売場でお魚くわえた３Dドラ猫を出現させたい](https://qiita.com/NagaharaHitomi/items/b8fe6844ca5933dd2cbc)
上記記事の3DモデルをNetlifyにアップロードする方法を参考にしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/5c96e46e-6e3a-3822-a91c-4f006fce67f8.png)
↑この赤枠部分をファイル名.jpgに変更してください。