お猫様に振り向いてもらうピヨピヨマシンを作った〜

### はじめに
こんばんわ！[IoTLT](https://iotlt.connpass.com/)アドベントカレンダー２日目です！！！

ねこIoTLT主催の3yakaと申します、フワッとしたフロントエンジニアです。
猫のために頑張って仕事をして猫のために。。。という猫中心の生活をしています。
猫との生活を充実させるためにねこIoTを楽しんでます〜

### クリスマスプレゼント的なお猫様に振り向いてもらうピヨピヨマシンを作った
おネコ様と暮らしていると、おそらくみなさんがやったことがあるであろう行為
「アレクサ！　鳥の鳴き声を教えて」みたいな、鳥の鳴き声を流すアレ。
若いネコさんは鳥のピヨピヨに反応して、興奮気味に鳥を探してくれます。（窓際にリアルに鳥さんが来るときと同じ反応をしてくれます）
しかし、「アレクサ！　〇〇・・・」的なことを言ってから鳥さんが鳴き始めると賢いお猫様はそのうちに相手にしてくれなくなります。

<b>いかに、人間がやっていないかのようにピヨピヨ言わせてお猫様を喜ばすかが重要になってきます。</b>

### やりたいこと
1. ピヨピヨマシーンと離れたところでスイッチを入れたい　→ 遠隔操作
2. 人間が近くでやるときは、人間の動作の直後ではなくてちょっとしてから鳴いて欲しい（自然を装いたい） →　Queueを使えば良い？
3. 外出時に猫カメラに映らない猫を呼び寄せたい →　カメラの死角から出てきて欲しい
4. アプリを増やしたくない →　LINEBotだー

### 概要
LINEBotに「ピヨピヨ」と入れたら、
Azure Queue storageに登録して
数十秒後にラズパイから鳥の鳴き声を出す

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">お猫様を喜ばせるピヨピヨマシーンを作ったんだけど、実験しすぎてあんまり反応してくれなくなった。。。<br>お猫様賢い。。。 <a href="https://t.co/NK9W3iZBrr">pic.twitter.com/NK9W3iZBrr</a></p>&mdash; 3yaka (@3yaka4) <a href="https://twitter.com/3yaka4/status/1333783815521636352?ref_src=twsrc%5Etfw">December 1, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


### LINEBotを作る
LINEBotはこちらの記事を参考に
[LINEBotからRaspberryPiで写真を撮ってLINEにおくる！ \- Qiita](https://qiita.com/3yaka4/items/ddeaaa746976327f236e#%E5%AE%8C%E6%88%90%E3%81%97%E3%81%9F)
こちらを追加

```node.js
    if (event.message.text.match("ピヨピヨ")) {
      piyo = await bird(event.source.userId);
      await client.replyMessage(event.replyToken, {
        type: "text",
        text: "鳥さん待機！",
      });
    }


const bird = async (userId) => {
  const {
    QueueClient
  } = require("@azure/storage-queue");
  
　let torisan = ownerName;

  async function main() {
    const queueName = torisan;
    console.log("\nCreating queue...");
    console.log("\t", queueName);

    const queueClient = new QueueClient(connectionString, queueName);

    // Create the queue
    const createQueueResponse = await queueClient.create();
    console.log("Queue created, requestId:", createQueueResponse.requestId);
    const sendMessageResponse = await queueClient.sendMessage(torisan);

    console.log("Messages added, requestId:", sendMessageResponse.requestId);

    // Get messages from the queue
    const receivedMessagesResponse = await queueClient.receiveMessages({
      numberOfMessages: 5,
    });

    console.log(
      "Messages received, requestId:",
      receivedMessagesResponse.requestId
    );
  }

  main()
    .then(() => console.log("\nDone"))
    .catch((ex) => console.log(ex.message));
};

```
### RaspberryPiの準備
こちらから好きな鳥の鳴き声をもらってきます
[自然・動物\[1\]｜効果音ラボ](https://soundeffect-lab.info/sound/animal/)
私はスズメの鳴き声にしました

ラズパイの構成はこんな感じ
node.jsは最新で挑んだ！

```
/home/torisan
　　 　｜- tori
　     　 　｜ーnode.modules
     　 　　｜ーpackage.json
     　 　　｜ーraspi_tori.js
     　 　　｜ーaudiofile
     　 　    　｜ー suzume.mp3
```
使用機材は　<b>イヤホンマイク</b>
スピーカーを設置したらにゃんこに怪しまれてしまったので、ラズパイからイヤホンの線を伸ばすとまぁまぁ距離を取れるので、引っ張ってイヤホン部分は隠しましょう

```javascript:raspi_tori.js 
"use strict";
const player = require("play-sound")();
// Azureとの連携用モジュール
const azure = require("azure-storage");

// Azure上のBLOBストレージとの接続用サービスオブジェクト
// 引数にBLOBストレージのConnectionStringを設定
var blobSvc = azure.createBlobService("***");

// Azure Storage の接続文字列を環境変数から取得
const connectionString = process.env.AZURE_STORAGE_CONNECTION_STRING;
const { QueueClient } = require("@azure/storage-queue");

//Quereにかきこんでおとをだす
const bird = "suzume";
async function main() {
  const AZURE_STORAGE_CONNECTION_STRING =
    process.env.AZURE_STORAGE_CONNECTION_STRING;

  const queueName = bird;
  console.log("\t", queueName);

  // Instantiate a QueueClient which will be used to create and manipulate a queue
  const queueClient = new QueueClient(
    AZURE_STORAGE_CONNECTION_STRING,
    queueName
  );

  // Get messages from the queue
  const receivedMessagesResponse = await queueClient.receiveMessages({
    numberOfMessages: 5,
  });

  if (receivedMessagesResponse.receivedMessageItems.length > 0) {
    console.log("とりがなきます");
    player.play("/home/pi/handson/audiofile/suzume.mp3", (err) => {
      if (err) throw err;
    });

    let receivedMessage = receivedMessagesResponse.receivedMessageItems[0];

    // 'Process' the message
    console.log("\tProcessing:", receivedMessage.messageText);

    // Delete the message
    const deleteMessageResponse = await queueClient.deleteMessage(
      receivedMessage.messageId,
      receivedMessage.popReceipt,
      receivedMessage.messageText
    );
    console.log(
      "\tMessage deleted, requestId:",
      deleteMessageResponse.requestId
    );
  }
}

main()
  .then(() => console.log("\nDone"))
  .catch((ex) => console.log(ex.message));

```

### おわりに

Twitterにあげた通り、実験をしすぎて相手にされなくなりました。
スズメの鳴き声を違う音声ファイルにしたらきっと探してくれるはず。。。

Queueの記事は少なくて辛かったですが公式のドキュメントが完璧だったので読み解けてないけど動いてるからよし。


### 参考
[クイック スタート:Azure Queue storage ライブラリ v12 \- JavaScript \| Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/storage/queues/storage-quickstart-queues-nodejs)