PostmanのMQTTサポート〜データ視覚化のあれこれ〜

## はじめに

2023年9月15日、PostmanはMQTTをサポートするようになりました。

https://blog.postman.com/postman-supports-mqtt-apis/

基本の使い方の[ドキュメント](https://learning.postman.com/docs/sending-requests/mqtt-client/mqtt-client-overview/)は用意されていますが、今回はデータの視覚化(Visualization)に着目したいと思います。

> Real-time data visualization
> 
> One of the prominent features introduced in our Postman’s MQTT support is the ability to view the telemetry data in a more readable fashion with visualization. As you receive data, you can see visualizations on your subscribed topics. No additional configuration is needed beyond subscribing to topics. 

*DeepL訳*
> *リアルタイムのデータ可視化*
> 
> *PostmanのMQTTサポートに導入された顕著な機能の1つは、遠隔測定データを視覚化によってより読みやすく表示する機能です。データを受信すると、サブスクライブしたトピックのビジュアライゼーションを見ることができます。トピックを購読するだけで、追加の設定は必要ありません。*

トピック、メッセージによって、どういう風に視覚化して表現するか、実験も兼ねて調べていきます。

<br>

**本記事が扱わないこと**
* Postmanの利用方法
* データの視覚化(Visualization)の表示方法
* MQTTの送受信方法

## データの視覚化？

説明より、直接見た方が早いと思います。

Postmanで下記メッセージを受信した際、

> {"name":"sensor1","temperature":14}
> {"name":"sensor1","temperature":1}
> {"name":"sensor1","temperature":8}
> {"name":"sensor1","temperature":2}
> {"name":"sensor1","temperature":14}
> {"name":"sensor1","temperature":2}
> {"name":"sensor1","temperature":11}
> {"name":"sensor1","temperature":10}
> {"name":"sensor1","temperature":7}

設定不要で`Visualization`タブから`temperature`グラフを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/f67c7f94-9dc1-36d6-443a-6c2b4b6f653d.png)

縦軸は数値で、データの範囲に応じて自動的に調節してくれる模様です。
横軸は時間で、受信時間の間隔を距離で表します。新しいデータを受信するたびに、右側に追加していきます。

マーカーにマウスオーバーすると受信時間と数値を確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/81ee80b3-a832-09a4-982f-657bd4a2cf48.png)

なお、`name`のグラフは作成されません。おそらく数値でない項目は排除されます。

折れ線グラフのほか、棒グラフに切り替えることも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/113d8fba-8f59-f5cd-d3f3-791b5508bbac.png)

:::note warn
表示モードが増えました。詳細は[更新(2023/12/16)](#更新20231216)をご参照ください。
:::

以降、検証のグラフは一定間隔で受信した10回分のデータから生成します。

## JSON

### 1トピック・1階層・1数値プロパティ

<table>
  <thead>
    <tr>
      <th>トピック1</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room1</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>{"name":"sensor1","temperature":<code>$整数</code>}</td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        {"name":"sensor1","temperature":8}<br>
        {"name":"sensor1","temperature":0}<br>
        {"name":"sensor1","temperature":11}<br>
    </td>
  </tr>
</table>

#### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/822b2a8d-f761-f0c5-c8aa-101ee29cafce.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/311d8ca5-6d90-d96b-0cc2-00a002d7a6f4.png)

**一言**
すでに前節で紹介済みだが、改めて記載した。


### 1トピック・1階層・1数値プロパティ（小数・負数あり）

<table>
  <thead>
    <tr>
      <th>トピック1</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room1</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>{"name":"sensor1","temperature":<code>$小数(小数点以下2桁)</code>}</td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        {"name":"sensor1","score":0.2}<br>
        {"name":"sensor1","score":-0.27}<br>
        {"name":"sensor1","score":1.01}<br>
    </td>
  </tr>
</table>

#### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/86375103-8453-ceee-8103-a8acb3a2b2e7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/cd28871d-d298-c6f5-1498-28d3f34f1462.png)

**一言**
縦軸は小数点以下1桁までの表示。折れ線のマーカー/縦棒の高さは縦軸とピッタリではなく、間をうまく表現している。


### 1トピック・1階層・2数値プロパティ

<table>
  <thead>
    <tr>
      <th>トピック1</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room1</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>{"name":"sensor1","temperature":<code>$整数</code>,"humidity":<code>$整数</code>}</td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        {"name":"sensor1","temperature":7,"humidity":81}<br>
        {"name":"sensor1","temperature":12,"humidity":82}<br>
        {"name":"sensor1","temperature":0,"humidity":87}<br>
    </td>
  </tr>
</table>

#### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/506db929-f9cb-80ad-5a13-4fa9df7516e6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/c0aee399-6327-cc6e-ac93-02a38006053b.png)

**一言**
同じグラフでの複数の折れ線/縦棒をサポート。
グラフ種類の混合は可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/859fe6c8-7758-325a-7003-94b44e726cc7.png)

:::note warn
グラフ種類の混合ができなくなりました。詳細は[更新(2023/12/16)](#更新20231216)をご参照ください。
:::


### 1トピック・1階層・2数値プロパティ（異なるキー）

<table>
  <thead>
    <tr>
      <th>トピック1</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room1</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>
      {"name":"sensor1","temperature":<code>$整数</code>,"humidity":<code>$整数</code>}<br>
      {"name":"sensor2","temperature":<code>$整数</code>,"humidity":<code>$整数</code>}<br>
    </td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        {"name":"sensor1","temperature":1,"humidity":86}<br>
        {"name":"sensor2","temperature":3,"humidity":74}<br>
        {"name":"sensor1","temperature":6,"humidity":77}<br>
        {"name":"sensor2","temperature":12,"humidity":61}<br>
    </td>
  </tr>
</table>

#### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/8330996d-41ee-1d1b-27f1-4a1eb8c95126.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/22365f0a-3aaa-7706-73c4-223f717457d6.png)

**一言**
思っていたと違う…`name`が違くても同じプロパティは同じデータとしてカウントされるようです。
やはり非数は予め除外されている？
この使い方はわりとあり得るケースだと思うが…？


### 2トピック・1階層・2数値プロパティ

<table>
  <thead>
    <tr>
      <th>トピック1</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room1</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>{"name":"sensor1","temperature":<code>$整数</code>,"humidity":<code>$整数</code>}</td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        {"name":"sensor1","temperature":7,"humidity":81}<br>
        {"name":"sensor1","temperature":12,"humidity":82}<br>
        {"name":"sensor1","temperature":0,"humidity":87}<br>
    </td>
  </tr>
</table>

<table>
  <thead>
    <tr>
      <th>トピック2</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room2</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>{"name":"sensor2","temperature":<code>$整数</code>,"humidity":<code>$整数</code>}</td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        {"name":"sensor2","temperature":13,"humidity":85}<br>
        {"name":"sensor2","temperature":9,"humidity":64}<br>
        {"name":"sensor2","temperature":5,"humidity":81}<br>
    </td>
  </tr>
</table>

結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/4d90051a-f4d2-d212-1e57-2309e0871fc8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/419259e1-bede-62b1-1326-22d98e4cb3a3.png)

**一言**
トピックを分けたら比較できた！トピックが違う場合、二つのグラフとして分けられる。


### 1トピック・多階層・2数値プロパティ

<table>
  <thead>
    <tr>
      <th>トピック1</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room1</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>{"sensor1":{"temperature":<code>$整数</code>,"humidity":<code>$整数</code>},"sensor2":{"temperature":<code>$整数</code>,"humidity":<code>$整数</code>}}</td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        {"sensor1":{"temperature":12,"humidity":80},"sensor2":{"temperature":10,"humidity":67}}<br>
        {"sensor1":{"temperature":5,"humidity":68},"sensor2":{"temperature":14,"humidity":84}}<br>
        {"sensor1":{"temperature":1,"humidity":88},"sensor2":{"temperature":6,"humidity":67}}<br>
    </td>
  </tr>
</table>

結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/f19586c9-ce82-f95b-61ea-b0985266873d.png)

~~一言~~ **感想**
同じグラフで同じプロパティ名でも折れ線を分けてくれたね！
私の環境では棒グラフに切り替えられなかった。

:::note warn
棒グラフも表示できるようになりました。詳細は[更新(2023/12/16)](#更新20231216)をご参照ください。
:::

少し困るのは項目を選ぶUIでは階層を記載しないので、同じプロパティ名の場合、どれがどれか分からない。
上から順にsensor1階層、sensor2階層かな？とは思う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/913631ca-d267-7809-6e83-f0f4bfc1c3ac.png)

マーカーにマウスオーバーすると階層付きで表示してくれる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/9ab651e4-9018-80b5-b51b-f11c4f206c6f.png)

上記グラフのJSONはこの様だが、
```json
{
    "sensor1": {
        "temperature": 1,
        "humidity": 64
    },
    "sensor2": {
        "temperature": 4,
        "humidity": 60
    }
}
```

階層を変えても同様なグラフ表現になった。
マウスオーバーすると違いが分かるが。

```json
{
    "box1": {
        "sensor1": {
            "temperature": 0,
            "humidity": 73
        },
        "sensor2": {
            "temperature": 13,
            "humidity": 80
        }
    }
}
```

```json
{
    "box1": {
        "sensor1": {
            "temperature": 7,
            "humidity": 65
        }
    },
    "box2": {
        "sensor2": {
            "temperature": 4,
            "humidity": 86
        }
    }
}
```


## JSON以外

### 整数文字列
<table>
  <thead>
    <tr>
      <th>トピック1</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room1</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>"<code>$整数</code>"</td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        50<br>
        1<br>
        18<br>
    </td>
  </tr>
</table>

結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/bed17236-fd06-6974-7c96-a997e5298ece.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/66f880d8-5fe8-d2a2-21c0-cfb8cbc77428.png)

**一言**
送信側は数値を文字列として送信したが、Postman側で数値として解釈してくれました。

### 小数文字列（負数あり）
<table>
  <thead>
    <tr>
      <th>トピック1</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room1</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>"<code>$小数(小数点以下2桁)</code>"</td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        50<br>
        1<br>
        18<br>
    </td>
  </tr>
</table>

結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/abaca22e-fa88-dd58-18a3-112eb6937991.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/00bffada-12a1-1f18-3fd1-00b6c90fad76.png)

**一言**
縦軸は小数点以下1桁までの表示。

### 整数文字列（エスケープ）
<table>
  <thead>
    <tr>
      <th>トピック1</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room1</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>"\"<code>$整数</code>\""</td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        "65"<br>
        "50"<br>
        "4"<br>
    </td>
  </tr>
</table>

結果
`Couldn't visualize the data`

**一言**
メッセージが表示されて、グラフは表示されなかった。
さすかに文字列だもんね…

:::note warn
表示が変わりました。詳細は[更新(2023/12/16)](#更新20231216)をご参照ください。
:::


### 16進数文字列
<table>
  <thead>
    <tr>
      <th>トピック1</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room1</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>"<code>$16進数</code>"</td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        1F<br>
        14<br>
        E<br>
    </td>
  </tr>
</table>

結果
`Couldn't visualize the data`

**一言**
さすがに文字列として認識されたようだ。
メッセージが表示されて、グラフは表示されなかった。

:::note warn
表示が変わりました。詳細は[更新(2023/12/16)](#更新20231216)をご参照ください。
:::


### 16進数文字列（0x接頭辞）
<table>
  <thead>
    <tr>
      <th>トピック1</th>
      <th></th>
    </tr>
  </thead>
  <tr>
    <td>トピック</td>
    <td>floor1/room1</td>
  </tr>
  <tr>
    <td>メッセージフォーマット</td>
    <td>"0x<code>$16進数</code>"</td>
  </tr>
  <tr>
    <td>メッセージ例</td>
    <td>
        0x1F<br>
        0x14<br>
        0xE<br>
    </td>
  </tr>
</table>

結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/a2351bf7-bf06-460f-7285-f945f733c179.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/c1a1806e-050a-ee69-35a7-465c4839ca28.png)

**一言**
`0x`接頭辞を明記したらちゃんと16進数の数値として認識してくた。グラフは10進数表記。

## 更新(2023/12/16)
なんと執筆の途中に更新があったようで、`Visualization`タブの挙動・表示が変わりました。
モード`Table`が追加されて、3つのモードをサポートするようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/a7438e9c-37ac-b67d-7d05-b5a51e4d58b3.png)

モードの変更UIも変わりました、項目別ではなく、グラフ全体に一つのモードを設定するようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/a61ac50b-cbe5-13bc-9b9b-1d997d77a06e.png)

多階層のJSONも棒グラフで表示できるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/3286a7a1-f1b3-fa5a-530f-35f285970e55.png)

代わりに下記のようなグラフ種類の混合ができなくなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/859fe6c8-7758-325a-7003-94b44e726cc7.png)

### Table
さて、この新しいモード`Table`ですが、名前の通りにメッセージをテーブルとして整理します。
グラフ系と異なって、入り組んだデータも得意です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/ace1c90c-aa2d-cc3e-5439-34d81a347a56.png)

グラフとして解釈できなかったデータも、そっけないメッセージ（`Couldn't visualize the data`）ではなく、デフォルトでモード`Table`で表示されるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243366/5ec12c10-56d0-748b-7ff3-de79b69f272e.png)

## さいごに
いい機能だと思います。
レスポンスの羅列より、グラフや整理されたテーブルの方はパッと見で分かりやすいです。
表示がシンプルでありながらもかゆい所に手が届くなあ、と感心しています。

冒頭のPostman Blogには以下の一文があります。

> Stay tuned for more updates because we plan to make this available for other protocols supported by Postman in the future.

将来はMQTT以外にも対応してくれる可能性が高いです。

9月にMQTTをサポートして、12月に表示モードが1個増えたことを考えると、
ほかのプロトコルに対応する前に、MQTTのデータの視覚化(Visualization)がさらにパワーアップするというのもあり得ますね。