ガチで危機感持った方がいい。Pythonで位置情報取得し、コンビニに近づいたらアラートして散財を防ぐ。

# コンビニ控えて節約したい
私はコンビニによく行くのですが、ついつい1000円くらい使ってしまいます。
そのたびに、もったいない！と思うものの、辞められません。
そのため、コンビニから足を遠ざけ、節約したいと思っています。

# コンビニに近づくとアラートメール自動送信
iPhoneの位置情報を継続的に取得して、コンビニに近づくと、メールを自動送信するというものを作成しました。

↓ 青いマーカーが現在地で、赤い円の範囲に入るとメールが自動送信されます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682615/17dead41-5bb2-6bad-3cfc-bf8f5939cb60.png" width="600"> 

↓ 実際に自動で送信されるメールです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682615/8dd39a12-abf7-1c10-1d28-b72247b4b05a.jpeg" width="400"> 

# 環境
Jupyter Notebook 6.4.12
python 3.10.13

# 実装
## iCloudアカウント情報の取得とログイン
iCloudアカウントの情報を取得し、PyiCloudServiceを使用して、iCloudにログインする。これにより、デバイスの位置情報を取得できるAPIオブジェクトが生成されます。

下記スクリプトを実行すると、登録しているiOSデバイスの情報が表示されます。複数ある場合は、devices[0], devices[1], devices[2], ･･･の順で表示されます。

```python
from pyicloud import PyiCloudService

# iCloudアカウント情報
username = 'your_username'
password = 'your_password'

# iCloudにログイン
api = PyiCloudService(username, password)

def get_oauth():
    auth = api.devices
    return auth

if __name__ == '__main__':
    auth=get_oauth()
    print('\n')
    print(auth)
```

## 継続的な位置情報の取得
デバイスの位置情報を継続的に取得し、その座標が一定範囲内にあるかどうかを確認します。もし範囲内にあればメール送信へ移行し、プログラムを終了します。

convenience_storeについては、適宜座標を代入してください。
```python
from geopy.distance import geodesic
import time

# 検知する座標範囲内
convenience_store = (store_latitude, store_longitude) 
radius_threshold = 0.03  # 30m以内に入った場合に検知

# 位置情報を継続的に取得するループ
while True:
    try:
        # iPhoneの位置情報を取得
        location = api.devices[0].location()
        current_coordinate = (location['latitude'], location['longitude'])
        print("座標", current_coordinate)
        
        # 現在位置とコンビニ位置の距離を計算
        distance = geodesic(current_coordinate, convenience_store).kilometers
        print("距離", distance)
        
        # 距離が設定した範囲内に入った場合、メール送信
        if distance <= radius_threshold:
            print("メール送信へ移行")
            break
        
    except Exception as e:
        print("エラー:", e)
    
    # 位置情報の取得間隔を設定するために適切な待ち時間を設定
    # 例えば、30秒ごとに位置情報を取得する場合
    time.sleep(30)
```

## メール送信の関数
* **SMTPサーバーの設定**
GmailのSMTPサーバーの情報（サーバーアドレスとポート番号）を設定します。
* **メールの設定** 
MIMETextオブジェクトを使用して、メールの本文を設定します。また、メールの件名、送信元アドレス、宛先アドレスなどの情報も設定します。
* **SMTPサーバーへの接続とメールの送信**
指定されたSMTPサーバーに接続し、SMTPサーバーとのセッションを開始、その後ログインします。そしてメールの内容を文字列形式に変換し、SMTPサーバーを介して宛先のメールアドレスにメールを送信します。

```python
from email.mime.text import MIMEText
import smtplib

def send_email(sender_email, sender_password, recipient_email, subject, body):    
    # SMTPサーバーの設定
    smtp_server = 'smtp.gmail.com'  # 送信者のメールサーバーを設定
    smtp_port = 587  # 587番ポートを使用

    # メールの設定
    msg = MIMEText(body)
    msg['Subject'] = subject
    msg['From'] = sender_email
    msg['To'] = recipient_email

    # SMTPサーバーに接続してメールを送信
    try:
        server = smtplib.SMTP(smtp_server, smtp_port)
        server.ehlo()  
        server.starttls()
        server.login(sender_email, sender_password)
        server.sendmail(sender_email, recipient_email, msg.as_string())
        server.quit()
        print("メールが送信されました。")
    except Exception as e:
        print("メールの送信に失敗しました:", e) 
```

## メール内容の設定
メールの件名、本文、また送信元と受信者のメールアドレスの設定を行い、メールを送信します。
```python
# メールの件名と本文を設定
subject = '厳しいって'
body = 'スーパー行かずにコンビニばっかり行ってる君、ガチで危機感持った方がいいと思う。'

# 送信元のメールアドレスとパスワードを設定
sender_email = 'your_email@example.com'
sender_password = 'your_password'

# 受信者のメールアドレスを設定
recipient_email = 'recipient_email@example.com' 

# メールを送信
send_email(sender_email, sender_password, recipient_email, subject, body)
```


# 最後に
今回は、Jupyterで実装しましたが、実際に使うとなると、スマホアプリにした方が実用的ではないかと感じたので、作成してみたいと思いました。