センスウェイのLoRaWANサービスを使ってみる その4


ACK要求付きの下りデータ送信を試す前に、まずは前回の補足から。

その1
その2
その3

tx_sendを受信するタイミング

前回、

tx_sendはデータが「送られた」時ではなく、デバイスが「受信した」に送られてくることになります。

と書きましたが、これはClass Aのタイミングチャートを参照することで理解できます。LoRa Allianceが公開している資料から図を抜粋します。

ここで「Transmit」となっているのが「デバイスがデータを送信する時間」です。デバイスはデータ送信が完了すると、RxDelay1で定義されている待ち時間が経過した後にRX1の期間だけ受信待ち受けを行います。この間にデータが受信できなかった場合、RxDelay2後に再びRX2の期間待ち受けを行います。

これを下敷きにしてtx_sendのタイミングを考えてみましょう。

既に述べたとおり、アプリケーションからLoRaWANサーバに送られたデータは、デバイスに送られる前に次のデータが来た場合には削除(上書き)されます。デバイスからのデータを受信した後、LoRaWANサーバは上図で示したとおりのタイミングで最新のデータをデバイスに送ります。これが完了したのを受け、アプリケーション側にtx_sendが返されるということになります。

ACK付きデータ送信

さて、それでは本題であるACK要求付きのデータ送信を試してみましょう。

データを送ってみよう

前回同様にデータを送ってみます。ただし今回はACK要求付きなので、メッセージの中に"cnf": trueを追加しておきます。また、メッセージ同士の関連を確認するためのRefも追加します。

$ docker run --rm -it test/mosquitto-client mosquitto_pub -h mqtt.senseway.net -p 1883 -u <useryname> -P <password> -t lora/<useryname>/<devEUI>/tx -m '{"port":14,"data":"01","ref":"1","cnf":true}'  -d

同様にデバイス側からデータを送信します。

> lorawan tx ucnf 1 01
>> Ok
>> rx 14 01
>> tx_ok
>

先にアプリケーション側から送信したデータが受信できました。この時のLoRaWANサーバの応答を見ると、

lora/<useryname>/<devEUI>/rx {"gw":[{"date":"2018-04-24T12:20:00.684738Z","rssi":-59,"snr":9.8,"gwid":"<gwid>"}],"mod":{"fq":927.4,"cnt":71,"data":"01","mt":"ucnf","devEUI":"<devEUI>","dr":"2","port":1}}
lora/<useryname>/<devEUI>/tx_send {"cnt":26,"cnf":true,"devEUI":"<devEUI>","date":"2018-04-24T12:20:01.078871Z","ref":"1","port":14,"size":1}

となり、正常にtx_sendを受信できました。この時点でデバイスにデータが届いたことになります。さて、ACKはどうなったのでしょうか? もう一度デバイスからデータを送り、LoRaWANサーバの応答を見てみます。

lora/<useryname>/<devEUI>/rx {"gw":[{"date":"2018-04-24T12:23:32.401519Z","rssi":-65,"snr":10.5,"gwid":"<gwid>"}],"mod":{"fq":927.4,"cnt":72,"data":"01","mt":"ucnf","devEUI":"<devEUI>","dr":"2","port":1}}
lora/<useryname>/<devEUI>/ack {"date":"2018-04-24T12:23:32.717703Z","ref":"1","devEUI":"<devEUI>"}

今度はACKが届きました。つまり、ACKはtx_sendを返したもうひとつ先のデータ送信のタイミングで送り返されてくることが分かりました。

重送データはどうなるか

さて、これまでの検討でtx_send受信前にデータを送信すると、それ以前のデータが削除されて最新のものだけが届くことが分かっています。それではACKが届く前ではどうでしょうか?

まずアプリケーションからデータを送ります。

$ docker run --rm -it test/mosquitto-client mosquitto_pub -h mqtt.senseway.net -p 1883 -u <useryname> -P <password> -t lora/<useryname>/<devEUI>/tx -m '{"port":14,"data":"02","ref":"2","cnf":true}'  -d

続いてデバイスからデータを送ります。

> lorawan tx ucnf 1 01
>> Ok
>> rx 14 02
>> tx_ok

LoRaWANサーバの応答は次の通り。

lora/<useryname>/<devEUI>/rx {"gw":[{"date":"2018-04-24T12:33:23.364639Z","rssi":-65,"snr":11.3,"gwid":"<gwid>"}],"mod":{"fq":927.8,"cnt":75,"data":"01","mt":"ucnf","devEUI":"<devEUI>","dr":"2","port":1}}
lora/<useryname>/<devEUI>/tx_send {"cnt":27,"cnf":true,"devEUI":"<devEUI>","date":"2018-04-24T12:33:23.766234Z","ref":"2","port":14,"size":1}

ここまでは想定通りの動作ですね。これでtx_sendの受信後、かつACKの受信前という状況になったので、アプリケーションから次のデータを送ってみます。

$ docker run --rm -it test/mosquitto-client mosquitto_pub -h mqtt.senseway.net -p 1883 -u <useryname> -P <password> -t lora/<useryname>/<devEUI>/tx -m '{"port":14,"data":"03","ref":"3","cnf":true}'  -d

すると今度は、LoRaWANサーバからこれまでに無い応答が返ってきました。

lora/<useryname>/<devEUI>/error {"date":"2018-04-24T12:35:54.239736Z","type":"DownlinkQueue","devEUI":"<devEUI>","error":"Currently could not update downlink queue item because waiting for ConfirmedDown ACK response. REF=2"}

tx_sendの受信後、かつACKの受信前に次のデータを送るとDownlinkQueueエラー(下りの待ち行列あふれ)になります。理由は「REF=2のデータに対するACKを受信していないから」となっており、状況と完全に一致しています。

確認のため、再度デバイスからデータを送ってACKが返ってくるのを確認した後、同じデータをもう一度アプリケーションから送ってみます。

$ docker run --rm -it test/mosquitto-client mosquitto_pub -h mqtt.senseway.net -p 1883 -u <useryname> -P <password> -t lora/<useryname>/<devEUI>/tx -m '{"port":14,"data":"03","ref":"3","cnf":true}'  -d

LoRaWANサーバの応答は

lora/<useryname>/<devEUI>/tx {"port":14,"data":"03","ref":"3","cnf":true}

となり、今度は正常にデータが送られたことが確認できました。

まとめ

  • ACK要求付きでデータを送った場合、ACKが返ってくるのは次々回のデバイス側データ送信のタイミングになる
  • tx_send受信後、ACK受信前に次のデータを送った場合、DownlinkQueueエラーとなりデータ送信に失敗する

図にするとこんな感じでしょうか。

この後は

最後に残ったのはデバイス側からのACK要求付きデータ送信ですね。これまた話がややこしそうです。