AWS IoT Core Device Location を使って SORACOM Air for セルラー(LTE) を利用しているデバイスの位置を取得して AWS IoT の Location Action で Amazon Location Service に送信する

# 概要
※ こちらは [SORACOM Advent Calendar 2022](https://qiita.com/advent-calendar/2022/soracom) 12日目の記事です。

2022/11/27 に AWS IoT Core に新機能 Device Location が追加されました([EN](https://aws.amazon.com/about-aws/whats-new/2022/11/aws-iot-core-new-device-location-feature/?nc1=h_ls)/[JP](https://aws.amazon.com/jp/about-aws/whats-new/2022/11/aws-iot-core-new-device-location-feature/))。IoT デバイスが利用しているセルラーネットワーク、Wi-Fi、GNSS、IP アドレスを用いて位置を特定できる機能です。今回は SORACOM Air for セルラーの LTE 回線を利用しているデバイスの位置情報を取得して Amazon Location Service に送信してみたいと思います。

# 構成
![Screenshot 2022-12-10 at 19.12.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/c6d614ad-fda8-a8b0-f855-e0b1c62b0496.png)

# 手順
まずデバイスを用意します。今回は以下を用意しました。
- Raspberry Pi 4 Model B rev 1.2 2GB
- SORACOM Onyx LTE USB ドングル
- SORACOM Air plan-D nano

他は以下の環境で進めます。
- MacBook Pro macOS Ventura 13.0.1
- VSCode
- Chrome

## 1. Raspberry Pi の初期セットアップ
Raspberry Pi の[公式サイト](https://www.raspberrypi.com/software/)から Raspberry Pi Imager をダウンロードして PC にインストールします。
![Raspberry Pi OS – Raspberry Pi 2022-12-06 14-17-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/6fbfaf82-d13e-fd6c-f4f0-88529ce9ea5d.png)
microSD カードを PC に接続し OS を書き込んでいきます。
OS は Raspberry Pi OS (64-bit) を選択しました。
![Raspberry Pi Imager v1.7.3 2022-12-06 14-34-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/b261f9ea-784b-9040-9fbe-bc50d420b941.png)
Wi-Fi の設定、SSH の設定を入れておきます。その他、必要な設定を入力したら WRITE します。
![Raspberry Pi Imager v1.7.3 2022-12-06 14-23-56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/e2a2f950-5b92-b0c6-bc21-e6d1f6976247.png)
Write→Verify が完了するまで待ちます。
![Raspberry Pi Imager v1.7.3 2022-12-06 14-33-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/78dd0619-8cf0-84a5-2bc4-982cfcaa9bca.png)
Verify が完了したら microSD カードを PCから外して Raspberry Pi の microSD カードスロットに挿して電源に接続します。
![raspi.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/09e8073a-b67e-6647-ff19-e8e30bef8663.jpeg)
※ ちなみに[金属製のアーマーケース](https://www.amazon.co.jp/gp/product/B07VD5L1VY/)を装着しています。冷却効果はわかりませんが満足度は上がりました。
Raspberry Pi Imager で Wi-Fi と SSH の設定を入れておいたので、VSCodeから SSH で接続してみます。
[VSCode](https://azure.microsoft.com/ja-jp/products/visual-studio-code/) の [Remote Development](https://code.visualstudio.com/docs/remote/remote-overview) Extensions で Raspberry Piに接続します。
![pi [SSH: raspi4b] 2022-12-06 14-56-46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/900ade17-d563-25cb-bf9a-7dcab76777f4.png)
SSH で繋がりました。

OS を新規インストールしたので、とりあえず apt update & upgrade します。
```shell-session
pi@raspberrypi:~ $ sudo apt update
pi@raspberrypi:~ $ sudo apt upgrade
```

## 2. SORACOM Onyx LTE USB ドングルの初期セットアップ
[こちら](https://users.soracom.io/ja-jp/guides/usb-dongles/soracom-onyx/raspberrypi/)を参考に SORACOM Onyx LTE USB ドングル をセットアップします。
SORACOM Onyx LTE USB ドングルを Raspberry Pi に挿します。
![onyx.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/0eaabd9c-fbe0-6966-37b4-805854829875.jpeg)

VSCode の Terminal で作業していきます。
```shell-session
pi@raspberrypi:~ $ ls /dev/ttyUSB*
/dev/ttyUSB0  /dev/ttyUSB1  /dev/ttyUSB2  /dev/ttyUSB3
pi@raspberrypi:~ $ mkdir ONYX
pi@raspberrypi:~ $ cd ONYX/
pi@raspberrypi:~/ONYX $ curl -O https://soracom-files.s3.amazonaws.com/setup_air.sh
pi@raspberrypi:~/ONYX $ sudo bash setup_air.sh
pi@raspberrypi:~/ONYX $ ifconfig ppp0
ppp0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1464
        inet 10.142.nnn.nnn  netmask 255.255.255.255  destination 10.64.64.64
        ppp  txqueuelen 3  (Point-to-Point Protocol)
        RX packets 420  bytes 139308 (136.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 401  bytes 30541 (29.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
pi@raspberrypi:~/ONYX $ cd
```
こちらもすぐに SORACOM プラットフォームに繋がりました。もう少し確認してみます。
```shell-session
pi@raspberrypi:~ $ ping -c 4 pong.soracom.io
PING pong.soracom.io (100.127.100.127) 56(84) bytes of data.
64 bytes from 100.127.100.127 (100.127.100.127): icmp_seq=1 ttl=64 time=39.0 ms
64 bytes from 100.127.100.127 (100.127.100.127): icmp_seq=2 ttl=64 time=63.5 ms
64 bytes from 100.127.100.127 (100.127.100.127): icmp_seq=3 ttl=64 time=61.8 ms
64 bytes from 100.127.100.127 (100.127.100.127): icmp_seq=4 ttl=64 time=58.6 ms

--- pong.soracom.io ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 38.984/55.716/63.474/9.816 ms

pi@raspberrypi:~ $ curl -s http://metadata.soracom.io/v1/subscriber
{"imsi":"4401050..省略}
```
ここで `http://metadata.soracom.io/v1/subscriber` が取得できないときは[メタデータサービス](https://users.soracom.io/ja-jp/docs/air/use-metadata/#%e3%83%a1%e3%82%bf%e3%83%87%e3%83%bc%e3%82%bf%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%82%92%e8%a8%ad%e5%ae%9a%e3%81%99%e3%82%8b)を設定してください。

## 3. AWS IoT Core Device Location を試してみる
Raspberry Pi + SORACOM Onyx LTE USB ドングルでセルラー回線に繋がったので、とりあえず AWS IoT Core Device Location を試してみます。AWS にログインし AWS IoT Core の管理画面に遷移すると、左側メニューの `Test` に `Device Location` が追加されています。
![AWS IoT 2022-12-07 14-17-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/62558648-14a8-8ffc-c862-966711e256f7.png)
![AWS IoT - Test - Device location 2022-12-07 14-19-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/6b353c57-052d-42d0-1055-6e66fce1a03e.png)
payload を入力して `Resolve` をクリックすると結果が取得できます。payload の詳細については AWS のドキュメント [Location solvers and device payload](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/device-location-solvers-payload.html) に記載されています。今回は [Cellular based solver](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/device-location-solvers-payload.html#location-solvers-cellular) を使用します。
LTE で required となっている項目は `Mcc`,`Mnc`,`EutranCid` の 3 つです。ちなみにざっくりと説明すると以下のような情報です。
- MCC: 国を表すコード
- MNC: ネットワークを表すコード
- EutranCid: そのエリアの中で基地局に割り当てられた番号

これらの情報を取得するためには、デバイスで AT コマンド(通信モジュールを制御するためのコマンド)を実行する必要があります。ただ、今回は SORACOM Air を利用しているため、[メタデータ](https://users.soracom.io/ja-jp/docs/air/use-metadata/)を利用して簡単に取得します。
`Mcc`,`Mnc`,`EutranCid` の 3 つはメタデータの `sessionStatus.cell` に含まれています。
```shell-session
pi@raspberrypi:~ $ curl -s http://metadata.soracom.io/v1/subscriber.sessionStatus.cell
{"radioType":"LTE","mcc":nnn,"mnc":nn,"tac":nnnnn,"eci":nnnnnnnnn}
```
:::note 
メタデータの[クエリ機能](https://users.soracom.io/ja-jp/docs/air/use-metadata/#%e3%83%a1%e3%82%bf%e3%83%87%e3%83%bc%e3%82%bf%e3%81%ae%e8%aa%ad%e3%81%bf%e5%8f%96%e3%82%8a%e4%be%8b-%e3%82%af%e3%82%a8%e3%83%aa%e6%a9%9f%e8%83%bd%e3%82%92%e4%bd%bf%e7%94%a8%e3%81%99%e3%82%8b)を使用して `cell` のみを抽出しています。
:::
`EutranCid` = `eci` です。これを Device Location の payload に合わせて整形します。整形には jq を利用します。`tac` も取得できるので optional ですが含めておきます。
```shell-session
pi@raspberrypi:~ $ sudo apt install -y jq
pi@raspberrypi:~ $ curl -s http://metadata.soracom.io/v1/subscriber.sessionStatus.cell | jq '{"CellTowers":{"Lte":[{"Mcc":.mcc,"Mnc":.mnc,"EutranCid":.eci,"Tac":.tac}]}}'
{
  "CellTowers": {
    "Lte": [
      {
        "Mcc": nnn,
        "Mnc": nn,
        "EutranCid": nnnnnnnnn,
        "Tac": nnnnn
      }
    ]
  }
}
```
:::note
jq の使い方、オプションの詳細は[公式サイト](https://stedolan.github.io/jq/manual/)を参照ください。
:::
整形された payload を `Resolve` してみます。
![AWS IoT - Test - Device location 2022-12-07 14-44-49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/a6536bd7-b024-1ee9-703b-a266ca50875d.png)
コピー & ペーストして `Resolve` をクリック。
![AWS IoT - Test - Device location 2022-12-07 14-44-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/a98f0b34-542b-c31e-4a72-356fde43598f.png)

:::note 
結果は [GeoJSON](https://geojson.org/) 形式で返ってきます
:::
無事 Resolve されました。`coordinates` に `経度, 緯度` が返ってきます。Google マップで確認してみます。確認する際は `緯度, 経度` のように入れ替えて検索します。
![34°44'28.5"N 135°31'22.3"E - Google Maps 2022-12-08 10-15-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/e1e8c1e6-d1b2-2027-4d77-b25d78fedc31.png)
おぉ、近からず遠からず...。ということでなんとなく AWS IoT Code Device Location の使い方がわかりました。

## 4. Raspberry Pi から SORACOM Beam を使って、 AWS IoT Core にデータを送信する
手動での確認が出来たので、ここからはデバイスとクラウドを繋いでいきます。SORACOM のドキュメント [AWS IoT と接続する](https://users.soracom.io/ja-jp/docs/beam/aws-iot-console/) を参考に Things(モノ) を作成します。
![AWS IoT - Manage - Things 2022-12-07 15-08-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/dde2881e-ece5-fdf7-e83e-10e97bd97d82.png)
出来ました。作成時に表示される各種証明書については全てダウンロードしておきます。
![AWS IoT - Manage - Things - takuya-raspi 2022-12-10 17-28-19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/ce8c8e7a-9966-5103-c3a7-a7a8dc6864fa.png)

証明書にポリシーもアタッチしました。ポリシーでは `iot:Publish` と `iot:Connect` を許可しています。
![AWS IoT - Security - Certificates - 851057952c2b953277a4bc17f96b763f962b6c04dcb60cb65d0a49d7c703630a 2022-12-07 15-10-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/0905b024-8c98-4cd4-7fdd-5e5fb31b6e03.png)
デバイスデータエンドポイントを確認しておきます。
![AWS IoT - Settings 2022-12-07 15-18-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/8f2eafb2-d68d-9589-684f-6705f9a4d9e0.png)
次に [SORACOM Beam の有効化](https://users.soracom.io/ja-jp/docs/beam/aws-iot-console/#soracom-beam-%e3%82%92%e6%9c%89%e5%8a%b9%e5%8c%96%e3%81%99%e3%82%8b)を行います。今回は MQTT エントリポイントを追加します。
![Groups - SORACOM User Console 2022-12-10 13-32-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/c21d0786-16eb-70f8-7a19-c0fe8ad29426.png)
`HOST NAME` には AWS IoT Core のデバイスデータエンドポイント、`PORT NUMBER`には 8883 を入力します。
![Groups - SORACOM User Console 2022-12-10 13-51-47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/7e6c8708-1a1a-ccf1-a2cf-6237b725d10d.png)
AWS IoT Core へは Things を作成した時にダウンロードしたクライアント証明書を利用して認証します。`CLIENT CERT` を設定し `Save` します。
![Groups - SORACOM User Console 2022-12-10 13-56-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/4e79a4fb-c8d2-8302-7213-62902c9f6e0d.png)
SORACOM Beam の設定が完了したので、[こちら](https://users.soracom.io/ja-jp/docs/beam/aws-iot-console/#%e3%82%b9%e3%83%86%e3%83%83%e3%83%97-3-%e3%83%87%e3%83%90%e3%82%a4%e3%82%b9%e3%81%8b%e3%82%89%e3%83%87%e3%83%bc%e3%82%bf%e3%82%92%e9%80%81%e4%bf%a1%e3%81%99%e3%82%8b)を参考にデバイスから AWS IoT Core に MQTT でデータを送信してみます。まず AWS IoT Core の MQTT Test Client の Subscribe を行います。`Topic Filter` に任意の文字列を設定し `Subscribe` をクリックします。
![AWS IoT - MQTT test client 2022-12-07 15-37-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/a7bb366d-5211-ca96-b567-b78dd0b14467.png)
次に VSCode の Terminal(Raspberry Pi) で作業します。MQTT Client として [mosquitto](https://mosquitto.org/) を利用します。
```shell-session
pi@raspberrypi:~ $ sudo apt install mosquitto-clients
```
mosquitto がインストールできたら、とりあえず Publish してみます。`-t` には MQTT Test Client で設定した任意の文字列(Topic)を指定します。
```shell-session
pi@raspberrypi:~ $ mosquitto_pub -d -h beam.soracom.io -t beam_test -m '{"Hello": "World"}'
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending PUBLISH (d0, q0, r0, m1, 'beam_test', ... (12 bytes))
Client (null) sending DISCONNECT
```
MQTT Test Client を見てみるとメッセージが届いていることが確認できます。
![AWS IoT - MQTT test client 2022-12-10 17-06-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/83c2828a-9bd5-2c54-d8f4-afb30d556397.png)
## 5. Raspberry Pi で Location を Resolve して AWS IoT Core に送信する
今回は Raspberry Pi 上で SORACOM Air for セルラーの LTE 回線の情報を元に位置情報を取得し、 AWS IoT Core に送信する形で実装します。VSCode の Terminal(Raspberry Pi) で作業していきます。また Python および [AWS SDK for Python(boto3)](https://aws.amazon.com/jp/sdk-for-python/) 、[paho](https://www.eclipse.org/paho/index.php?page=clients/python/index.php) を使用します。
[Boto3 の Quickstart](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html) を参考にインストールします。
```shell-session
pi@raspberrypi:~ $ python -V
Python 3.9.2
pi@raspberrypi:~ $ pip install boto3
pi@raspberrypi:~ $ pip install paho-mqtt
```
AWS への認証情報を設定します。`~/.aws/credentials` に以下のように記載します。
```shell:credentials
[default]
aws_access_key_id = Axxxxxxx
aws_secret_access_key = Qxxxxxx
```
Python のコードは以下です。
```python:send_location.py
import time
import requests
import json
import boto3
import datetime
import paho.mqtt.client as mqtt

client_id = 'takuya-raspi'
protocol = mqtt.MQTTv311
host = 'beam.soracom.io'
port = 1883
keepalive = 60
topic = client_id + '/location'
wait = 60


def on_log(client, userdata, level, buf):
    print(buf)


def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))


def main():
    mqtt_client = mqtt.Client(protocol=protocol)
    mqtt_client.on_log = on_log
    mqtt_client.on_connect = on_connect
    mqtt_client.connect(host=host, port=port, keepalive=keepalive)

    while True:
        # Get cellular tower information
        res = requests.get(
            'http://metadata.soracom.io/v1/subscriber.sessionStatus.cell')
        json_data = res.json()
        print("cell_data: " + json.dumps(json_data))
        # Resolve location
        boto3_client = boto3.client('iotwireless')
        ts = datetime.datetime.now(
            datetime.timezone(datetime.timedelta(hours=9)))
        res = boto3_client.get_position_estimate(
            CellTowers={
                'Lte': [
                    {
                        'Mcc': json_data['mcc'],
                        'Mnc': json_data['mnc'],
                        'EutranCid': json_data['eci'],
                        'Tac': json_data['tac']
                    },
                ],
            },
            Timestamp=ts
        )

        geoJson = json.loads(res['GeoJsonPayload'].read().decode())
        geoJson["device_id"] = client_id
        print("send_geoJson: " + json.dumps(geoJson))

        mqtt_client.publish(topic, json.dumps(geoJson))
        time.sleep(wait)


if __name__ == "__main__":
    main()
```
適当な名前で保存し、実行します。
```shell-session
pi@raspberrypi:~ $ vi send_location.py
pi@raspberrypi:~ $ python send_location.py 
```
簡単にコードを説明すると
1. メタデータから `sessionStatus.cell` を取得
2. AWS SDK for Python(boto3)で [`get_position_estimate`](https://docs.aws.amazon.com/ja_jp/iot-wireless/2020-11-22/apireference/API_GetPositionEstimate.html) を実行し位置情報(GeoJSON 形式)を取得する
3. 取得した位置情報(GeoJSON 形式)に`device_id` を追加する
4. MQTT で Topic: `takuya-raspi/location` に Publish する
5. 上記を 60 秒間隔で繰り返す

という内容になっています。停止させる際は `Ctrl + c` で停止させてください。

AWS IoT Core の MQTT Test Client でデータが届いていることを確認します。
![AWS IoT - MQTT test client 2022-12-11 23-41-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/9700ca30-8390-83b2-9ddc-3e027d4bceca.png)
## 5. AWS IoT Rule Actions で Amazon Loction Service にデータを送信する
AWS IoT Core まで位置情報が届いたので、その位置情報を Amazon Location Service に送信します。送信には AWS IoT Rule Actions の [Location](https://docs.aws.amazon.com/iot/latest/developerguide/location-rule-action.html) を使用します。
Rule を新規作成していきます。
![AWS IoT - Message Routing - Rules 2022-12-10 17-53-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/42ec7f63-72e5-34e6-14ba-40a7dadb8645.png)
![AWS IoT - Message Routing - Rules - Create rule 2022-12-10 17-57-31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/2a594f63-4364-667a-36b8-b0e97d88f4df.png)
SQL Statement は Raspberry Pi から送信(Python Script から送信)している Topic を FROM に指定します。
![AWS IoT - Message Routing - Rules - Create rule 2022-12-10 18-00-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/1abd8081-11c3-c23c-89b0-b26af38fafc4.png)
Rule actions の `Action 1` で `Location` を選択し `Create a Tracker` を選択します。
![AWS IoT - Message Routing - Rules - Create rule 2022-12-10 18-03-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/bc36d4c3-b57b-21c7-3ff7-2d924b6fb498.png)
Amazon Location Service の画面が開きます。Tracker の `Name` を入力し、`Create tracker` を選択します。
![Create tracker | Trackers | Amazon Location 2022-12-10 18-05-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/51a47d7b-9854-e255-0591-9742fce4a96f.png)
元の画面に戻り再読み込みボタンを選択し、作成した Tracker を選択します。`Device ID` に `${device_id}`、`Longitude` に `${get(coordinates, 0)}`、`Latitude` に `${get(coordinates, 1)}`、`Timestamp` に `${timestamp()}` と入力し、 `Create new role` を選択します。
![AWS IoT - Message Routing - Rules - Create rule 2022-12-11 23-47-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/87c8be04-da04-3b0b-724a-b2b02c1b3fa7.png)

:::note
${expression} は[置換テンプレート](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-substitution-templates.html)です。AWS IoT Core に送信されたデータに置き換えたり、関数や演算子を使用できます。今回は Longitude/Latitude の取得に [get](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-sql-functions.html#iot-sql-function-get)、Timestamp value に [timestamp()](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-sql-functions.html#iot-function-timestamp) という[関数](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-sql-functions.html)を使用しています。
:::

Role Name を入力して `Create` を選択します。
![AWS IoT - Message Routing - Rules - Create rule 2022-12-10 18-18-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/7ffb91fa-69a0-4fc0-8e36-30b4754eb4d0.png)
作成した IAM Role が選択されていること、他の入力項目が正しいことを確認して `Next` を選択します。
![AWS IoT - Message Routing - Rules - Create rule 2022-12-12 00-15-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/48932d75-8598-c54c-3e18-42f9b53ba16a.png)
内容を確認して `Create` を選択します。
![AWS IoT - Message Routing - Rules - Create rule 2022-12-12 13-45-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33047/eda0f83b-dbc2-6ef9-9a48-f9e1426d61d0.png)
これで、Topic: `takuya-raspi/location` に Publish されたデータが、Amazon Location Service の Tracker: `takuya-tracker` に送信されるようになりました。もう一度 Raspberry Pi でデータ送信を実行します。
```shell-session
pi@raspberrypi:~ $ python send_location.py 
```
何度かデータが送信されたら、以下のコードで Tracker のデータを確認します。
```get_device_position_history.py
import json
import pprint
import boto3

client_id = 'takuya-raspi'
tracker_name = 'takuya-tracker'


def main():
    client = boto3.client('location')
    res = client.get_device_position_history(
        DeviceId=client_id,
        TrackerName=tracker_name
    )
    devicePositions = json.dumps(
        res['DevicePositions'], default=str)
    print(devicePositions)


if __name__ == "__main__":
    main()
```
適当な名前で保存し、実行します。
```shell-session
pi@raspberrypi:~ $ vi get_device_position_history.py
pi@raspberrypi:~ $ python get_device_position_history.py
[{"DeviceId": "takuya-raspi", "Position": [135.52nnnnnnnnnnnn, 34.74nnnnnnnnnnnn], "ReceivedTime": "2022-12-10 09:26:13.905000+00:00", "SampleTime": "2022-12-10 09:26:12.729000+00:00"}, {"DeviceId": "takuya-raspi", "Position": [135.52nnnnnnnnnnnn, 34.74nnnnnnnnnnnn], "ReceivedTime": "2022-12-10 09:27:15.022000+00:00", "SampleTime": "2022-12-10 09:27:14.085000+00:00"}]
```
Tracker にデータが格納されていることが確認できました。

# あとがき
LTE 回線を利用しているデバイスの位置情報の取得が簡単にできました。今回は Raspberry Pi 上で位置情報を取得（`get_position_estimate`）しましたが、デバイス側を省力化する場合は AWS IoT Core にデータを送信した先で位置情報を取得する形がいいと思います。例えば、
- `takuya-raspi-location-cellular` に Publish → Rule Action で Lambda を呼び出す → Lambda で位置情報を取得し `takura-raspi-location` に Republish する
- `takuya-raspi-location` の SQL Statement で Lambda を呼び出す

のような形が考えられます。

ちなみに、SORACOM Air for セルラーでは[基地局の位置情報を取得できる API](https://blog.soracom.com/ja-jp/2020/10/14/cell-location-api/) が無料で提供されています。AWS IoT Core Device Location は Semtech 、 HERE 、MaxMind など AWS パートナーが提供するソリューションと統合されていますが、SORACOM の位置情報取得 API は Mozilla Location Service のデータを利用しています。また戻り値が GeoJson 形式ではないので、利用する際にはデータの送信前に加工する、 Location Action の置換テンプレートを変更する、といった対応が必要になります。
あと、置換テンプレートが便利でした。GeoJson 形式では `{"Position": [135.52nnnnnnnnnnnn, 34.74nnnnnnnnnnnn]}` のように Longitude / Latitude を配列で取り扱いますが、配列そのままで値を取得することができます。置換テンプレート（というか AWS IoT の SQL Statement）がないと、GeoJson 形式を JSON(KEY/VALUE) に変換して送信する、ということが必要になります。Rule をうまく使えば、Longitude / Latitude で受信したデータと GeoJson 形式で受信したデータの両方を Amazon Location Service に送信することも簡単にできます。今回は Raspberry Pi を使用したので送信するデータの加工は比較的容易ですが、送信するデータフォーマットが固定されているデバイスでも置換テンプレート(と [SORACOM Orbit](https://soracom.jp/services/orbit/) )を使えばなんとかできそうな気がします。
Amazon Location Service での可視化はアプリ（Web アプリ、Android）を作る必要があります。こちらもいつか試してみたいと思います。

ではまた。