アドベントカレンダー6日目

# 5つ目 持ち物提案アシスタント
 5つ目は、持ち物提案アシスタントです。

# きっかけ
　家を出る際に、その日の天候などにより持って行った方がいいものが出てきます。暑い日は、ハンカチだけでは足りないから汗拭きシートやハンディファン、雨の日は靴の中が濡れてしまうので替えの靴下やタオル、寒い日はホッカイロなどがあげられます。だが、傘やハンカチほど重要ではないため、ふとしたときに使いたいタイミングで手元になかったことがありました。これは悪い癖なのですが、部屋で思い出しても後で用意しようと後回しにしてしまうことがよくあります。小さいことゆえに、なかなか治らないため、困っていました。
　これを解消するために、その日の天候や気温に応じて、持っていくものをアシスタントしてくれるシステムを制作することにしました。

 # 実際に作ってみる
 　今回使用したのは、M5Core2、タッチセンサー、BUZZERセンサーです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924203/dff82e7a-b5bd-86ef-1aab-ec3ef7155810.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924203/975ebfa4-c228-2ab1-6ee3-181391600d67.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924203/6da201c0-9b4b-b745-abdf-9faeb815c514.png)


# プログラム
　Wi-Fiを利用し、OpenWeatherMapから情報を受け取って反映させています。アラームは自由に時間を変えることができ、自身の生活習慣に合わせて替えることも可能です。
　ディスプレイは、タッチセンサーに触れた後から10秒間表示し、また初期の暗い画面に戻るように設定しています。

~~~Arduino:assistant.ino
#include <M5Unified.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid = "WiFi_ssid";
const char* password = "WiFi_password";
const char* apiKey = "OpenWeatherMap_APIkey";
const char* city = "Hachinohe";
const char* apiUrl = "http://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric";

int buzzerPin = 25;    // BUZZERピン
int touchPin = 33;      // タッチセンサーのピン

// 推奨アイテム表示関数
String getRecommendedItems(const String& weather, float temp) {
  if (weather == "rain" && temp < 15.0) {
    return "傘とハンカチを持っていきましょう！";
  } else if (weather == "snow" && temp < 15.0) {
    return "ホッカイロと手袋を持っていきましょう！";
  } else if (temp >= 25.0) {
    return "タオルを持っていきましょう！";
  } else if (temp < 10.0) {
    return "ホッカイロを持っていきましょう！";
  }
  return "特に追加の持ち物はありません。";
}

void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);
  M5.Lcd.setTextFont(&fonts::efontJA_16);
  
  pinMode(buzzerPin, OUTPUT);  // BUZZERを出力モードに設定
  pinMode(touchPin, INPUT);    // タッチセンサーを入力モードに設定

  // WiFi接続
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }

  delay(2000);  // 接続後の待機
  M5.Lcd.clear();
}

void loop() {
  // 8時にアラームを鳴らす
  struct tm timeInfo;
  if (getLocalTime(&timeInfo) && timeInfo.tm_hour == 8 && timeInfo.tm_min == 0) {
    for (int i = 0; i < 5; i++) {  // 簡単なアラーム音を鳴らす
      digitalWrite(buzzerPin, HIGH);
      delay(500);
      digitalWrite(buzzerPin, LOW);
      delay(500);
    }
    delay(60000);  // 1分待機して再びアラームが鳴らないようにする
  }

  // タッチセンサーに触れたら情報を表示
  if (digitalRead(touchPin) == HIGH) {
    displayWeatherInfo();
    delay(10000);  // 情報表示後10秒間待機
    M5.Lcd.clear();  // 画面を暗くして待機状態に戻る
  }
  delay(100);  // センサーのチェック頻度
}

// 天気情報を取得して表示
void displayWeatherInfo() {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    char url[256];
    sprintf(url, apiUrl, city, apiKey);
    http.begin(url);

    int httpCode = http.GET();
    if (httpCode > 0) {
      String payload = http.getString();
      StaticJsonDocument<1024> doc;
      deserializeJson(doc, payload);

      const char* weather = doc["weather"][0]["main"];
      float temp = doc["main"]["temp"];
      
      String itemSuggestion = getRecommendedItems(weather, temp);

      M5.Lcd.clear();
      M5.Lcd.setCursor(10, 20);
      M5.Lcd.printf("天気: %s", weather);
      M5.Lcd.setCursor(10, 50);
      M5.Lcd.printf("気温: %.1f C", temp);
      M5.Lcd.setCursor(10, 80);
      M5.Lcd.printf("推奨: %s", itemSuggestion.c_str());
    } else {
      M5.Lcd.clear();
      M5.Lcd.setCursor(10, 20);
      M5.Lcd.println("天気情報の取得に失敗しました");
    }
    http.end();
  } else {
    M5.Lcd.clear();
    M5.Lcd.setCursor(10, 20);
    M5.Lcd.println("WiFiに接続できません");
  }
}
~~~

　今回も色々なサイトを参考にさせていただきました。

https://github.com/m5stack/M5Stack

https://github.com/arduino/reference-jp

https://chatgpt.com/

# 結果
　実際の起動画面です。天候と気温、推奨という項目では前項目の二つの情報から持って行った方が良いものが表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924203/f9973564-7e83-de31-efa2-4aedd60f3a05.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924203/a86d1fcd-b1c4-e17c-360a-b5e3f74f6b62.png)
　他の都市でも試し、設定したとおりに表示されました。

# 反省点
　タッチセンサーに一々触れなきゃいけないのが唯一の反省点かと思いました。最初は、PIRモーションセンサーにしていましたが、範囲が広すぎたためタッチセンサーに変更しました。もう少し検知範囲の狭いセンサーを使用することで改善できそうです。

# 感想
　実際使用すると、いつもは忘れるものも持っていこうという意識をすることができました、これで、当初の目的を達成できたと思います。