obniz「今から帰るね！」とＬＩＮＥでメッセージ送ると、奥さんの好きな曲が流れ、LEDランプで到着時間を色で教えてくれる仕組み！

##obniz<font color="Red">「今から帰るね！」<font color="　">とＬＩＮＥでメッセージ送ると、奥さんの好きな曲が流れ、LEDランプで自宅の到着時間を教えてくれる仕組み!　
仕事が終わって携帯を見ると、いつも奥さんから<font color="BLUE">「何時に帰ってくる？」「何時の電車に乗る？」<font color="　">といったLINEメッセージが来ている。これが気になる理由は、夕食の準備やお風呂を沸かす準備があるからだ！
<font color="Red">「今から帰るね！」<font color="　">とLINEメッセージを送ると自宅のobnizに連携させたスピーカーから、奥さんの好きな音楽が流れ、時間の経過とともに。LEDランプの色が変化する仕組みを制作したいと思いました。
(例)自宅到着1時間前:<font color="Red">赤色ランプ　<font color="　">30分前:<font color="DarkKhaki">黄色ランプ　<font color="　">10分前:<font color="blue">青色など　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/189c8411-48c4-2fc0-803f-9b75dfc7656e.png)

##作成した仕組み<font color="Red">(未完成)
Visual Studio Codeを使い、LINEBot×obniz(スピーカーとLEDを連携させた仕組み)制作
まだ、制作途中段階で、好きな音楽も制作出来ていない状況です。
[音階周波数](https://www.tomari.org/main/java/oto.html)で制作したいと思っております)

##開発環境
・[LINEBot公式アカウント解説](https://zenn.dev/protoout/articles/16-line-bot-setup)
・[Visual Studio Code基本操作](https://zenn.dev/protoout/articles/19-vscode-handson)
・[LINEBot参考ページ](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)
・[obniz公式ドキュメント（起動とWi-Fi設定）](https://obniz.com/ja/doc/reference/board-1y/quick-start/)
・[obniz公式ドキュメント（Speaker）](https://obniz.io/ja/sdk/parts/Speaker/README.md)

##準備
機材を準備
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/91b496a2-611f-e904-fb3b-d9c4c8a41a71.png)
・LEDは、obniz0~5番繋ぐ。
・スピーカーを10番～11番に繋ぐ。
・Visual Studio Codeで、LINEBotとobnizを連携させる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/8c44106f-38c8-b32f-a7e4-11d837bcc2ed.png)
・LINEBot準備
　Botアカウントの準備は、前回と同様に、[こちらの記事](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/d929885c-311a-83ef-32f5-3419b7b7dd2f.png)


##共通テンプレート
テンプレートをもとに作成しました！
<details><summary>サンプルコード　<font color="Red">**(クリックで表示)**</font></summary><div><br><br>

```js
'use strict';

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

// パッケージを使用します
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: '作成したBotのチャネルシークレット',
    channelAccessToken: '作成したBotのチャネルアクセストークン'
};

// ########## ▼▼▼ サンプル関数 ▼▼▼ ##########
（この行をサンプル関数丸ごと全部と置き換えてね）
// ########## ▲▲▲ サンプル関数 ▲▲▲ ##########

// ########################################
//  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サーバーを実行中です…`);

```
</div></details>
##Visual Studio Code
　(LEDランプとスピーカー連携)

<details><summary>ソースコード　<font color="Red">**(クリックで表示)**</font></summary><div><br><br>

```
const Obniz = require('obniz');
const { exit } = require('process');
const obniz = new Obniz('obniz_ID'); // Obniz_IDに自分のIDを入れます。今回は、消してます。

// 任意の秒数待つことができる関数
// 参考: https://qiita.com/suin/items/99aa8641d06b5f819656
const sleep = (msec) => new Promise(res => setTimeout(res, msec));

// obnizが接続済み
obniz.onconnect = async function () {
    var led = obniz.wired("LED", {anode:0, cathode:1});
    led.blink(); // 100msec
    var led = obniz.wired("LED", {anode:2, cathode:3});
led.blink(); // 200msec
var led = obniz.wired("LED", {anode:4, cathode:5});
led.on();

    // スピーカーを利用
    const speaker = obniz.wired('Speaker', { signal: 10, gnd: 11 });

    // ﾎﾟｯ↓
    speaker.play(500); await sleep(300); speaker.stop(); await sleep(700);
    // ﾎﾟｯ↓
    speaker.play(500); await sleep(300); speaker.stop(); await sleep(700);
    // ﾎﾟｯ↓
    speaker.play(500); await sleep(300); speaker.stop(); await sleep(700);
    // ﾎﾟ~~~ﾝ↑
    speaker.play(1000); await sleep(1000); speaker.stop();
    // Ctrl+C を打たなくても自動で終了します
    exit();
    }
```
</div></details>
##現在の状況
<details><summary>ソースコード　<font color="Red">**(クリックで表示)**</font></summary><div><br><br>

```
const Obniz = require('obniz');
const { exit } = require('process');
const obniz = new Obniz('obniz_ID'); // Obniz_IDに自分のIDを入れます

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

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

const app = 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));
});

const client = new line.Client(config);

// obniz接続
obniz.onconnect = async function () {
  obniz.display.clear();
  obniz.display.print("obniz meets LINE Bot!");
}

function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  let mes = ''
  if(event.message.text === '帰るね！'){
    mes = 'すこしまってね';  //メッセージだけ先に処理
    getAskObnizSpeaker(event.source.userId);  //スクレイピング処理が終わったらプッシュメッセージ
  }else{
    mes = event.message.text;
  }

  return client.replyMessage(event.replyToken, {
    type: 'text',
    text: mes
  });
}
const getAskObnizSpeaker = async (userId) => {
 // スピーカーを呼び出す
 const speaker = obniz.wired("Speaker", {signal:0, gnd:1});
 console.log("Speaker")
 await client.pushMessage(userId, {
  type: 'text',
  text: "了解！気を付けて！",
});

// 任意の秒数待つことができる関数
// 参考: https://qiita.com/suin/items/99aa8641d06b5f819656
const sleep = (msec) => new Promise(res => setTimeout(res, msec));

// obnizが接続済み
obniz.onconnect = async function () {
    var led = obniz.wired("LED", {anode:0, cathode:1});
    led.blink(); // 100msec
    var led = obniz.wired("LED", {anode:2, cathode:3});
led.blink(); // 200msec
var led = obniz.wired("LED", {anode:4, cathode:5});
led.on();

    // スピーカーを利用
    const speaker = obniz.wired('Speaker', { signal: 10, gnd: 11 });

    // ﾎﾟｯ↓
    speaker.play(500); await sleep(300); speaker.stop(); await sleep(700);
    // ﾎﾟｯ↓
    speaker.play(500); await sleep(300); speaker.stop(); await sleep(700);
    // ﾎﾟｯ↓
    speaker.play(500); await sleep(300); speaker.stop(); await sleep(700);
    // ﾎﾟ~~~ﾝ↑
    speaker.play(1000); await sleep(1000); speaker.stop();
    // Ctrl+C を打たなくても自動で終了します
    exit();
}
```
</div></details>

##稼働状況
https://twitter.com/EgashiraYosuke/status/1450791166673178625

##詰まっているところ
・LINE通知を検知し、LEDランプと音を連携させるところ。<font color="Red">(うまく連携出来ていない)
<font color="　">・自宅到着1時間前:<font color="Red">赤色ランプ　<font color="　">30分前:<font color="DarkKhaki">黄色ランプ　<font color="　">10分前:<font color="blue">青色など
　<font color="　">フルカラーLEDでも良いかと考えております。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/27071472-f605-7a2a-ab94-dc0ade10e558.png)

##フィードバック
奥さんからは、「曲を毎回変えて欲しい」「LINEを送付したら、乗換案内で自動検索し、何時着が自動通知してくれる」「車の場合は、エンジンをかけた瞬間、計算してくれ通知してくれるなど」GPSみたいと笑ってました。社内からは、「outlookとIoT連携した施策」、「全く別物だが、温度センサーを使い、冷凍・冷蔵温度異常がでた際に、社員スマホ、LINEに通知がくるシステムがあると便利。夏場温度異常が多く、緊急対応が多いため」という声がありました。

##今後チャレンジしたいこと
今後、[赤外線距離センサー](https://obniz.com/ja/sdk/parts/GP2Y0A21YK0F/README.md)赤外線距離センサーを活用し、自宅のポストに投函されたら、LINEの通知が来るようなシステムも制作していきたい思っております。
奥さんも喜んでくれると思うので、汗
これも奥さん、友達にフィードバックもらったところ、「毎回通知される仕組みでなく、せめて1日1回にして欲しい」
「一人暮らしで毎回見るの面倒だから、一定の量を超えたら通知して欲しい」という声がありましたので、次回制作していく中で、この意見を取り入れながら進めていきたいと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793863/4a5dab85-246b-ac39-e36c-19def034f687.png)

##今後取り組みたい課題
https://note.com/dsvvpxgc/n/ne90690aa950b

https://note.com/dsvvpxgc/n/nd9a8ca33e2e1

https://note.com/dsvvpxgc/n/nc78e8f8b5f11

https://note.com/dsvvpxgc/n/n88616f7f9c4f