この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは。CX事業本部Delivery部のakkyです。 re:Invent期間中ということでさまざまな新サービスが発表されていますが、今まで私がご紹介しているIoT CoreではDevice Locationという機能が発表されました。
詳細は、以下の記事をご覧ください。
[アップデート]AWS IoT Core が新しい Device Location 機能を発表しました
Device Locationとひとまとめにされていますが、大きく分けて以下の2つの機能があります。
- デバイスの周囲のWi-Fiスキャン結果、LTEの基地局の情報、IPアドレスから実際の経緯度(座標)を得る機能。いわゆるジオロケーション。 (GetPositionEstimate API)
- 座標データをAmazon Location Serviceへ送信する機能 (IoT Coreルール)
なお、この2つの機能は連携しているわけではなく、それぞれ別の処理として実行する必要があります。つまり、GetPositionEstimateは単体でジオロケーションAPIとして使うことができます。
今回はこのうち、1のGetPositionEstimate APIを使って、IPアドレスとWi-Fiからジオロケーションをしてみました。
実験環境
マネジメントコンソールから使用する場合には、特にソフトウェアのインストールは必要ありません。
AWS IoT Coreを開き、Device Locationを開くと、以下のような入力欄が現れますので、JSONで記述したクエリを入力して実験してください。「解決」をクリックすると、結果が表示されます。
AWS CLIでGetPositionEstimateコマンドを使用する場合は、最新バージョンを使用してください。 自分の場合は、あらかじめインストールしてあったaws-cli/2.7.21では使用できず、aws-cli/2.9.2に更新する必要がありました。
IPアドレスによるジオコーディング
マネジメントコンソールの場合は、以下のJSONを入力して、解決をクリックしてください。192.0.2.1の部分は、ご自分のIPアドレスに置き換えてください。(例のままでは解決できません。)
{
"Ip": {
"IpAddress": "192.0.2.1"
}
}
以下のような結果が表示されます。IPアドレスからなので、大まかな地域レベルではあっているかな?という精度です。
結果のJSONはGeoJSONという形式です。
{
"coordinates": [
139.***,
35.***
],
"type": "Point",
"properties": {
"country": "Japan",
"city": "***-ku",
"postalCode": "***-****",
"horizontalAccuracy": **,
"horizontalConfidenceLevel": 0.**,
"state": "Tokyo",
"timestamp": "2022-11-29T08:46:52.195Z"
}
}
経緯度はcoordinatesに入っています。結果を可視化するにはGoogle Mapsを使うのが手軽ですが、検索する際には、coordinatesに入っている結果と順番を逆にして入れる必要があります。つまり、この例では「35.xxx,139.xxx」と検索ボックスに入力してください。
また、AWS CLIでは以下のように実行すると、同じ結果がJSONファイルで得られます。
$ aws iotwireless get-position-estimate --ip IpAddress=192.0.2.1 outfile.json
Wi-Fiによるジオコーディング
Wi-Fiで周囲のAPをスキャンし、その結果から位置を推測する方法です。 ESP32などを使用する際にはこの方法が手軽だと思います。
今回はWindows 10のPCを使用して、Pythonのwin32wifiというPIPパッケージを使い、Wi-Fiの状況を取得しました。 なお、実行時にWin32Wifi.pyの105行目でエラーが出た場合には、この行をコメントアウトしてください。
以下のようなスクリプトを作成しました。
from win32wifi.Win32Wifi import getWirelessInterfaces
from win32wifi.Win32Wifi import getWirelessNetworkBssList
import time
import json
macs = []
ifaces = getWirelessInterfaces()
for iface in ifaces:
print(iface)
guid = iface.guid
bsss = getWirelessNetworkBssList(iface)
for bss in bsss:
macs.append({"MacAddress":bss.bssid, "Rss":bss.rssi})
print()
inputjson = { "Timestamp": int(time.time()), "WiFiAccessPoints": macs}
outputjson = json.dumps(inputjson)
print(outputjson)
実行すると、以下のような出力を得られます。
{
"Timestamp": 1669713742,
"WiFiAccessPoints": [
{
"MacAddress": "XX:XX:XX:XX:XX:XX",
"Rss": -**
},
{
"MacAddress": "XX:XX:XX:XX:XX:XX",
"Rss": -**
},
...
]
}
この結果を解決すると、そこそこ正確な結果を得ることができました。お見せできないのですが、誤差100mくらいでしょうか。かなり正確な印象です。
なお、与えるクエリ―によっては実行がエラーになってしまうことがありました。与えるアクセスポイントを減らすと結果が返ってくるようになったので、どうやらデータベースにないMACアドレスを与えるとダメな場合があるようです。
まとめ
AWS IoT Coreに追加されたDevice Locationを使ってジオロケーションを使ってみました。GoogleやMLSなど、他のサービスもありますが、AWSで完結できるようになったのが便利ですね。
IoT Coreのルールとも組み合わせた使用方法も検証したいと思います。