👏

AirTagを華麗に使いこなしてみせたかった

2024/09/20に公開

TL;DR

  • AirTagの持つログの取り方をまとめています。
  • ログからはiPhone〜AirTagの距離や角度情報等を取得できますが、本記事では距離の正確性のみ把握することができました。
  • AirTagのログの活用は十分にできなかったため、AirTag有識者の方がいらっしゃれば、ぜひコメントいただければと思います。

モチベーション・想定読者

皆さんご存知のAirTag、便利ですよね。使い始めるのは簡単なのに、取り付けた物の追跡能力はとても正確です。時々忘れ物をしてしまう自分にとって、AirTagは「忘れてもなんとかなる」と思わせてくれる救世主のような存在でした。
ところが、しばらく経つと「忘れない限りありがたみを感じることがない」ガジェットとなってしまうことに気づきます。当たり前ですが、忘れないことが一番なので、この状態が望ましい姿なのです。一方で、一回も役に立つ機会がないと、「なんとなくもったいない」精神が体を蝕んだので、試しに手を動かしてみることにしました。
本記事は、なんとか緊急時のお助けガジェット・お守り以上の使い道を探ってみたい、そういったモチベーションから始まった調査の記録になります。「AirTagで何ができそうなの?」「制約はないの?」という疑問を持つような読者の方向けに、調べた内容を共有できればと思います。

実行環境

  • Mac
    • チップ: Apple M2
    • macOS: Ventura
  • iPhone
    • 機種: iPhone 13 Pro
    • iOSバージョン: 17.6.1

AirTagのログが取得できる状態にする

AirTagは、それ単体でログを保持することはありません。接続したiPhone経由から、AirTagのログを取得する必要があります。手順は下記の通りです。

  1. iPhone側で、AirTagのデータを送信するための準備をする
    • Apple Developerのプロファイルページでダウンロード(画像左)
    • 設定から「VPNとデバイス管理」を開き、AirTags Logging Profileを選択してインストールする(選択後の画面: 画像中央、インストール後の画面: 画像右)
  2. PC側で、ログを受け取るための準備をする
    • iOSデバイスと通信するためのライブラリlibimobiledeviceをインストールします
      brew install libimobiledevice
    • MacとiPhoneをLightningケーブルで繋ぎ、データが送受できる状態にします。
    • idevicepair pairを実行すると、接続したiphoneをペアリングします。(下記のようなSUCCESSのメッセージが出れば成功)
      $ idevicepair pair             
      SUCCESS: Paired with device XXXXXXXX-XXXXXXXXXXXXXXXX
      

この辺りは、先人様の記事を参考にさせていただきました。びっくりするくらいAirTag関連の記事ってないんですね・・・

ログの取得

ペアリング後、FindMy(探す)アプリを起動し、任意のAirTagを探すとAirTagのログをMac側に出力できます。

$ idevicesyslog -u $(idevice_id)

これを実行すると、取得したい対象以外のログも大量に出力されてしまうため、適宜フィルタリングの上でログを取得する必要があります。今回利用しているライブラリでは、idevicesyslogコマンドのpオプションで、指定した文字列を含むログのみ出力させることができます。

$ idevicesyslog -u $(idevice_id) -p nearbyd
# 出力結果を抜粋
nearbyd(CoreLocation)[118] <Notice>:
{"msg":"#CLLocationManager invoking #delegate",
"self":"XXXXXXXXX", "delegate":"XXXXXXXXXX",
"selector":"locationManager:didUpdateLocations:",
"location":
{"floor":XXXXX,"lifespan":22.5,"rawLat":XXXXX,
"integrity":75,"referenceFrame":"WGS84","lon":XXXXXX,
"speed":-1,"type":"XXXX","altitude":XXXXXX,"rawCourse":-1,
"confidence":69,"suitability":"Any","ellipsoidalAltitude":XXXXXX,
"timestamp":XXXXXXXX,"rawReferenceFrame":"WGS84",
"lat":XXXXXXXXX,"verticalAccuracy":8.7947015762329102,
"rawLon":XXXXXX,"horizontalAccuracy":35,
"speedAccuracy":-1,"courseAccuracy":-1,"fromSimulationController":false,
"course":-1},
"eventType":"kCLConnectionMessageLocation"}

最初は、nearbydでフィルタリングする対象の全てが、AirTagから送信されるログで、収集対象であると考えていました。上記のログなどは、緯度(lat)や経度(lon)を持っており、これが分かればAirTagの正確な動きが分かる!と推測したのです。
結論として、こちらのログはAirTagのログではありません。PCとの接続時から流れており、内容を見る限りiPhoneの位置情報関連のログかと思います。
目的とするAirTagのログは、FindMyアプリを起動してから流れるログとなります。

idevicesyslog -u $(idevice_id) -p nearbyd -m "[Solution Provider] Range Result"
# 一部抜粋
[Solution Provider] Range Result (Part 1 of 2):
{
	'ticket id': XX,
	'r1 sess id': X,
	'r1 cycle_idx': X,
	'r1 mac_addr': XXXXXXXXXXXX,
	'mach abs time (sec)': 271994,
	'mach cont time (sec)': 849595.557283,
	'r1 timestamp (sec)': 849579,
	'r1 sess status': SUCCESS,
	'r1 sess type': PointToPoint,
	'r1 winning_tx_antenna_mask': 0x04,
	'r1 UWB channel': CHANNEL9,
	'r1 Band select': N/A,
	'r1 NB channel': N/A,
	'r1 range (m)': 0.701437,
	'ME range unc (m)': 0.200000,
	'r1 azimuth PDOA (deg)': invalid,
	'r1 elevation PDOA (deg)': invalid,
	'r1 SOI RSSI (dBm)': -80,
	'r1 anchor time offset raw (r1 ticks)': 230151,
	'r1 anchor time offset (ps)': 5.99352e+09,
	'r1 AOA first path SNR - center (dB)': invalid,
	'r1 AOA first path SNR - vertical (dB)': invalid,
	'r1 AOA first path SNR - horizontal (dB)': invalid,
	'r1 carrier freq offset (ppb)': 304.119,
	'r1 AOA first path index - center (dB)': invalid,
	'r1 AOA first path index - vertical (dB)': invalid,
	'r1 AOA first path index - horizontal (dB)': invalid,
}
...
[Solution Provider] Range Result (Part 2 of 2):
{
	'ticket id': XX,
	'r1 sess id': X,
	'r1 cycle_idx': X,
	'r1 mac_addr': XXXXXXXXXXXX,
	'r1 SOI RSSI 2 (dBm)': invalid,
	'r1 OC SOI RSSI 2 (dBm)': invalid,
	'r1 mms val status':  N/A,
	'r1 nb demod chain: ':  N/A,
	'r1 nb rx0 elna hg: ':  N/A,
	'r1 nb rx1 elna hg: ':  N/A,
	'r1 nb tx antenna: ':  N/A,
	'r1 cycle skipping':  N/A,
	'toa peak snr (dB)':N/A,
	'toa peak index high res':N/A,
	'toa peak signal level high res (dB)':N/A,
}

FindMyのアプリ画面では、AirTagがどこにあるかを距離(m)で表示してくれるのですが、その値と同じ情報がr1 range (m)に格納されているため、この情報を取れば良さそうです。
距離だけだと、ユースケースが限定的になりそうなので、他に使えそうな情報がないか探ります。結果、使えそうな情報は下記の通りになります。

  • r1 azimuth PDOA (deg): 恐らく方位角?
  • r1 elevation PDOA (deg): 恐らく高さの角度?

距離と水平方向と垂直方向のなす角さえ分かれば、iPhoneを基準として座標を明らかにできるので、色々なことに使えるのでは・・・?という見込みを立てました。

余談ですが、得られるログは2つのパートに分かれています([Solution Provider] Range Result (Part X of 2))。ですが、有効な値が入っているのがPart 1 of 2の方であるため、基本的にはこちらを文字列の決め打ちでフィルタするのが良さそうです。

ログの加工

得られたログは、iPhoneを接続している間、常に出力されます。何かに使うにしても、まずは出力された生のログを加工し、必要な情報だけ取り出せている状態を目指します。
加工するために、一度ログをファイルに出力し、必要な情報をpandasのDataFrameに格納して、解析をしてみます。詳細な加工のロジックについてはGitHubに実際のnotebookを置いたので、見ていただければと思います。
有効な値が入っていない行を除き、加工したログは下記の通りです。

range azimuth elevation pos_x pos_y pos_z
1.068970 335.0 330.0 -0.967309 -0.129191 -0.436257
0.969581 187.0 98.0 0.792119 0.554367 0.072880
1.183980 239.0 205.0 -0.195950 -0.200341 1.150337
1.122720 260.0 245.0 0.766337 -0.033915 -0.819804
1.109810 277.0 245.0 0.569889 -0.025221 0.951981

azimuthelevationは、-180~180度の範囲で表記されるため、0~360度の範囲に直しています。
唐突に出てきたpos_(x,y,z)は、3次元極座標の考え方をもとに、素直にrange(iPhoneからの距離)に対して、azimuth(x軸とのなす角)とelevation(z軸とのなす角)を踏まえた座標を出した結果を格納しています。

これらを元に、一定時間FindMyを起動している間、AirTagをゆっくり水平に動かしてみたログを元に、3次元に動きを描画してみます。

あれ・・・?どこかで実装ミスした・・・?
と思いながら改めてログを見てみると、

range azimuth elevation pos_x pos_y pos_z
1.068970 335.0 330.0 -0.967309 -0.129191 -0.436257
0.969581 187.0 98.0 0.792119 0.554367 0.072880

水平に移動しているはずなのに、そもそもログの時点で、いきなり反転しているような挙動になっている・・・!

距離に関してはイメージと合う挙動なので、取得した値に不具合があったのか、想定していた値ではない値(方位角などではない)だったのでしょうか・・・
確かに2回に1回はinvalid(有効ではない値)が格納されていたので怪しさはありましたが、他にそれらしき情報も無いので、結局有効に使えるのはiPhoneからAirTagまでの直線距離のみという結果になりました。
どなたか、AirTagにお詳しい有識者の方でこのあたりの仕様をご存知の方がいらっしゃれば、ご教示いただければ嬉しいです。

まとめ

長くなってしまいましたが、以上がAirTagの使い道を模索しようと足掻いた跡となります。現状の私のアプローチでは、iPhoneからAirTagの距離情報だけ活用できそうである、という結論となってしまいました。

もし有益な情報を得ようと閲覧いただいた方がいらっしゃれば、肩透かしのような記事で申し訳ありません。勇んで触り始め、空回りしたこの足跡を少しでも楽しんでくださる方がいらっしゃれば幸いです。
いつか上手いこと多くの情報をAirTagから取れるようになったら、もっと遊んでみようと思います。

Discussion