termux×AWS IoT でスマホ位置情報をAWSに送信

#はじめに
妻に、「職場を出たらラインしろ」と言われているのですが、正直面倒です。
自分が職場を出たことを自動で通知できないかなと思い、とりあえず位置情報をAWSに送ってみました。

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/f9429f7f-320e-2383-24da-e35578dd9fdb.png)


#環境
スマホ：京セラ（KTV44）
OS:Android 9

##スマホ（termux）側
AndroidにGoogle Playを利用して、termuxをインストールします。
https://play.google.com/store/apps/details?id=com.termux&hl=ja

スマホだとキーボード入力しづらいため、
インストール後に下記コマンドを入力し、ssh用の環境を構築します。

```shell
$ apt upgrade #とりあえず最新にする。
$ termux-setup-storage #termuxにandroidストレージの使用を許可する。
$ pkg install openssh #ssh（サ－バ、クライアント両方）をインストール
$ sshd #sshサーバを起動
$ passwd #パスワードの設定
$ whoami #ユーザ名の確認（メモしてください。）
$ ifconfig #スマホのIPアドレスの確認（メモしてください。）
```



ちなみに、termuxで表示されるIPアドレスはスマホ自体のIPアドレスと一緒なので、あらかじめ分かっていればifconfigしなくても大丈夫です。
  
次に作業しやすいようにPCからsshでスマホに接続します。
ここで注意です.
sshのデフォルトのTCPポート番号は22ですが、termuxの場合は8022が指定されています。
そこで-pオプションでポート番号を指定します。
PC（Ubuntu）側

```shell
$ ssh -p 8022  (ユーザ名)@(スマホのIPアドレス)
```

最初にsshをした場合、
Are you sure you want to continue connecting (yes/no)?
と出るので、yesと回答。
その後、スマホで設定したパスワードを入力します。

初期状態ではバックグラウンド処理が禁止されているため、スマホがスリープ状態になるとsshの接続がその都度中断されててしまいます。
スマホで「RELEASE　WAKELOCK」を選択することで、バックグラウンド処理が行われるようになる。

![Screenshot_20201015-214307.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/f0efddd0-4ff1-8631-11f0-74a51bc2cbd4.png)


sshで入れるようになったら、引き続き環境を構築していきます。

```shell
$ pkg install git #後に使用するAWS IoT Core用にgitをインストールしておく。
$ pkg install python #Pythonもインストールしておく。
$ pkg install vim-python #ファイル編集用にvimもインストールしておく。
$ pkg install termux-api #termux-apiもインストールしておく。GPS情報を取得するために必要。
```
インストール系が終了したら、次はAWS Iot Coreを設定します。
この↓記事を参考に「android01」なるモノを登録し、スマホからAWSへの接続テストまで行います。
https://qiita.com/zakuzakuzaki/items/e30d63598ca1d6c0f2a9

意外とそのままできたのでびっくりです。
termuxすごい。

「termux-api」の中の、termux-locationコマンドで、位置情報を取得します。
https://wiki.termux.com/wiki/Termux-location

```shell
$ termux-location -p network #スマホが観測している現在位置を出力
{
  "latitude": 	35.6359322,
  "longitude": 139.8786311,
  "altitude": 43.5,
  "accuracy": 23.26799964904785,
  "vertical_accuracy": 3.299999237060547,
  "bearing": 0.0,
  "speed": 0.0,
  "elapsedMs": 97,
  "provider": "network"
}
```

-pは、位置情報の取得手段を選択するオプションで[gps/network/passive]の中から選択します。
デフォルトだとgpsですが、なぜか自分のスマホではできませんでしたので、networkを選択しました。
（エラーも出ず、ずっと待ち状態になる。）
ちなみにスマホをWi-Fi接続から3G接続に変えても、networkを選択しないと位置情報を取得できません。
>おそらくtermuxアプリの権限の問題だと思いますが、解決できなかったので放置しました。
通常、androidはアプリの設定画面でアプリ毎にフォルダ、カメラ、ＧＰＳなどの利用権限が付与できるのですが、
termuxはそもそも権限の選択肢が出てこないので、付与のしようがありません。

位置情報が取得できることが確認できたら、処理しやすいようにしてjson形式で保存します。


```shell
$ termux-location -p network |sed -e "4,10d"|tr -d '\n'|tr -d ' '| sed -s s/,}/}/g > location.json
$ cat location.json 
{"latitude":35.6359322,"longitude":139.8786311}#いい感じに整形されたことを確認
```
やっていることは、
・位置情報を取得
・４～１０行目（緯度経度以外）を削除
・改行を削除
・スペースを削除
・最後の” , ”（カンマ）を削除
・カレントディレクトリにlocation.jsonを保存
です。
全部の情報をそのまま送ってもいいと思うのですが、少しでも通信量を下げるために、余計なデータをカットしました。

次に、位置情報をパブリッシュするためのプログラムを作成します。
aws-iot-device-sdk-python内のサンプルファイル、「basicPubSub.py」の最後の部分を改造した、「jsonPub.py」を作成します。
位置情報が入っている、location.jsonを読み込みパブリッシュするようにします。


編集前

```python:basicPubSub.py（112行目以降）
# Publish to the same topic in a loop forever
loopCount = 0
while True:
    if args.mode == 'both' or args.mode == 'publish':
        message = {}
        message['message'] = args.message
        message['sequence'] = loopCount
        messageJson = json.dumps(message)
        myAWSIoTMQTTClient.publish(topic, messageJson, 1)
        if args.mode == 'publish':
            print('Published topic %s: %s\n' % (topic, messageJson))
        loopCount += 1
    time.sleep(1)
```

編集後

```python:jsonPub.py（112行目以降）
# Publish to the same topic in a loop forever
with open("location.json", "rb") as load_file:#位置情報ファイルの読み込み
    location = bytearray(load_file.read())#MQTT送信用にbytearray型に変換
loopCount = 0
while True:
    if args.mode == 'both' or args.mode == 'publish':
        myAWSIoTMQTTClient.publish(topic, location, 1)#位置情報をパブリッシュ
        if args.mode == 'publish':
            print('Published topic %s: %s\n' % (topic, location))#確認用
        loopCount += 1
    time.sleep(1)

```

これでスマホ側の構築は終わりです。

##AWS側の設定
次にクラウド側の設定を行います。
といってもポリシーを変えるだけです。

AWS IoT＞ポリシーから、パブリッシュ、サブスクライブしてもいいトピックを追加します。
今回は「location」という名前のトピックを追加しました。
編集が終わったら、「新しいバージョンとして保存」します。
これをしないと接続エラーが発生します。

![0.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/55a19fd9-5f6d-59be-20d5-a2e299c4e193.png)


#テスト
AWS IoT ＞テストにアクセスし、トピック名（location）を入力したのち、「トピックへのサブスクライブ」をクリックします。

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/77fc2661-81b9-0889-a59a-b4a01fcb467a.png)

ターミナルでjsonPub.pyを実行します。
コマンドの最後に-tオプションでトピック名を指定します。

```shell
python jsonPub.py  -e (自分のARNに合わせてください)-ats.iot.ap-northeast-1.amazonaws.com -r root-CA.crt -c android01.cert.pem -k android01.private.key -t location
```

ターミナルに下記メッセージが出力されることを確認します。
スマホがAWSにパブリッシュした位置情報をAWSからサブスクライブできました。

```shell

Received a new message: 
b'{"latitude":35.6359322,"longitude":139.8786311}'
from topic: 
location
--------------
```

さらにAWS側で、locationトピックをサブスクライブしていることを確認します。
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/e2f4afb1-d31e-945d-c771-b7718f9681a9.png)

おつかれさまでした。

#おわりに
スマホの位置情報をAWSに送信する環境を構築しました。
次は、lambda等を利用して退社自動通知や、帰りの電車の発車時刻を調べてくれたらいいですね。
ちなみに、本ページで表示している位置情報は私の家ではありませんので、ご安心ください。

今回作成したファイルは、githubにあげました。
https://github.com/zakuzakuzaki/zaki-aws/tree/main/iot


#参考URL
ご協力ありがとうございました。
　　
Android 端末上で開発環境を整えてみた
https://qiita.com/leosuke/items/b83425d5a6730aa4cf94

Termux で持ち運べるモバイルリポジトリを作る
https://wlog.flatlib.jp/item/1859

PythonでJSON 読み込み
https://qiita.com/kikuchiTakuya/items/53990fca06fb9ba1d8a7

#追　記
AWSとは無関係ですが、[IFTTT（イフト）](https://ifttt.com)の位置情報を用いたトリガーを使って、ほんの数分で実現したいことができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287677/dd75bf1f-5294-8ccf-c292-4c1a3541b559.png)