朝の天気を教えて！EC2で毎朝天気をLINEに自動通知！

## 天気を確認せず外に出たら雨でした

私は毎朝天気を確認せず家を出るのですが、雨が降っていたときは一度部屋まで傘を取りに戻ります。これが本当に面倒なんです。

今回はそれを解決するため、EC2やDockerをつかって毎朝天気をLINEに自動通知するシステムを作成しました。通知は画像のように来ます。

![IMG_3723.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682615/1c31442c-5682-4627-ac1a-1e9e4a539764.jpeg)


## OpenWeather API
天気情報は、無料でAPIを提供しているOpenWeatherMapからデータを取得しました。
アカウントを作成すると、API Keyを取得できます。

https://openweathermap.org/

## LINEへの通知
今回 LINE Notify を用いましたが、2025年3月31日にサービスを終了だそうです。
Messaging APIは残っているようなので、今後LINE通知するものを作成するときはこちらを使いましょう。

https://notify-bot.line.me/ja/

## 実装
### EC2 インスタンスの起動
特に問題ないと思いますが、流れとしては以下のとおりです。
1. 「インスタンスを起動」ボタンをクリック
2. OSの選択 → 今回は「Amazon Linux 2023」を選択しました。
3. インスタンスタイプ → 「t2.micro」(無料枠内)を選択
4. ストレージの設定（デフォルトでOK）
5. セキュリティグループの設定 → 22番ポート（SSH）を開放（自分のIPのみに制限）
6. SSH キーペアを作成してダウンロード
7. インスタンスを起動

### EC2にSSH接続
ローカルPCから SSH で接続します。

```
ssh -i your-key.pem ec2-user@your-ec2-public-ip
```

このとき、うまく接続できないときがあります。
こちらのサイトでIPアドレスを確認するとインバウンドのルールに記載されているものと違うときがあり、それを変更するとうまくいくときがあります。

https://www.cman.jp/network/support/go_access.cgi


### EC2にDockerをインストール

```
sudo yum update -y
sudo yum install docker -y
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker ec2-user
```

ログアウト、再ログインしてDockerの権限を適用

```
exit
ssh -i your-key.pem ec2-user@your-ec2-public-ip
```

Dockerが正しくインストールされているか確認
```
docker --version
```

### Docker、Pythonの準備
#### プロジェクトディレクトリの作成
```
mkdir weather_forecast
cd weather_forecast
```

#### Dockerfileを作成
```
nano Dockerfile
```
以下を記述
```
FROM python:3.12
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "weather_forecast.py"]
```

#### requirements.txtを作成
```
nano requirements.txt
```
以下を記述
```
requests
schedule
python-dotenv
```

#### weather_forecast.pyを作成
```
nano weather_forecast.py
```

以下を記述
```python
import requests
import os
import schedule
import time
from dotenv import load_dotenv  # .envファイルを読み込む

# 環境変数を読み込む
load_dotenv()

API_KEY = os.getenv("API_KEY")
CITY = os.getenv("CITY", "Tokyo")
LINE_NOTIFY_TOKEN = os.getenv("LINE_NOTIFY_TOKEN")

# APIキーのチェック
if not API_KEY:
    raise ValueError("API_KEY が設定されていません。環境変数を確認してください。")

# LINE Notify トークンのチェック
if not LINE_NOTIFY_TOKEN:
    raise ValueError("LINE_NOTIFY_TOKEN が設定されていません。環境変数を確認してください。")

# OpenWeather API のURL
URL = f"https://api.openweathermap.org/data/2.5/weather?q={CITY}&appid={API_KEY}&units=metric&lang=ja"

def get_weather():
    """ 天気情報を取得し、LINE に通知する """
    response = requests.get(URL)
    
    if response.status_code != 200:
        print(f"エラー: {response.status_code}, {response.text}")
        return
    
    data = response.json()
    weather = data['weather'][0]['description']
    temp = data['main']['temp']
    message = f"{CITY} の天気: {weather}, 温度: {temp}℃"
    
    print("取得した message:", message)
    
    # 取得した天気情報を LINE に通知
    send_line_notify(message)

def send_line_notify(message):
    """ LINE Notify を使って通知を送信 """
    url = "https://notify-api.line.me/api/notify"
    headers = {"Authorization": f"Bearer {LINE_NOTIFY_TOKEN}"}
    data = {"message": message}

    response = requests.post(url, headers=headers, data=data)
    
    if response.status_code == 200:
        print("LINE 通知送信成功")
    else:
        print(f"LINE 通知エラー: {response.status_code}, {response.text}")

# スクリプト実行時に即時天気情報取得＆通知
get_weather()

# スケジュール実行を設定 (日本時間で毎日7時に実行)
schedule.every().day.at("22:00").do(get_weather)

# スケジュールをループ実行
while True:
    schedule.run_pending()
    time.sleep(60)
```

## まとめ
一度稼働し始めれば、何も触らなくてよいのは便利だなと思いました。
また、設定時間について、日本時間ではないので22:00とすると、プラス9時間されて、7:00に通知されます。

ちなみにGitHubと連携して、コードを更新するときは、ローカルPCでコードを変更し、GitHubにプッシュした後、EC2で以下を実行すると最新コードが適用されます。
```
cd ~/weather_forecast
git pull origin main
docker-compose up --build -d
```