Amazon Location Service を使って GPS デバイスが特定エリアを出入りしたら通知する仕組みを作ってみた #reinvent

Amazon Location Service を使って、特定の場所に出入りしたら通知する仕組みを作ってみました。とても簡単に位置情報を活用できるようになりました!
2020.12.18

先日発表された新サービス「Amazon Location Service」 を使って、GPS デバイスの位置情報を活用する仕組みを作ってみました。

注意点

Amazon Location Service は、2020年12月17日現在でプレビューサービスです。そのため、本記事の内容は、今後サービスの仕様と異なる場合がありますのでご注意ください。

概要 - 秋葉原に出入りしたら通知する

今回は「秋葉原駅の周辺に出入りしたら通知」する仕組みを作ります。想定するシナリオは以下のようなものとします。

  • GPS 機能のあるデバイスを想定(ソラコムの GPS マルチユニットなど)
  • GPS デバイスの位置情報は MQTT で AWS IoT Core に Publish される
  • 検知するエリアは「秋葉原駅周辺」
  • 「秋葉原駅」周辺エリアに出入りしたタイミングで Amazon SNS 経由でメール通知する

構成図

全体の構成イメージは以下です。
 

00-location-diagram

やってみた

GeoJSON ファイルの作成

まず、特定エリアを定義する Json(GeoJSON)ファイルを用意します。geojson.io などの外部サービスで簡単に作成できます。

geojson.io のページ上で秋葉原駅周辺を適当に線で囲みます。地図右側のメニューから形を選択して囲んでみましょう。

01-geojson_io

エリアを選択できたら画面上のメニューより「Save」を選択して「GeoJSON」として保存します。このファイルは Amazon Location Service にアップロードして使うので、パソコンの適当な場所に保存しておきましょう。

02-select-json

Amazon Location Service の設定

次に、Amazon Location Service の設定です。今回は「Quick Start」から作成していきます。

03-quickstart

そのまま「Get started」をクリックしてください。

04-get-start

ここではジオフェンスを追加しますので、先程ダウンロードしておいた GeoJSON ファイルをアップロードします。

05-upload-geojson

アップロードできたら「Geofence collections」 を今回は明示的に指定して作成します。

06-new-collection

適当な名前と説明を記入したら「Next」をクリックしてください。

07-setting-collection

次はトラッカーの設定です。先程と同様にトラッカーも明示的に指定して作成します。
先に設定したジオフェンスコレクションと、ここで指定するトラッカーがリンクされます。

08-create-new-tracker

名前と説明を入力して次に進みます。今回は「MyTracker1」としました。作成したトラッカーは、後ほど Lambda 関数で指定して使います。

09-enter-tracker-setting

このウィザードでは、EventBridge ルールと CloudWatch Logs が自動的に作成されます。後で動作確認時に使います。

10-set-cloudwatch

レビュー画面で問題がなければ「Create resources」をクリックして作成します。

11-review

作成できたら下記画面のように、作成に成功した表示が見られます。後で使うので各リンクから EventBridge と CloudWatch Logs の画面を開いておくと楽です。

12-success-monitoring

Lambda 関数の作成

次は Lambda 関数の作成です。今回は Python で作ります。
なお、Lambda に含まれる SDK はまだ最新ではないので、最新の SDK を含んだ形で作成します。作業の詳細は割愛しますが下記記事にある手順で最新の Boto3 を利用できるようにパッケージングしました。

関数はドキュメントにあるものをそのまま利用しています。コード中のコメントにあるようにTRACKER_NAME変数には先程作成したトラッカー名に変更しておきましょう。

from datetime import datetime
import json
import os
import boto3

# Update this to match the name of your Tracker resource
TRACKER_NAME = "MyTracker1"

"""
This Lambda function receives a payload from AWS IoT Core and publishes device updates to Amazon Location Service via the BatchUpdateDevicePosition API.

Parameter 'event' is the payload delivered from AWS IoT Core.

In this sample, we assume that the payload has a single top-level key 'payload' and a nested key
'location' with keys 'lat' and 'long'. We also assume that the name of the device is nested in
the payload as 'deviceid'. Finally, the timestamp of the payload is present as 'timestamp'. For
example:

>>> event
{ 'payload': { 'deviceid': 'thing123', 'timestamp': 1604940328,
  'location': { 'lat': 49.2819, 'long': -123.1187 } } }

If your data does not match this schema, you can either use the AWS IoT Core rules engine to
format the data before delivering it to this Lambda function, or you can modify the code below to
match it.
"""
def lambda_handler(event, context):
  # load the side-loaded Amazon Location Service model; needed during Public Preview
  os.environ["AWS_DATA_PATH"] = os.environ["LAMBDA_TASK_ROOT"]

  updates = [
    {
      "DeviceId": event["payload"]["deviceid"],
      "SampleTime": datetime.fromtimestamp(event["payload"]["timestamp"]).isoformat(),
      "Position": [
        event["payload"]["location"]["long"],
        event["payload"]["location"]["lat"]
      ]
    }
  ]

  client = boto3.client("location")
  response = client.batch_update_device_position(TrackerName=TRACKER_NAME, Updates=updates)

  return {
    "statusCode": 200,
    "body": json.dumps(response)
  }

Lambda 関数の作成が完了したら、このLambda が Amazon Location Service を利用できる権限を追加します。該当の関数にある IAMロールのリンクをクリックして IAMロール の画面を開きます。

13-lambda-permission

下記のようなポリシーを追加します。今回はインラインポリシーとして追加しました。

14-lambda-location-policy

ポリシーの内容はBatchUpdateDevicePositionを許可するようにしています。必要に応じて対象トラッカーの指定など行ってください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "WriteDevicePosition",
            "Effect": "Allow",
            "Action": "geo:BatchUpdateDevicePosition",
            "Resource": "arn:aws:geo:*:*:tracker/*"
        }
    ]
}

AWS IoT ルールの作成

次は、パブリッシュされたメッセージを Lambda へ送る AWS IoT ルールを作成します。AWS IoT Core の画面から「Rules」をクリックします。IoT ルールの画面が開いたら右上の「Create」をクリックしてルールの作成を開始します。

15-aws-iot-rules

ルールの内容は次のようにしました。
ルールのクエリは SELECT * FROM 'iot/location' として、アクションには作成したLambda関数を指定します。

16-create-location-rule

最後に、イベント発生を SNS へ通知するために EventBridge を設定しましょう。「Location Service」の設定で作成された EventBridge のルール画面を開きます。

17-eventbridge-rule

デフォルトでは、SNS 通知のルールが無いので追加します。SNS トピックは必要に応じて事前に作成しておいてください。ルールのターゲットに追加できれば下記画面のようにCloudWach Logs と SNS の2つのターゲットが並びます。

CloudWatch Logs のターゲットは Location Service 設定時に自動的に追加されたものです。このロググループに記録されるのは、Lambda でBatchUpdateDevicePosition API が呼び出されることによってジオフェンスに入るイベントです。このイベントをトリガーに EventBride 経由で SNS からメール通知される仕組みです。

18-add-sns-target

動作テスト - 有楽町から秋葉原へ移動

以上で全て設定が完了したので、動作確認してみましょう!
今回は簡単にテストするために、AWS IoT Core のコンソールから位置情報をパブリッシュします。

19-aws-iot-test

画像のように、トピックには IoT ルールで指定したiot/locationを入力します。

20-publish

パブリッシュするメッセージは下記です。最初に設定したジオフェンスの領域外にある有楽町からスタートする想定です。
準備ができたら「トピックに発行」をクリックして位置情報をパブリッシュします。

項目 説明
timestamp unixtime です。(2020-12-17 10:00:00)
location 有楽町駅前の座標です。
{
  "payload": {
    "deviceid": "GPS-Device-001",
    "timestamp": 1608166800,
    "location": {
      "lat": 35.674439,
      "long": 139.764493
    }
  }
}

初回は何も発生しないので、次に秋葉原へ移動してジオフェンスの領域に入ってみましょう。パブリッシュするメッセージを次のように変更してパブリッシュします。
時間は前回より後の時間を指定します。仮に同じ時間を指定すると Location Service 側でエラーとなります。

項目 説明
timestamp unixtime です。(2020-12-17 10:20:00)
location 秋葉原にある書泉ブックタワー近くの座標です。

21-enter-publish

問題なければ、先程のCloudWatch Logs に Location Service のイベントログが記録されます。画像のように"EventType": "ENTER"となっているので、ジオフェンス領域に入った(秋葉原周辺に入った)ことが分かります。

22-enter-event-log

同じタイミングで SNS からメールも届いていました。

23-sns-email

更に追加で、再度時間と場所を更新して有楽町駅前に戻ってみると "EventType": "EXIT"というイベントが記録されてジオフェンス領域から出たことが分かります。

24-exit-event-log

最後に

市販されている GPS トラッカーなどから AWS へ位置情報を送ることができれば、非常に簡単に位置情報アプリケーションが作成できそうな事が分かりました。
これまでは同じことをAWSサービスで実装する場合、下記記事のように設定がやや面倒な部分がありましたが、Amazon Location Service を使うと簡単に同様の仕組みが作れるようになりました。

他にも「キーワードマッチな周辺店舗の情報取得」などもできるようなので、活用用途はまだまだたくさんあると思います。Tokyoリージョンでも利用できますので、ぜひ活用してみてください!!