【バイクのエンジンかけるだけ】LINE botとラズパイを使って「今から帰ります」を全自動化してみた

# 目次
* きっかけ
* この記事をおすすめする人
* Geocoding APIとは？ Google Maps Geocoding API keyの取得・使用方法
* 事前準備（crontabとwpa_supplicant.conf設定）
* システム構成
* 実装編
* 実際に使ってみた
* 最後に


# 1. きっかけ
#### 大学から家に帰る時、「今から帰ります」を連絡するのが面倒...
私はバイクで通学しているので、ヘルメット被って携帯開いて連絡するのが結構面倒で、自動化できないかなあと思っておりました。ワンボタンで「今から帰ります」を実現してみた！等はよくありますが、
意識せず、全自動化で送ってくれるのは見当たりませんでした...

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1936739/ef47b3b1-e7f7-9e51-3de7-738138975686.png" width=70%>





そこで、バイクのシガーソケットを給電に、小型コンピュータをポケットに入れ、繋げておくことで、電源が入った瞬間にGPS取得、場所の特定、LINEで帰宅メッセージの送信ができるシステムを構築しました！

また、GPS情報から住所情報の変換はGoogle Maps Geocoding APIを使用します。登録の仕方は次章で説明します。今回はGPS情報→住所なので逆ジオコーディング(Reverse Geocoding)を使用します。







# 2. この記事をおすすめする人
- 簡単なIoTシステムを手軽に作ってみたい人
- Geocoding APIを使いたい人
- 今から帰りますを自動化したい人


# 3. Geocoding APIとは？ Google Maps Geocoding API keyの取得・使用方法

### Geocoding API とは？

Geocoding APIは、与えられた住所情報を地理座標に変換するためのAPIです。住所情報を入力すると、APIはその住所の地理座標（緯度と経度）を返します。
逆に、地理座標から住所を得たい場合は逆ジオコーディング(Reverse Geocoding)を使用します。

Geocoding APIには、多くの企業やオープンソースのプロジェクトが提供しており、Google Maps Geocoding API、Mapbox Geocoding API、OpenCage Geocoder API、Here Geocoder APIなどがあります。それぞれのAPIには、料金、利用可能な機能、制限などが異なる場合があります。

### Google Maps Geocoding API keyの取得方法

まず、[Google Cloud Platform](https://cloud.google.com/?hl=ja)にログインしてください。

その後、左上の三本線からAPIとサービス、ライブラリへ移動してください。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1936739/f74ca785-c53d-0413-b8a0-67b997dddce3.png" width=60%>


その後、Geocoding APIと検索します。有効にするをクリック。

![スクリーンショット 2023-04-28 15.26.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1936739/79e0cf06-b95d-47a7-d04b-4e412e7a9eab.png)

その後、三本線からAPIとサービスをクリック。認証情報をクリックします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1936739/54818807-4d3d-5bdf-20e5-9f8a1e83e9f0.png" width=60%>

認証情報を作成をクリックしAPIキーを選択。その後API keyが発行されるのでメモしておきましょう。


![スクリーンショット 2023-04-28 15.36.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1936739/79eeeeef-932d-ee7b-d4d4-0d3289da94d6.png)


# 4. 事前準備（crontabとwpa_supplicant.conf設定）

### crontabの設定

crontabによって起動後にapp.pyを時効するように制御しておきましょう
pathは変えてご使用ください。

```
@reboot sleep 10 && /usr/bin/python3 /path/to/app.py >> /path/to/logfile.log 2>&1
```
### wpa_supplicant.confの設定

バイクを乗るときは常時携帯を所持しているのでテザリングが繋がるように制御しましょう

```
network={
        ssid="XXXXXXX"
        psk="XXXXXX"
        priority=1
}
```




# 5. システム構成

システム構成図を示します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1936739/ce20dc69-5bf9-2d05-5661-cd0178e4b69b.png" width=90%>

(①より前にまず携帯のテザリングに接続します)
① app.pyが走り始め、GPS情報を取得します。(取得できるまでループを回します。)
② lat,lonをGCPのAPIへ投げます。
③ APIの結果をラズパイへ返します。
④ 処理結果をnotifyに投げる




:::note info
**バイクの運転終了とともに電源が急に切れるとラズパイにダメージが行きかねないので、app.pyの実行完了後はスタンバイモードになるようにしています**
:::

# 6. 実装編
```python

import requests
from gps3 import gps3
import os

# LINE Notifyのアクセストークンを設定
ACCESS_TOKEN = "XXXXXXXX"

# LINE NotifyのAPIエンドポイントを設定
NOTIFY_URL = "https://notify-api.line.me/api/notify"

# Google Maps Platform APIのAPIキーを設定
API_KEY = "XXXXXXXX"

# 逆ジオコーディングするAPIのURLを設定
GEOCODE_URL = "https://maps.googleapis.com/maps/api/geocode/json"


def main():
    # GPSデータを取得する
    gps_socket = gps3.GPSDSocket()
    data_stream = gps3.DataStream()
    gps_socket.connect()
    gps_socket.watch()

    try:
        while True:
            new_data = gps_socket.next()
            if new_data:
                data_stream.unpack(new_data)
                lat = data_stream.TPV['lat']
                lon = data_stream.TPV['lon']
                if lat != 'n/a' and lon != 'n/a':
                    # 逆ジオコーディングして住所に変換する
                    params = {"latlng": f"{lat},{lon}", "key": API_KEY, "language": "ja"}
                    response = requests.get(GEOCODE_URL, params=params)
                    result = response.json()

                    # 住所の取得に失敗した場合はスキップ
                    if not result.get('results'):
                        continue

                    address = result['results'][0]['formatted_address']
                    # 位置情報に基づいてメッセージを作成
                    if '大学周辺の住所を入れる' in address:
                        address = '大学'
                    elif '自宅周辺の住所を入れる' in address:
                        address = '自宅'
                    message = f"現在より、{address}を出発します。"

                    # LINE Notifyにメッセージを送信
                    headers = {"Authorization": "Bearer " + ACCESS_TOKEN}
                    payload = {"message": message}
                    requests.post(NOTIFY_URL, headers=headers, params=payload)
                    break
    except Exception as e:
        print(e)
    finally:
        gps_socket.close()
        # スリープモード命令
        os.system("sudo systemctl suspend")


if __name__ == '__main__':
    main()

```

# 7. 実際に使ってみた

す、すごい。。
バイクの電源を入れるだけで勝手にLINEが送信されている...
こちら自宅での撮影になるので、「自宅を出発しました」のメッセージが送信されています。

※最近ハマってるゴーファーくんは見逃してください。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1936739/9b931031-fa63-dfd0-12b2-e5dbb1778849.gif" width=90%>

# 8. 最後に

GPSは起動後少し時間がかかるのがネックですね...! 早くても電源投入後1分はかかりました...
読んでいただき、ありがとうございました！いいなと思えばいいねお願いいたします！