0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LoRaWAN標準実装の時刻同期コマンド(DeviceTimeReq)について

Posted at

先にざっくりまとめ

  • LoRaWAN 1.0.3から標準定義された DeviceTimeReqDeviceTimeAns を使うことによって、端末側の時刻同期が簡単に可能
  • NTPのように往復時間(RTT)を都度計測するような複雑な仕組みではないが、プロトコルの仕組み上、Downlinkの通信遅延(レイテンシ)の影響を受けずに正確な時刻同期が可能
    • 実装がNTPに比べて非常に楽
    • 我々の用途としては十分過ぎる精度が出る
  • ただし GPS準拠の時間 であるため、以下の考慮が必要
    • うるう秒(Leap Seconds) の減算補正が必要(UTCが欲しい場合)
    • msレベルで合わせるには、1/256秒単位の補数計算が必要

DeviceTimeReq / DeviceTimeAns とは?

LoRaWAN デバイスがネットワークサーバ(NS)に対して 現在時刻を問い合わせるための、LoRaWAN 1.0.3から標準定義されたMAC コマンド。

  • ノード →(DeviceTimeReq)→ NS (Uplink)
  • NS →(DeviceTimeAns)→ ノード (Downlink)

返される時刻は GPS時間(GPS Epoch 時刻)と、秒以下の補正値(Fractional Second) になる。
仕様上は±1秒以内の精度とされているが、実装を工夫すればさらに高精度にできる。

コマンド仕様

Uplink/Downlink 共に、Command ID (CID) は 0x0D を使用する。

■ DeviceTimeReq (CID: 0x0D)

  • コマンド自体に payload はない
  • 1 byte の MAC コマンド ID をただ投げるだけ
    • これが標準で定義された予約コマンドになっているので、サポートされたLoRa Network Server(LNS)は DeviceTimeAns を自動的に返してくれる
0x0D
  • ペイロードが空で非常に軽いので通信が通りやすく、相対的にバッテリーにも優しい

■ DeviceTimeAns (CID: 0x0D)

  • ネットワークサーバから返るデータは CID(1byte) + ペイロード(5byte)
Byte 内容 説明
0-3 Time (GPS Epoch) 4-byte UInt32 (Little Endianに注意)
4 Fractional Second 1-byte(1/256 秒単位)

⚠️ 注意点

💡 GPS Epoch = 1980/01/06 00:00:00

1. うるう秒 (Leap Seconds) の考慮

DeviceTimeAns で返ってくる GPS 時刻は以下の仕様になっている。

  • うるう秒を含まない
  • 2025年現在、UTC とは 18 秒差
    • ※この差分は将来的に増減する可能性があるため、厳密な運用の場合は設定値として外から持たせる設計が望ましい

そのため、ノード側で UTC(協定世界時)扱いたい場合は、以下のように補正を掛ける必要がある。

UTC = GPS - 18秒(現在のうるう秒)

2. 時刻のアンカーポイント

DeviceTimeAns で返ってくる時刻は一般的イメージと違って 「サーバが応答パケットを作った時刻」ではない。
「DeviceTimeReq を含んだ Uplink の送信が完了した瞬間」 の時刻が格納されている。

そのため、Downlinkが届くまでに数秒のラグがあっても、端末側では「送信完了割り込み」のタイミングさえ覚えておけば、計算によって遅延をキャンセルして正確に同期できる。

実装イメージ

返ってくる値はあくまで秒単位のものであるため、最大 0.999…秒ズレうる。
そこで Fractional Second (Byte 4) を使うことで、約4ms単位(1/256秒)までズレを修正することができる。

以下は実装のロジック例。

// 1. アップリンク送信完了割り込み(TxDone)で、その瞬間のローカル時刻を抑えておく
t_local_tx_done = get_current_local_time_ms();

~ 数秒後、Downlinkで DeviceTimeAns を受信 ~

// 2. DeviceTimeAnsのパース
// GPS時間は 1980/1/6 起点。Fractional Secondは 1/256秒単位。
double t_net_gps_sec = device_time_ans.Seconds + (device_time_ans.Frac / 256.0);

// 3. UTCへの変換(うるう秒補正:2025年時点は -18秒)
double t_net_utc_sec = t_net_gps_sec - 18.0;

// 4. オフセットの計算
// 「サーバーが計測した送信完了時刻」と「端末が記録した送信完了時刻」の差分をとる
double offset_sec = t_net_utc_sec - (t_local_tx_done / 1000.0);

// 5. 現在時刻の確定
// 現在のローカル時刻にオフセットを足せば、高精度な現在時刻(UTC)になる
current_utc_time = get_current_local_time_ms() / 1000.0 + offset_sec;

注意

  • LoRaWAN v1.0.3以上でしか使えないが、それ以外にもLNSがサポートしているかどうかというのもある
    • 少なくとも The Things Network や AWS IoT Core は対応しているので実用上はまず大丈夫だと思うが、万が一に備えてLNS側を要確認

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?