M5stickCのlwIPにTCP_QUICKACKを追加してみました
背景
mqttの通信実験を行ってる際に、
publishパケットとackパケットの数が違うので、
TCP_QUICKACK有効にしてpublishパケットとackパケットの数を合わせることで
応答確認をしやすくしようと思いました
しかし、ショックなことにlwIPにはTCP_QUICKACK設定がないことが
分かりました
せっかくの機会なので、lwIPの勉強を兼ねて自分で追加してみました
お願い
導入は自己責任でお願いします
1 TCP_QUICKACKとは
初期設定(TCP_QUICKACK無効)においては、必要な時にACKを返します。
TCP_QUICKACKを有効にすると、即ACKを返します。
-
TCP_QUICKACK有効時のメリット
TCPの受信ごとにACKを返すので応答速度をあげることが出来ます。 -
TCP_QUICKACK有効時のデメリット
TCPの受信ごとにACKを返すので通信量増加とTCPスタック負荷増となります。
wikipedia
https://ja.wikipedia.org/wiki/TCP%E9%81%85%E5%BB%B6ACK
2 lwIPとは
組込用途に適した軽量TCPスタックです。
M5stickCで採用されています。
wikipedia
https://ja.wikipedia.org/wiki/LwIP
公式ページ
http://savannah.nongnu.org/projects/lwip/
3 準備
3.1 platformIOの準備
platformIOで開発を進めますので導入は公式ドキュメントを参照願います
3.2 esp-idfの準備
- M5stickCなどのESP系の、OSやデバイスドライバなどをソースコードからビルドして開発するための開発環境がesp-idfです
- 検証時のplatformIOで採用していたEspressif32のバージョンはv3.2でした
- Espressif32のv3.2のesp-idfはv3.3系となります
- そのため、windowsにesp-idfのv3.3系の開発環境を構築します
今回導入するv3.3.5のドキュメントにしたがって進めます
https://docs.espressif.com/projects/esp-idf/en/v3.3.5/get-started/index.html
3.2.1 esp-idf-toolsのインストール
3.2.1.1 esp-idf-toolsをダウンロード
ダウンロード先から
esp-idf-tools-setup-online-2.9.exeをダウンロードします
3.2.2.2 ライセンス認証
3.2.2.3 インストール環境のチェック
3.2.2.4 esp-idfの取得
3.2.2.5 esp-idfのバージョン選択
3.2.2.6 esp-idfのインストール先の設定
3.2.2.7 開発環境の設定
私はeclipseを使わないので選択を外しています
3.2.2.8 インストール開始
しばらく待つと終わります
準備はこれで完了です
4 コードの変更内容
4.1 esp-idf
4.1.1 TCP_QUICKACKのdefineを追加します
変更ファイル
\esp-idf\components\lwip\lwip\src\include\lwip\socket.h
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */
#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */
#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl Use seconds for get/setsockopt */
#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt Use number of probes sent for get/setsockopt */
+ #define TCP_QUICKACK 0x06 /* set pcb->quickack get/setsockopt */
#endif /* LWIP_TCP */
4.1.2 quickack設定用の変数定義を追加します
変更ファイル
\esp-idf\components\lwip\lwip\src\include\lwip\tcp.h
/* KEEPALIVE counter */
u8_t keep_cnt_sent;
+
+ u32_t quickack;
+
#if LWIP_WND_SCALE
u8_t snd_scale;
u8_t rcv_scale;
#endif
4.1.3 quickack設定用の変数を初期化します
変更ファイル
\esp-idf\components\lwip\lwip\src\core\tcp.c
変更関数
tcp_alloc
#if LWIP_TCP_KEEPALIVE
pcb->keep_intvl = TCP_KEEPINTVL_DEFAULT;
pcb->keep_cnt = TCP_KEEPCNT_DEFAULT;
#endif /* LWIP_TCP_KEEPALIVE */
+
+ pcb->quickack = 0;
+
}
return pcb;
}
4.1.4 TCP_QUICKACKのオプション取得を追加します
変更ファイル
\esp-idf\components\lwip\lwip\src\api\socket.c
変更関数
lwip_getsockopt_impl
case TCP_KEEPALIVE:
*(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
break;
+
+ case TCP_QUICKACK:
+ *(int*)optval = sock->conn->pcb.tcp->quickack;
+ break;
+
#if LWIP_TCP_KEEPALIVE
case TCP_KEEPIDLE:
4.1.5 TCP_QUICKACKのオプション設定を追加します
変更ファイル
\esp-idf\components\lwip\lwip\src\api\socket.c
変更関数
lwip_setsockopt_impl
case TCP_KEEPALIVE:
sock->conn->pcb.tcp->keep_idle = (u32_t)(*(const int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n", s, sock->conn->pcb.tcp->keep_idle));
break;
+
+ case TCP_QUICKACK:
+ sock->conn->pcb.tcp->quickack = (u32_t)(*(const int*)optval);
+ break;
+
#if LWIP_TCP_KEEPALIVE
case TCP_KEEPIDLE:
4.1.6 quickack有効時の振る舞いを追加します
変更ファイル
\esp-idf\components\lwip\lwip\src\core\tcp_in.c
変更関数
tcp_receive
#endif /* TCP_QUEUE_OOSEQ */
-
- /* Acknowledge the segment(s). */
- tcp_ack(pcb);
+ if( pcb->quickack!= 0 ) {
+ tcp_ack_now(pcb);
+ } else {
+ /* Acknowledge the segment(s). */
+ tcp_ack(pcb);
+ }
+
#if LWIP_IPV6 && LWIP_ND6_TCP_REACHABILITY_HINTS
4.1.7 ビルドオプションの変更します
4.1.7.1 ESP-IDF 3.3 CMDのコマンドプロンプトを開きます
4.1.7.2 ビルドプロジェクトに移動します
cd example\get-start\hello-world
※例としてhello-worldを選んでいます
4.1.7.3 メニューを開きます
idf.py menuconfig
4.1.7.4 ビルドオプションを設定します
4.1.8 ビルドします
idf.py build
エラーがなければ完了です
4.2 実験用プロジェクト
4.2.1 TCP_QUICKACKのdefineを追加
変更ファイル
platformIOのインストール先\platformio\packages\framework-arduinoespressif32\tools\sdk\include\lwip\lwip\socket.h
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */
#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */
#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl Use seconds for get/setsockopt */
#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt Use number of probes sent for get/setsockopt */
+ #define TCP_QUICKACK 0x06 /* set pcb->quickack get/setsockopt */
#endif /* LWIP_TCP */
4.2.2 quickack設定用の変数定義を追加
変更ファイル
platformIOのインストール先platformio\packages\framework-arduinoespressif32\tools\sdk\include\lwip\lwip\tcp.h
/* KEEPALIVE counter */
u8_t keep_cnt_sent;
+
+ u32_t quickack;
+
#if LWIP_WND_SCALE
u8_t snd_scale;
u8_t rcv_scale;
#endif
4.2.3 ライブラリファイルを更新します
念のため、上書きする間にライブラリをバックアップしておくとよいかと思います
コピー元
esp-idf\examples\get-started\hello_world\build\esp-idf\lwip\liblwip.a
コピー先
platformio\packages\framework-arduinoespressif32\tools\sdk\lib\liblwip.a
5 使い方
設定値取得
httpsClient.getOption(TCP_QUICKACK,&getval);
設定値更新
setval = 1; /* 有効 */
httpsClient.setOption(TCP_QUICKACK,&setval);
setval = 0; /* 無効 */
httpsClient.setOption(TCP_QUICKACK,&setval);
6 サンプル
MQTTのsubscriberのプロジェクトにおいて
TCP_QUICKACK設定を切り替えています
#include <M5StickC.h>
#include <PubSubClient.h>
#include <WiFi.h>
#include <LovyanGFX.hpp>
#include <lwip/sockets.h>
// Wi-FiのSSID
const char *ssid = "****";
// Wi-Fiのパスワード
const char *password = "****";
// MQTTの接続先のIP
const char *endpoint = "192.168.0.22";
// MQTTのポート
const int port = 1883;
// デバイスID
const char *deviceID = "M5Stickc_1"; // デバイスIDは機器ごとにユニークにします
// メッセージを知らせるトピック
const char *pubTopic = "/pub/M5Stickc_1";
// メッセージを待つトピック
const char *subTopic = "/sub/M5Stickc_1";
////////////////////////////////////////////////////////////////////////////////
static LGFX lcd;
WiFiClient httpsClient;
PubSubClient mqttClient(httpsClient);
int qa = 0;
int setval = 1;
char subMessage[128];
void mqttCallback (char* topic, byte* payload, unsigned int length) {
int res;
int getval;
Serial.print("Received. topic=");
Serial.println(topic);
httpsClient.getOption(TCP_QUICKACK,&getval);
Serial.printf("get TCP_QUICKACK %d/%d\n",getval,qa);
for (int i=0; i < length; i++) {
subMessage[i] = (char)payload[i];
}
Serial.println(subMessage);
res = httpsClient.setOption(TCP_QUICKACK,&setval);
if (res != 0 ) {
Serial.printf("set TCP_QUICKACK error %d\n",res);
}
// ディスプレイへ受信内容を表示
lcd.setCursor(0,40);
lcd.printf("RX: %s", subMessage );
}
void connectMQTT() {
while (!mqttClient.connected()) {
if (mqttClient.connect(deviceID)) {
httpsClient.setNoDelay(true); // disable nagle
Serial.println("MQTT Connected.");
int qos = 0;
mqttClient.subscribe(pubTopic, qos);
Serial.println("Subscribed.");
} else {
Serial.printf("Failed. Error state=%d\n",mqttClient.state());
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
// Initialize the M5Stack object
M5.begin();
lcd.init(); // 初期化
// START
lcd.fillScreen(BLACK);
lcd.setCursor(10, 10);
lcd.setTextColor(WHITE);
lcd.setTextSize(1);
lcd.printf("START");
// Start WiFi
Serial.println("Connecting to ");
Serial.print(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print("*");
}
// WiFi Connected
Serial.println("\nWiFi Connected.");
lcd.setCursor(10, 40);
lcd.setTextColor(WHITE);
lcd.printf("WiFi Connected.");
mqttClient.setServer(endpoint, port);
mqttClient.setCallback(mqttCallback);
connectMQTT();
}
char pubMessage[128];
int count = 0;
void mqttLoop(void) {
if (!mqttClient.connected()) {
connectMQTT();
}
mqttClient.loop();
}
void loop() {
mqttLoop();
if(M5.BtnA.wasPressed() != 0 ) {
Serial.println("pressA");
lcd.println("pressA");
sprintf(pubMessage, "{\"count qa\": %d}", count++);
Serial.print("Publishing message to topic qa");
Serial.println(pubTopic);
Serial.println(pubMessage);
mqttClient.publish(pubTopic, pubMessage, 0, MQTTQOS0);
Serial.println("Published.");
}
if(M5.BtnB.wasPressed() != 0 ) {
setval ++;
setval %= 2;
Serial.printf("pressB %d\n",setval);
lcd.printf("pressB %d\n",setval);
}
M5.update();
delay(10);
}
7 結果
pubslishパケットとACKパケットの数が一致するか確認します
凡例
記号 | 説明 |
---|---|
T | 送信 |
TS | レスポンスがまとめられた送信 |
R??? | 送信???パケットのACKレスポンス |
- | 通信エラーパケット |
- TCP_QUICKACK無効
T 18個
R 12個
QUICKACK無効のため、6個のACKパケットを減らしています
No. | Time | Source | Destination | Protocol | Length | Sequence number | Acknowledgment Number | Info | |
---|---|---|---|---|---|---|---|---|---|
TS | 309 | 0 | 192.168.0.21 | 192.168.0.22 | MQTT | 60 | 1 | 1 | Ping Request |
T | 310 | 0.000260834 | 192.168.0.22 | 192.168.0.21 | MQTT | 56 | 1 | 3 | Ping Response |
R310 | 311 | 0.012788982 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 3 | 3 | 55272 > 1883 [ACK] Seq=3 Ack=3 Win=5700 Len=0 |
T | 527 | 9.395390509 | 192.168.0.22 | 192.168.0.21 | MQTT | 88 | 3 | 3 | Publish Message [/pub/M5Stickc_1] |
TS | 528 | 0.000193334 | 192.168.0.22 | 192.168.0.21 | MQTT | 122 | 37 | 3 | Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1] |
T | 529 | 0.000740001 | 192.168.0.22 | 192.168.0.21 | MQTT | 292 | 105 | 3 | Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1] |
R527 | 533 | 0.186260289 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 3 | 37 | 55272 > 1883 [ACK] Seq=3 Ack=37 Win=5666 Len=0 |
T | 539 | 0.248317435 | 192.168.0.22 | 192.168.0.21 | TCP | 360 | 37 | 3 | [TCP Retransmission] 1883 > 55272 [PSH, ACK] Seq=37 Ack=3 Win=64184 Len=306 |
R529 | 541 | 0.040337001 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 3 | 343 | 55272 > 1883 [ACK] Seq=3 Ack=343 Win=5360 Len=0 |
T | 676 | 4.413271966 | 192.168.0.22 | 192.168.0.21 | MQTT | 88 | 343 | 3 | Publish Message [/pub/M5Stickc_1] |
T | 680 | 0.033683863 | 192.168.0.22 | 192.168.0.21 | MQTT | 88 | 377 | 3 | Publish Message [/pub/M5Stickc_1] |
R676 | 690 | 0.069251585 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 3 | 377 | 55272 > 1883 [ACK] Seq=3 Ack=377 Win=5326 Len=0 |
T | 691 | 7.2812E-05 | 192.168.0.22 | 192.168.0.21 | MQTT | 224 | 411 | 3 | Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1] |
R680 | 692 | 0.007991421 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 3 | 411 | 55272 > 1883 [ACK] Seq=3 Ack=411 Win=5292 Len=0 |
T | 695 | 0.000345938 | 192.168.0.22 | 192.168.0.21 | MQTT | 88 | 581 | 3 | Publish Message [/pub/M5Stickc_1] |
R691 | 696 | 0.001326097 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 3 | 581 | 55272 > 1883 [ACK] Seq=3 Ack=581 Win=5122 Len=0 |
T | 700 | 0.008312879 | 192.168.0.22 | 192.168.0.21 | MQTT | 88 | 615 | 3 | Publish Message [/pub/M5Stickc_1] |
R695 | 701 | 0.002579849 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 3 | 615 | 55272 > 1883 [ACK] Seq=3 Ack=615 Win=5088 Len=0 |
R700 | 702 | 0.004276674 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 3 | 649 | 55272 > 1883 [ACK] Seq=3 Ack=649 Win=5054 Len=0 |
T | 705 | 0.009433663 | 192.168.0.22 | 192.168.0.21 | MQTT | 88 | 649 | 3 | Publish Message [/pub/M5Stickc_1] |
R705 | 710 | 0.159095029 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 3 | 683 | 55272 > 1883 [ACK] Seq=3 Ack=683 Win=5020 Len=0 |
TS | 715 | 0.421771862 | 192.168.0.21 | 192.168.0.22 | MQTT | 60 | 3 | 683 | Ping Request |
T | 716 | 0.000274323 | 192.168.0.22 | 192.168.0.21 | MQTT | 56 | 683 | 5 | Ping Response |
R716 | 719 | 0.062750375 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 5 | 685 | 55272 > 1883 [ACK] Seq=5 Ack=685 Win=5018 Len=0 |
TS | 820 | 4.443223995 | 192.168.0.22 | 192.168.0.21 | MQTT | 88 | 685 | 5 | Publish Message [/pub/M5Stickc_1] |
TS | 823 | 0.005977771 | 192.168.0.22 | 192.168.0.21 | MQTT | 88 | 719 | 5 | Publish Message [/pub/M5Stickc_1] |
TS | 824 | 0.000173073 | 192.168.0.22 | 192.168.0.21 | MQTT | 88 | 753 | 5 | Publish Message [/pub/M5Stickc_1] |
T | 825 | 0.000124115 | 192.168.0.22 | 192.168.0.21 | MQTT | 122 | 787 | 5 | Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1] |
- | 834 | 0.285642652 | 192.168.0.22 | 192.168.0.21 | TCP | 224 | 685 | 5 | [TCP Retransmission] 1883 > 55272 [PSH, ACK] Seq=685 Ack=5 Win=64182 Len=170 |
R825 | 836 | 0.134010607 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 5 | 855 | 55272 > 1883 [ACK] Seq=5 Ack=855 Win=4848 Len=0 |
T | 837 | 0.000119688 | 192.168.0.22 | 192.168.0.21 | MQTT | 224 | 855 | 5 | Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1] |
- | 839 | 0.103405551 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 5 | 855 | [TCP Dup ACK 836#1] 55272 > 1883 [ACK] Seq=5 Ack=855 Win=4848 Len=0 |
R837 | 840 | 0.000153907 | 192.168.0.21 | 192.168.0.22 | TCP | 60 | 5 | 1025 | 55272 > 1883 [ACK] Seq=5 Ack=1025 Win=4678 Len=0 |
- TCP_QUICKACK有効
T 20個
R 20個
TCPとACKパケットが同じなのでQUICKACKが効いていると思います
| | No. | Time | Source | Destination | Protocol | Length | Sequence number | Acknowledgment Number | Info
- | - | - | - | - | - | - | - | - | - |
| 372 | 0 | 192.168.0.21 | 192.168.0.22 |MQTT|60|1|1|Ping Request
T|373|0.00025849|192.168.0.22|192.168.0.21|MQTT|56|1|3|Ping Response
R373|374|0.009280068|192.168.0.21|192.168.0.22|TCP|60|3|3|55272 > 1883 [ACK] Seq=3 Ack=3 Win=4672 Len=0
T|732|11.823577702|192.168.0.22|192.168.0.21|MQTT|88|3|3|Publish Message [/pub/M5Stickc_1]
T|735|0.018673781|192.168.0.22|192.168.0.21|MQTT|88|37|3|Publish Message [/pub/M5Stickc_1]
R732|749|0.068378345|192.168.0.21|192.168.0.22|TCP|60|3|37|55272 > 1883 [ACK] Seq=3 Ack=37 Win=4638 Len=0
T|750|7.5469E-05|192.168.0.22|192.168.0.21|MQTT|224|71|3|Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1]
R735|751|0.000151615|192.168.0.21|192.168.0.22|TCP|60|3|71|55272 > 1883 [ACK] Seq=3 Ack=71 Win=4604 Len=0
R750|754|0.011953041|192.168.0.21|192.168.0.22|TCP|60|3|241|55272 > 1883 [ACK] Seq=3 Ack=241 Win=4434 Len=0
T|755|4.3333E-05|192.168.0.22|192.168.0.21|MQTT|88|241|3|Publish Message [/pub/M5Stickc_1]
R755|756|0.004809748|192.168.0.21|192.168.0.22|TCP|60|3|275|55272 > 1883 [ACK] Seq=3 Ack=275 Win=4400 Len=0
T|759|0.005588759|192.168.0.22|192.168.0.21|MQTT|88|275|3|Publish Message [/pub/M5Stickc_1]
R759|760|0.004332351|192.168.0.21|192.168.0.22|TCP|60|3|309|55272 > 1883 [ACK] Seq=3 Ack=309 Win=4366 Len=0
T|763|0.024022645|192.168.0.22|192.168.0.21|MQTT|88|309|3|Publish Message [/pub/M5Stickc_1]
R763|764|0.008477879|192.168.0.21|192.168.0.22|TCP|60|3|343|55272 > 1883 [ACK] Seq=3 Ack=343 Win=4332 Len=0
T|877|3.03367422|192.168.0.21|192.168.0.22|MQTT|60|3|343|Ping Request
T|878|0.000230417|192.168.0.22|192.168.0.21|MQTT|56|343|5|Ping Response
R877|879|0.004368966|192.168.0.21|192.168.0.22|TCP|60|5|345|55272 > 1883 [ACK] Seq=5 Ack=345 Win=4330 Len=0
T|975|2.106806607|192.168.0.22|192.168.0.21|MQTT|88|345|5|Publish Message [/pub/M5Stickc_1]
T|983|0.142087425|192.168.0.22|192.168.0.21|MQTT|88|379|5|Publish Message [/pub/M5Stickc_1]
R975|986|0.073340592|192.168.0.21|192.168.0.22|TCP|60|5|379|55272 > 1883 [ACK] Seq=5 Ack=379 Win=4296 Len=0
T|987|0.000123333|192.168.0.22|192.168.0.21|MQTT|326|413|5|Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1]
R983|988|0.000207657|192.168.0.21|192.168.0.22|TCP|60|5|413|55272 > 1883 [ACK] Seq=5 Ack=413 Win=4262 Len=0
T|989|0.002308858|192.168.0.21|192.168.0.22|TCP|60|5|413|[TCP Window Update] 55272 > 1883 [ACK] Seq=5 Ack=413 Win=5710 Len=0
R373|990|0.012468146|192.168.0.21|192.168.0.22|TCP|60|5|685|55272 > 1883 [ACK] Seq=5 Ack=685 Win=5438 Len=0
T|1130|4.794089045|192.168.0.22|192.168.0.21|MQTT|88|685|5|Publish Message [/pub/M5Stickc_1]
T|1133|0.015986068|192.168.0.22|192.168.0.21|MQTT|88|719|5|Publish Message [/pub/M5Stickc_1]
T|1136|0.014751431|192.168.0.22|192.168.0.21|MQTT|88|753|5|Publish Message [/pub/M5Stickc_1]
T|1139|0.015450859|192.168.0.22|192.168.0.21|MQTT|88|787|5|Publish Message [/pub/M5Stickc_1]
R1130|1149|0.065963547|192.168.0.21|192.168.0.22|TCP|60|5|719|55272 > 1883 [ACK] Seq=5 Ack=719 Win=5404 Len=0
T|1150|0.000087761|192.168.0.22|192.168.0.21|MQTT|190|821|5|Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1], Publish Message [/pub/M5Stickc_1]
R1133|1151|0.000747188|192.168.0.21|192.168.0.22|TCP|60|5|753|55272 > 1883 [ACK] Seq=5 Ack=753 Win=5370 Len=0
R1136|1152|0.001131096|192.168.0.21|192.168.0.22|TCP|60|5|787|55272 > 1883 [ACK] Seq=5 Ack=787 Win=5336 Len=0
R1139|1153|0.000174479|192.168.0.21|192.168.0.22|TCP|60|5|821|55272 > 1883 [ACK] Seq=5 Ack=821 Win=5302 Len=0
R1150|1154|0.002439536|192.168.0.21|192.168.0.22|TCP|60|5|957|55272 > 1883 [ACK] Seq=5 Ack=957 Win=5166 Len=0
T|1157|0.008647149|192.168.0.22|192.168.0.21|MQTT|88|957|5|Publish Message [/pub/M5Stickc_1]
R1157|1158|0.004542768|192.168.0.21|192.168.0.22|TCP|60|5|991|55272 > 1883 [ACK] Seq=5 Ack=991 Win=5132 Len=0
T|1161|0.005588031|192.168.0.22|192.168.0.21|MQTT|88|991|5|Publish Message [/pub/M5Stickc_1]
R1161|1162|0.005189383|192.168.0.21|192.168.0.22|TCP|60|5|1025|55272 > 1883 [ACK] Seq=5 Ack=1025 Win=5098 Len=0