【JOJO風通知アプリつくってみた】湿温の奇妙な点検！～室内潮流は乱れない～

この記事は[身の回りの困りごとを楽しく解決！ by Works Human Intelligence Advent Calendar 2022](https://qiita.com/advent-calendar/2022/works-hi-1)の参加記事です。

## 超低温は氷の世界。さむい。

<b>最近朝、寒くて起きられない</b>。
そう思っている人は少なくないはず。

エアコンを付けたいけど、電気代やCO2の排出が気になって中々つけられない。
というかうちは<b>つけてはいるんだが、全然あったかくならないし動作しているか眉唾</b>だった。

## なに？うちの季節家電がおもちゃの様な動きで動かない？

ーそれは無理やり稼働させようとするからだよ。 

うちの10年物のおんぼろエアコンが「自動運転」したところで
<b>寒すぎたり暑すぎたり、適切に機能するわけがなかった。</b>

そして、リモコンの表示温度だって常に眉唾だ。
だから思いついた。<b>アテにならないなら、測りなおせばいいじゃあないか、と。</b>

```Jorge.Joestar
　　　　　　　､--‐冖'⌒￣￣`ｰ-､
　　　　 ／⌒`　　　　　　　三ミヽｰ-ﾍ, 
　　　__,{　;;,, 　　 　　 ミミ　　　ｉ　´Z,
　　 ゝ　　　''〃//,, 　,,.ミﾐ､_ノリ}j;　f彡
　　_)　　　   〃///,　,;彡'rffｯ､ｨ彡'ﾉ从iﾉ彡
　　>';;,, 　  ノ丿川j!川｜;　 :.`7ﾗ公 '>了
　_く彡川fﾞノ'ノﾉ_ノノﾉイシﾉ｜ ｜:　'〈八ﾐ､､;.)
　 ヽ.:.::.;=､彡／‐-ニ_＜、{_,ﾉ -一ヾ`~;.;.;）
　 く .::::.:!ﾊ.イぇ'无ﾃ,`ヽ｝}ィt于  |ィ"
　　 ):.::::|.Y }!　 ｀二´/' ;　|丶ﾆ　 ﾉﾉ 　　　逆に考えるんだ
　 　 ） :.: ﾄ､リ:!ヾ:、　丶　;　|　ﾞ　ｲ:}
　　 ｛ .:.:ｌ｛: : }　 　,.__(__,}　　/ﾉ 　　「 自分で管理しなくてもいいさ 」
　　　 ヽ !　　`'ﾞ! 　 　,.,,.`三'ﾞ､,_ /´
　 　 ,/´{　　ﾐ　l　　　　/ﾞ,:-…-…､ ）| 　　　　　　と　考えるんだ
　　,r{ 　 ＼ ﾐ 　＼　　 `'　'≡≡'　" ﾉ
__ノ 　ヽ 　　＼　 ヽ＼　　　　彡 　,ｲ_　
　　 　 　＼ 　　＼ ヽ 丶. 　　　　ノ!|ヽ｀ヽ、
　　 　 　 　 ＼ 　　＼ヽ ｀……´/ |ｌ　ト､　｀'ｰ-､__
　 　 　 　 　 　 ＼　　｀'ｰ-､　　/／　/:.:.}　 　　 　 ｀'ｰ､_
　　　　　　　 　 ｀､＼　　　／⌒ヽ　 /!:.:.|
　　　　　　　　　　｀､ ＼ /ヽLｆ___ハ/　　{
　　　　　　　　　　　　　 ′ /　! ヽ
```


という事で今回、自動で気温・室温の取得・通知を送ってくれるシステムを作ってみました。<b>ジョジョ風に。</b>

### ・用意したもの

![20221230_154337-800x448.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/c8228bbf-a0b8-9f69-1c0b-8ffc52985c35.jpeg)
 - [M5StickC](https://www.switch-science.com/products/6350)
家に転がってるRaspberry Pi Zero Wと迷ったが、最近転売されてて高いのとそんなに性能いらなくねということでお気に入りESP32系マイコンのM5StickCをチョイス。より小型ならAtomが良いのだが、画面ある方がデバッグしやすいのでこちらに。(<b>※現在は[M5StickCplus](https://www.switch-science.com/products/6470)しか販売されていません。</b>が、同じ.hファイルを変えるだけで<b>同様に動作</b>します)

 - <b>[M5Stack用温湿度気圧センサユニット Ver.3（ENV Ⅲ）](https://www.switch-science.com/products/7254)</b>
M5StickC系専用である[HATシリーズのEnvHatⅢ](https://www.switch-science.com/products/7367)で最初に試したんですが、本体の発熱で1,2℃誤差を生じることが判明しこちらに変更。その時の試行錯誤記事は<b>[こちら](https://manumaruscript.com/m5stickcplus-env-hat-error/)(※外部ブログへ飛びます)</b>

 - <b>TypeCケーブル（M5StickC給電用）</b>

 - <b>[LINE Notify](https://notify-bot.line.me/ja/)(LINEAPIアカウント)</b>

 - <b>燃え尽きるほどヒートな実装精神(やる気)</b>

## できたもの

### (最新版)

<b>（2023/01/05追記）バージョンアップデート実施しました！</b><br>同湿度・同温度での定期観測時に同じ台詞が飛ばないよう、バリエーションを追加しました。
また、それに伴い台詞と低温多湿、乾燥への分岐方法も若干微調整を加えています。
（低温状態を22度以下、超低温状態を19度以下に細分化、絵文字による寒さの段階表示など）

全台詞に絵文字を盛り込み、単調な見た目からカラフルな感じに変えてみました。
鳴き声もベ〇ビィ・フェイス→タ〇クact1になってます。かわいい。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【ジョジョの奇妙な室温計bot】<br>v1.01Update!<br><br>(適温・高温・低温)時<br>(適湿・多湿・乾燥)時で<br>各状態にマッチしたセリフが3種類の中からランダムに届くようになりました。<br><br>＋一言ではなく、<br>名シーンも飛ぶようになってます。<br><br>これで毎日の気温管理楽しくなる😊<a href="https://twitter.com/hashtag/JOJO?src=hash&amp;ref_src=twsrc%5Etfw">#JOJO</a> <a href="https://twitter.com/hashtag/%E3%82%B8%E3%83%A7%E3%82%B8%E3%83%A7%E5%A5%BD%E3%81%8D%E3%81%95%E3%82%93%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#ジョジョ好きさんと繋がりたい</a> <a href="https://t.co/neJlQgdoBx">pic.twitter.com/neJlQgdoBx</a></p>&mdash; まる＠NeuroArt (@hevel_epsilon) <a href="https://twitter.com/hevel_epsilon/status/1610917446814429185?ref_src=twsrc%5Etfw">January 5, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


### (制作当初)
とぅーるるるる、るるるん！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ジョジョ風に部屋の室温・湿度を観測してくれるアプリを作りました。<br><br>毎日ランダムで名言も届くよ。<a href="https://twitter.com/hashtag/JOJO?src=hash&amp;ref_src=twsrc%5Etfw">#JOJO</a> <a href="https://twitter.com/hashtag/%E3%82%B8%E3%83%A7%E3%82%B8%E3%83%A7%E5%A5%BD%E3%81%8D%E3%81%AA%E4%BA%BA%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#ジョジョ好きな人と繋がりたい</a> <a href="https://t.co/ao4RVOGUqt">pic.twitter.com/ao4RVOGUqt</a></p>&mdash; まる＠NeuroArt (@hevel_epsilon) <a href="https://twitter.com/hevel_epsilon/status/1608431717026791425?ref_src=twsrc%5Etfw">December 29, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


部屋の気温・湿度を検知し、外出中でも好きなタイミングで通知してくれます。
でも、「<b>ただ数値を定点観測するだけだとすぐ出来てつまらないし、じきに飽きて通知も見なくなる</b>」と思った為、<b>黄金の精神</b>をインストールすることにしました。（漆黒の意思についても動作確認済です）

そこで以下、震えるぞハート！な<b>こだわりのオマケ機能</b>を紹介していきます。

## 黄金の精神のインストール

### ・襲い来る暗殺チーム機能
![Sofwet.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/31ffbfb6-9cc9-793d-83ba-e6bf616ea714.jpeg)
<b>適温/適湿以下・以上となった際に、敵の暗殺チームがやってきて教えてくれます。</b>

プ〇シュート兄貴が来た時は肌の状態が著しく悪化しますので、忘れずに氷を当てて体温を保ちましょう。
冷えすぎるとギ〇ッチョがブチ切れに来るので気をつけてください。

今は6時間ごとの経過取得にしていますが、勿論<b>特定の時刻や特定の気温になったタイミング</b>での通知も可能です。
これでエアコンによる室温変化を時系列で正確にロガーできるようになりました。

一応、気圧(hPa)も測れるのでジャンピング・ジャック・フラッシュが攻撃を仕掛けてきたときも無事対応出来ます。

### ・隠者の紫機能

また、低確率でキャラクターが出現します。
![RoH.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/5f91ef78-5f6a-d8db-13e6-31ae895ea945.jpeg)

今はまだ花〇院と露〇しか作っていないので、ボスを呼び出せるようにしたいなと思っています

![EP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/d3c65ed1-de47-659c-12da-f957db0c7050.jpeg)![ディアボロ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/30adde3e-e5a4-c782-bdc5-4ee8d365b764.png)

この辺り進捗あればTwitterの方で呟き予定です。

### ・記録ヲ全テ、リプレイシマス機能
![MEIGEN.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/bac35a00-8618-9a59-f848-bf0732ea44b2.jpeg)
61個(素数)の中から毎回ランダムで一つ、名セリフが送られてきます。

<b>興奮する...だがこういう時は、浮かれたヤツから死んでいく。。(後述のバッファオーバーフロー)</b>
調子に乗って入れすぎると配列のメモリオーバーして再起動繰り返すようになったので、現在は61個で留めています( ﾟДﾟ)

![143873.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/b40bde1b-8959-0ec2-5331-55f5885c9c4b.jpeg)

日常の何気ないタイミングでこんな通知が送られてくるので、スマートウォッチとかで見るとフフッ、てなることができます😊

## 恥知らずのエピローグフェイズ

![145254.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/74d2d9e4-6dce-e838-3230-7c04b0f6759b.jpeg)


### （開発小話）
元々、エアコンを痩せ我慢して使わずに「つけてるから大丈夫ｘ２」と~~まるでトーキング・ヘッドにとりつかれたように~~家族にウソをつく<b>ばーちゃんの死活監視</b>用に作成していたのですが、室温湿度を表示するだけなんて<b>｢退屈ッ！ふざけずにはいられないッ！！｣</b>という事で気が付いたらつくってました。~~<b>心の中で思ったならッ！その時既に行動は(ry</b>~~

<b>ばーちゃんの命も守る。納期(自己目標)も守る。「両方」やらなくっちゃあならないってのが「エンジニア」のつらいところだな..</b>

一応気圧や電源電圧もとれるようにしていたんですが、殆ど変わることがないので今はガオンして消し飛ばしています。

![145251.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/74a01886-250d-72c4-2685-a2501451c928.jpeg)

その他、今年の夏ぐらいに、ゴミ出しをよくし忘れるので毎週夕方に通知をくれるアプリを自作していて、
そちらも退屈だったのでラテン語の格言が毎日ランダムで飛ぶように途中から改良(?)していました。~~<b>同居人にはいらないといわれました</b>~~

この時も少しだけふざけていましたが、<b>「もっと思いっきりふざけたほうが面白くなるんじゃね？？」</b>と舵を切ったのが今回の経緯になります。



## 開発で苦労したこと

元々Pythonをメインに書いていることが多く、C++はあまり書いたことがなかったので型変換やバッファサイズの計算に苦戦しました。
<b>これらの詳細はArduino,C/C＋＋系備忘録として1月1,8,15の朝7時にブログの方でも公開予定です。</b>(予約投稿済)
~~元々Qiitaがそういう場所だよね~~

### ・assertion "head != NULL" failed　エラー

ヒープメモリ領域を適切に確保しきれていなくて、名言を詰め込みすぎたところM5stickcplusが再起動を繰り返すように。

最初はバッファサイズとかはわからず、

```C++
"「フランスの「パリ」ってよォ...英語では「パリス PARIS」っていうんだが、みんなはフランス語どおり「パリ」って発音して呼ぶ。でも「ヴェネツィア」はみんな「ベニス」って英語で呼ぶんだよォ〜。「ベニスの商人」とか「ベニスに死す」とかよォー。なんで「ヴェネツィアに死す」ってタイトルじゃあねえーんだよォオオォオオオーッ」"

```

このセリフが一行で多すぎるのか、

```C++
"ただいま14.2℃です⛄"
```
とか環境依存文字や特殊記号、絵文字を入れてたのがまずかったのか
分からなかったりして、色々試しました。

最終的には、Serial.printでデバッグしつつ、M5.setup()でコケていることを知り最終的に配列への格納、ランダムで出力時のタイミングで死んでいたのでそこから配列サイズへの格納要素数を減らし、可変長文字列にすることで特定。

### ・NotifyのSend Error
Sleepを2，3秒挟んでもLINEへの通知送信に失敗することがありました。
結局、一回Nullで送信を挟むとその次が正常に動くことを知り送信の際にはsleepを挟みつつ二度送るようにしています。
（この辺り、詳しいドキュメント見つからなかったのでご存じの方ご教示頂けると嬉しいです！）

### ・char*文字列とsnprintf関数の合わせ技

![145257.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/4b0ae662-69bc-87eb-4dcc-bc9abab272f4.jpeg)

最初、LINE Notifyにて「温度・湿度通知」と「それに対するキャラクターのコメント」、「ランダム名言」の3発にわけていたのですが、6時間おきとはいえ3回も<b>LINEが来るのは中々にうるさかった</b>です。


```C++
sprintf(str_tmp, "【気温】: %2.1f ℃", tmp);
sprintf(str_hum, "【湿度】: %2.0f ％", hum);

const char* KAKUGEN[]={
  " <1..3..5..7..素数を数えて落ち着くんだ.. ",
  " <このジョルノ・ジョバァーナには夢がある！",
};
```

最初、CとC++、どっちの関数をArduinoだとメインに使われているのかよく分からず、
連結させやすいstd::stringを使ってもLINEnotifyでは型エラーとなってしまう為、string型の文字列に対してchar*の文字列を連結させるのに苦戦しました。

最終的にはstd::stringのメンバ関数であるc_str()を使い、char* 型のポインタを返す形で一つの文字列に結合させる形で送信に成功しました。

```C++
lmsg2 += str_tmp;
const char* l_msg2 = lmsg2.c_str();
Line_notify(l_msg2);
```

### ・定期実行のやりかた
ラズパイでいうcrontabやデーモンのように、M5Stackシリーズでもloop関数内でのSleep、ディープスリープモード、子ルーチンで動かすなど色々やり方があります。

```C++
  //子ルーチン
  //  第1引数はタイマ番号(0～3)、第2引数は分周比。M5Stackのペリフェラル周波数は80MHzなので80に設定し、1カウントを1MHzに
  timer = timerBegin(0, 80, true);
  //割り込み登録
  timerAttachInterrupt(timer, &onTimer, true);
  //6時間置きにサブプロセスにて定期実行
  timerAlarmWrite(timer, 21600000000, true);
```

今回は、AButtonを押した時も名言が欲しかったのでディープスリープモードは見送り、子ルーチンで動かすことにしました。
モバイルルーターなど、省電力下での利用の際はディープスリープモード・ディスプレイ輝度0の設定がオススメです。

```C++
  //ディープスリープモード
  //μsec単位で指定した引数で指定した時間スリープした後、マイコンがリセットされる
  esp_deep_sleep(60000000ULL); // 1 * 60 /6 /2 * 60 * 1000000 μs = 5minute
```

Hatを使って本体の近くで計測するなら、連続稼働により計測温度が上昇しがちになるので、ディープスリープモードにて温度を定期的に下げるのもアリかもしれません。

### ・AAの作成
![AA3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/faa021c8-d325-2ad9-8bbe-afe61f6005da.jpeg)　![AA2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/7105b9db-5f83-f5c0-7a6d-986ac3680677.jpeg)　![AA.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/17490243-6866-6e5c-e281-b7046083e572.jpeg)

そして最後に、みんな大好きAA(アスキーアート)の作成です。

5chのAAなどは、基本LINEの幅には対応してもらず文字崩れを起こしてしまうので、<b>VSCodeで編集</b>してLINE用に作りなおしました。<b>これに結構~~無駄に~~時間を割いた気がする</b>けど、<b>大切なのは『真実に向かおうとする意志』だと思っている</b>ので、達成感という意味ではディ・モールトベネ。

ただ、スマートフォンによっても表示できる横文字幅は変わるので、AAも画像化してSendするのが得策に感じました。~~オイ~~

<b>花〇院はアゴがズレた感じがなんか気に入ったので、このままにしています。</b>
決して手抜きとかではないです。🍒ξ´ิڡ´ิ )ﾚﾛﾚﾛﾚﾛﾚﾛﾚﾛﾚﾛﾚﾛﾚﾛﾚﾛﾚﾛﾚﾛﾚﾛﾚﾛ...

## 今後の改修予定

### ・キャラクター通知バリエーション、台詞変化機能の追加

<b>良く学習しているぞッ！機能</b>
現在、適温・適湿を定義して以上、以下をもとに1キャラクターのセリフが送られてくるようになっていて
まだワンパターンなのでこの後パターンを増やしていく予定。

<b>3回連続ギ〇ッチョが呼び出されると「なんでエアコンの温度をまだ変えねェ～～～んだよぉぉぉ～～～ッッッ！！」とかブチ切れ</b>られたり、気温・室温が<b>素数だった時にプ〇チ神父が来て14の言葉を一つずつ唱える</b>ようにしたい。

考えるだけで楽しい。🍒ξ´ิڡ´ิ )ﾚﾛﾚﾛﾚﾛ...

### ・エアコンの制御

定期観測の自動化までできたから、ホントはIoTで外出先とかから遠隔で操作＆自動制御も行いたい。
[SwitchbotAPI](https://github.com/OpenWonderLabs/SwitchBotAPI) や [M5Stack用赤外線送受信ユニット【M5STACK-IR-UNIT】](https://www.marutsu.co.jp/pc/i/1556080/)を使えばイケると思う。

Switchbotと組みあわせて、帰宅時間に冷えてたら先につけておく、など電力の最適化が出来たらもっと便利そう。

M5の赤外線リモコンはプロジェクターのOFFONとかはやってるけど、温度の上げ下げみたいなのはまだやってないので要調査だが、Rawデータをそのまま学習させて飛ばせば出来る気がしている。

### ・表現方法の拡張

[mobizt](https://github.com/mobizt)さんという方が以下、ESP系用のLINENotifyライブラリを自作してるみたい。神。

Github - mobizt/ESP-Line-Notify
[LINE Notify Arduino Library for ESP8266 and ESP32](https://github.com/mobizt/ESP-Line-Notify)

で、みてみるとどうやらLINEの[既定スタンプ](https://developers.line.biz/ja/docs/messaging-api/sticker-list/#sticker-definitions)なら送れるらしい。

![LINEstamp.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/7b03588d-0ee8-63cf-88ba-25c0672f75ec.jpeg)(引用：[LINE Developers](https://developers.line.biz/ja/))

外国圏のスタンプは日本だと買えなかったりして、アジア圏の友達とLINEする際に不満だったのだが
これを使えば英語や中国語、韓国語Verのものも送れるっぽい。
ので、これでスタンプを送れるようにしたり、画像送信するなどして、テキスト以外の表現も使ってもう少し遊び心マシマシにしたい。

<b>こうしてmalmal0v0は..
セリエA（アー）のスター選手に
あこがれるよりも・・・・・</b>

![自作AA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217271/7647f001-ca48-f56e-b54a-fb924825709c.png)

```

　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　〈￣ヽ 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　 　,､＿＿＿＿|　 |＿＿＿＿,､ 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　 〈　　＿＿＿＿＿＿＿＿＿　ヽ, 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　|　| 　　　　　　　　　|　| 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　ヽ'　 〈＾ー―――＾ 〉  |／ 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　,､二二二二二＿、 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　〈＿_　　＿　　＿＿〉 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　 |　|　|　| 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　/　/　 |　|　　　|＼ 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　＿＿ _/　/　　 |　|＿＿＿|ヽ 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　＼＿＿/　　　   ヽ＿＿＿＿＿） 

```

## 謝辞(参考サイト)
ありがとう..それしか言う言葉が見つからない。
 - [M5StickC ENV Hat III で気圧を測る ～ 高度計を作る](https://www.kunimiyasoft.com/m5stickc-env-hat3/)
 - [M5Stack ENV Hat, ENV Unit, ENV II Unitを比べてみた](https://lang-ship.com/blog/work/m5stack-env-test-u001/)
 - [ESP32 ( ESP-WROOM-32 , M5Stack )自分的 トラブルシューティング まとめ](https://www.mgo-tec.com/blog-entry-trouble-shooting-esp32-wroom.html/7)
 - [std::string::c str (C++入門)](https://kaworu.jpn.org/cpp/std::string::c_str)
 - [【C++】string型をcharに変換/コピーする方法【値 配列 ポインタ string to char】](https://marycore.jp/prog/cpp/convert-string-to-char/)
 - [error: cannot convert ‘std::__cxx11::string’ {aka ‘std::__cxx11::basic_string’} to ‘const char*’ line 23
](https://stackoverflow.com/questions/68965516/error-cannot-convert-std-cxx11string-aka-std-cxx11basic-stringch)
 - [Arduino 日本語リファレンス](http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=1418)
 - [C++ 文字列を結合するサンプル](https://itsakura.com/cpp-string-ketsugou#s4)
 - [C++ 文字列の連結と追加【std::string｜文字列結合と挿入処理】](https://marycore.jp/prog/cpp/concat-append-string/)