タグ: CoAP

  • CoAP Observe、更新通知の到着順と情報の新しさを分ける仕組み

    CoAP Observe、更新通知の到着順と情報の新しさを分ける仕組み

    室温を遠隔で表示するとき、一定間隔で「今は何度ですか」と問い合わせ続ける方法があります。CoAPのObserveは、最初に関心のある情報を登録し、その後の変化をサーバーから知らせてもらう仕組みです。ただし、届いた通知を順番に画面へ出すだけでは、遅れて届いた古い温度へ表示が戻ることがあります。

    簡単にまとめると?

    • CoAP Observeでは、GETで登録したリソースの更新を、同じTokenに対応する通知として受け取ります。
    • UDP上では通知の到着順が前後するため、Observeの番号を使って新しい状態を選びます。番号の大小だけでは、折り返しを扱えません。
    • 新旧の判定と、Max-Ageによる鮮度の期限は別です。途中の全状態が届く保証もありません。

    一度のGETから、更新の通知が続く

    CoAP(Constrained Application Protocol)は、計算能力や通信量に制約のある機器向けのアプリケーションプロトコルです。温度などの情報を「リソース」として扱い、その表現をGETで取得します。Observeは、この取得を継続的な観測へ広げる拡張です。本稿の通知順序の説明は、RFC 7641に基づくUDP上のCoAPを対象にします。[1、1.1–1.2、2]

    クライアントはGETにObserve: 0を付け、リソースの観測を登録します。サーバーからObserveオプションを含む成功応答が返れば、登録が成立したと分かります。Observeのない応答なら、通常のGETとして情報を取得しただけの場合があります。「温度が一度返った」と「更新を受け取る登録ができた」は分けて扱います。[1、2、3.1]

    その後の通知は、最初のGETに対する追加の応答です。通知に含まれるTokenは、その通知がどの要求に対応するかを識別します。一方、応答側のObserve値は、通知の新旧を見分けるための番号です。TokenとObserve値は、同じ数字の欄ではありません。[1、3.2]

    遅れて届いた通知で、表示を巻き戻さない

    次の図は説明用に作った受信例です。観測登録済みの一つの温度リソースについて、各通知が温度の表現を含み、途中で登録やTokenが変わらないものとします。最初の通知からの経過時間を使い、ネットワークの実測値ではありません。

    CoAP Observeの独自受信例。時刻0秒に番号100で21℃、3秒に102で23℃を採用。4秒に遅れて届く101の22℃は採用せず23℃を維持し、8秒に105の24℃を採用する。
    受信時刻の新しさだけでは、通知された状態の新しさは分かりません。番号101が遅れて届いても、表示を23℃から22℃へ戻さない受信例です。

    番号100の後に102を受け取ったら、表示を21℃から23℃へ更新します。その後に101が届いても、これは102より前の通知なので、最新の表現には採用しません。受け取った順にすべて上書きすると、すでに見えていた23℃を古い22℃で置き換えてしまいます。[1、3.4]

    ただし、番号が飛んだことから「何回分の温度測定を失ったか」は計算できません。Observeの番号は新旧の判定に使うもので、測定回数の通し番号とは限りません。また、通信の混雑などにより、中間状態の通知が省かれることもあります。Observeの目的は現在の状態へ近づくことであり、すべての変化の履歴を配ることとは異なります。[1、1.3、3.3.1、4.4]

    24ビットの番号は、最大値の先で折り返す

    UDP上の通知では、Observe値に増加する番号の下位24ビットを使います。表せる値は0から16,777,215までなので、その先では小さい値へ戻ります。受信した値を普通の整数として比べるだけでは、折り返した後の新しい通知を古いと判断してしまいます。[1、3.4]

    例えば、直前の値が16,777,214で、次に1が届いたとします。24ビットの範囲を一周することを織り込めば、前へ3進んだ関係です。短い受信間隔でこの二つを比べる場合、1を新しい通知として扱います。反対に、1の後へ16,777,214が届いた場合は、単純に「大きいから新しい」とはできません。

    この比較の土台がシリアル番号演算です。一周の半分より小さい前進を、新しい側として区別します。24ビットなら半周は8,388,608で、ちょうど半周離れた値は番号だけでは前後を決められません。RFC 7641の受信判定には、最も新しい通知の受信から128秒を超えた場合の条件もあります。短時間の番号比較だけを切り出して、常に使える規則にしないことが大切です。[1、3.4][2、3.2]

    新しい番号でも、いつまでも現在値とはいえない

    通知の順序を判定できても、その後に通信が途絶えれば、最後の温度が画面に残り続けます。ここで使うのがMax-Ageです。これは、その表現をどれだけの期間、新鮮な情報として扱えるかを示します。最後に採用した通知の年齢がMax-Ageを超えたら、その内容が現在のリソースの状態を表しているとは見なせません。[1、3.3.1][3、5.6.1]

    先ほどの例で、8秒時点に受け取った通知のMax-Ageを10秒とします。受信時の年齢を0として扱う直接通信の説明例では、18秒時点の年齢は10秒、19秒時点では11秒です。後者では、新しい通知が来ていないからといって24℃を「現在の室温」と表示し続ける根拠がありません。画面なら、最後の値とともに更新待ちの状態や最終受信時刻を示す設計が考えられます。

    用途を決める際には、「直近の温度を知りたい」のか、「一瞬の温度上昇も漏れなく記録したい」のかを分けます。後者では、保存場所、欠測の検出、再取得できる履歴などを別途設計する必要があります。到着順序を直す機能だけで、すべての出来事の記録まで保証されるわけではありません。

    なお、TCPなどの信頼性のあるトランスポート上のCoAPは、RFC 8323が別に規定しています。TCPは順序を保つため、成功通知のObserve値を受信側では無視する規則になっています。同じObserveという名前でも、UDP向けの番号比較をそのまま持ち込まないよう、実際のトランスポートを確かめます。[4、7.1]

    出典

    1. RFC 7641 — Observing Resources in the Constrained Application Protocol (CoAP)、K. Hartke、2015年9月。1.1–1.3、2、3.1–3.4、4.4、図1–2を参照。2026年10月26日JSTに公式情報ページでProposed Standard、RFC 8323による更新を確認。図と受信時刻・温度の例は独自作成。
    2. RFC 1982 — Serial Number Arithmetic、R. Elz、R. Bush、1996年8月。3.2の比較と半周の曖昧さ。
    3. RFC 7252 — The Constrained Application Protocol (CoAP)、Z. Shelbyほか、2014年6月。5.6.1の鮮度モデル。本稿は基礎となるUDP上の通信を対象とし、CoAPの全拡張を網羅しない。
    4. RFC 8323 — CoAP (Constrained Application Protocol) over TCP, TLS, and WebSockets、C. Bormannほか、2018年2月。7.1の通知順序に関する変更。