MQTTをWebMiteで使用する

# はじめに

PicoMite（MMBasic）でBME280を使って温度・湿度・気圧データを取得できたがコンソールなどのローカル環境でしか確認できない。そこでこれらのデータを[beebotte.com](https://beebotte.com)に公開してリモートから確認できるようにMMBasicがサポートしているMQTTを利用して取得した温度・湿度・気圧データのパブリッシュ、beebotteのダッシュボードでの表示などができるようになった。それらの内容を以下に記す。

# 使用ソフトウェア

今回使用したソフトウェアは下記のとおりです。

|ソフトウェア|バージョン|
|--|--|
|macOS|Sequoia 15.5|
|MMbasic|6.0002|
|mosquitto|2.0.21|

# macOSでMQTTのテスト

まず、LAN内のMacとWebMiteが動作するRaspberry Pi Pico Wおよび Pico 2 Wの間でMQTTでの通信を確認しました。

macOSでMQTTを利用するには`mosquitto`（https://mosquitto.org ） を使用しました。

## mosquittoのインストール

mosuquittoはHomebrewでインストールします。

```shell
$ brew install mosquitto
```

インストールが完了すると`/opt/homebrew/bin`と`/opt/homebrew/sbin`にコマンドへのシンボリックリンクが作成される。

```shell
ls /opt/homebrew/bin/mosq*
/opt/homebrew/bin/mosquitto_ctrl   /opt/homebrew/bin/mosquitto_rr
/opt/homebrew/bin/mosquitto_passwd /opt/homebrew/bin/mosquitto_sub
/opt/homebrew/bin/mosquitto_pub
❯ ls /opt/homebrew/sbin/mosq*
/opt/homebrew/sbin/mosquitto
```

それぞれのコマンドは次の機能があります。

|コマンド名|機能・説明|
|---|---|
|mosquitto|MQTTのブローカー|
|mosquitto_ctrl|ブローカーの動作中に対して設定変更や情報取得を行う|
|mosquitto_rr|Request–Responseテスト用ユーティリティ|
|mosquitto_passwd|パスワードファイル（password_file）の生成・更新|
|mosquitto_sub|MQTT ブローカーにサブスクライブ（購読）するクライアント|
|mosquitto_pub|MQTT ブローカーへパブリッシュ（送信）するクライアント|

## mosquittoの設定

mosuquittoのブローカは初期設定ではローカルマシン上のクライアントからの接続のみを受け付けるモードで動作しているのでLAN内の他のホストからのメッセージを受信できない。また、MMBasicからのMQTTブローカへの接続はユーザ名とパスワードによる認証が必要なのでそれらの設定が必要になります。

Homebrewでインストールしたmosquittoの設定ファイルは`/opt/homebrew/etc/mosquitto/mosquitto.conf`です。使い慣れたテキストエディタで開き、次の3ヶ所を修正します。

- リモートホストからの接続を許可する：234行目
- 匿名接続を無効化する：533行目
- ユーザ名とパスワードを保存したファイルの指定 ：551行目

```conf:/opt/homebrew/etc/mosquitto/mosquitto.conf
233 # listener port-number [ip address/host name/unix socket path]
234 listener 1883

532 # the local machine.
533 allow_anonymous false

550 # password_file, the plugin check will be made first.
551 password_file /opt/homebrew/etc/mosquitto/passwd.txt
```

## ユーザ名とパスワードの作成

`mosquitto_passwd`コマンドを使って認証用のユーザ名とパスワードを生成し、パスワードファイルに保存します。
ここではパスワードファイルを`/opt/homebrew/etc/mosquitto/passwd.txt`とし、ユーザ名を`hoge`にします。
コマンド`mosuqitto_passwd`のオプション`-c`に続けてパスワードファイル名を指定し、その後に作成するユーザ名`hoge`を入力します。
コマンドを実行するとパスワード入力を促されるので設定したいパスワードを入力します。入力したパスワードは表示されません。その後、パスワードの再入力を促されるので同じパスワードを入力します。


```shell
$ mosquitto_passwd -c /opt/homebrew/etc/mosquitto/passwd.txt hoge
Password: 設定するパスワードを入力（表示されません）
Reenter password:設定するパスワードを再入力
```

パスワードファイルを生成できたらパスワードファイルのグループを`staff`に変更します。変更しなくてもブローカは起動しますが将来のバージョンでパスワードファイルのロードを拒否されるようなので設定しておきます。

```shell
$ chgrp staff /opt/homebrew/etc/mosquitto/passwd.txt
```

## MQTTブローカの起動

パスワードファイルのグループを変更できたら設定ファイルを`-c`オプションで指定してブローカを起動します。

```shell
$ mosquitto -c /opt/homebrew/etc/mosquitto/mosquitto.conf
1748932872: mosquitto version 2.0.21 starting
1748932872: Config loaded from /opt/homebrew/etc/mosquitto/mosquitto.conf.
1748932872: Opening ipv6 listen socket on port 1883.
1748932872: Opening ipv4 listen socket on port 1883.
1748932872: mosquitto version 2.0.21 running
```

## ローカルで通信のテスト

ブローカを起動したターミナルとは別に2つのターミナルを開いてサブスクライバーとパブリッシャーを起動してメッセージが送受信をテストします。

### サブスクライバーを起動

`mosquitto_sub`コマンドを使ってメッセージを受信します。ブローカは同一ホストで動作しているのでlocalhostを、トピックをtp1/hoge、上記で登録したユーザ名/パスワードを使って起動します。コマンドが起動するとパブリッシャーからのメッセージの受信待機状態になります。

```shell
$ mosquitto_sub -v -h localhost -t tp1/hoge -u hoge -P hoge
```

コマンドのオプションは次の表に示す意味があります。

|オプション|設定する値|
|:-:|-|
|-v|トピック名を表示する|
|-h|ブローカのアドレス|
|-t|トピック名|
|-u|ユーザ名|
|-P|パスワード|

### パブリッシャーでメッセージ送信

`mosquitto_pub`コマンドでブローカにトピックを指定してメッセージを送信します。ブローカは同一ホストで動作しているのでlocalhostを、トピック名はtp1/hoge、登録したユーザ名/パスワードでメッセージを送信します。

```shell
$ mosquitto_pub -h localhost -t tp1/hoge -m "hello Hoge" -u hoge -P hoge
```

コマンドのオプションは表示示す意味があります。

|オプション|設定する値|
|:-:|-|
|-h|ブローカのアドレス|
|-t|トピック名|
|-m|送信するメッセージ|
|-u|ユーザ名|
|-P|パスワード|

ブローカにメッセージを送信するとサブスクライバーはブローカから受信したメッセージを表示します。

```shell
$ mosquitto_pub -h localhost -t tp1/hoge -m "はろー Hoge！" -u hoge -P hoge
```

上記コマンドを実行すると先ほど実行したサブスクライバーがメッセージを表示します。

```shell
$ mosquitto_sub -v -h localhost -t tp1/hoge -u hoge -P hoge
tp1/hoge はろー Hoge！
```

## MMBasicからの送受信

mosquittoでのメッセージ送受信を確認できたのでMMBasicからの送受信を試します。
MMBasicには`WB MQTT`コマンドでMQTTブローカとの接続・切断、パブリッシュ、サブスクライブできます。

次に示すプログラムは[http://pwillard.com/files/book.pdf](http://pwillard.com/files/book.pdf)に掲載されているプログラムから作成したものです。

LAN内にあるMQTTブローカ（192.168.10.23）のポート1883にユーザ名/パスワードhogeで接続し、ブローカからのメッセージを受信したときにサブルーチンmintを実行するようにしています。また、トピックtp1/hogeをサブスクライブし、2秒間隔でトピックtp1/hogeにHelloと時刻を送信するようにしています。

```BASIC:mqtt-test.bas
  1	WEB mqtt close
  2	WEB mqtt connect "192.168.10.23", 1883, "hoge", "hoge", mint
  3	WEB mqtt subscribe "tp1/hoge"
  4
  5	Do
  6	  WEB mqtt publish "tp1/hoge", "Hello! " + Time$
  7	  Pause 2000
  8	Loop
  9 ' 受信時に実行されるサブルーチン
 10	Sub mint
 11	  Print MM.ADDRESS$ ":" MM.MESSAGE$
 12	End Sub
```

ブローカへの接続コマンドの構文は次の通りです。

```
WEB mqtt connect 接続先アドレス, ポート番号, ユーザ名, パスワード,[メッセージ受信時に実行するサブルーチン]
```

サブルーチンmint内の`MM.ADDRESS$`は受信したメッセージのトピック名、`MM.MESSAGE$`は受信したメッセージを格納しています。

このプログラムを実行するとmosquittoへのネットワーク受信接続を許可するかを問い合わせるメッセージが表示されるので許可します。

![スクリーンショット 2025-06-02 22.22.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/99dc58d9-499b-4871-96d1-7229dc67dd73.png)

実行されるとサブスクライバはメッセージを受信し、他のホストからパブリッシュされたメッセージはWebMiteのコンソールはLCDディスプレイに表示されます。

# Beebotteの利用

ローカルのMQTTブローカとの接続ができたのでIoTやリアルタイムアプリケーション向けのクラウド型MQTTブローカーの[Beebotte](https://beebotte.com/)にBME280から取得した温度・気圧・湿度のデータを送信し、可視化を試しました。

手順は次の通りです。

1. Beebotteでチャンネル作成
2. Beebotteで受信したデータを可視化するダッシュボード作成
3. MMBasicでBeebotteへの接続し、データを送信するコード作成

## チャンネル作成

チャンネルには図に示すように気温、気圧、湿度の3つのデータをリソースを作ります。チャンネル、リソースに名前を付けます。`チャンネル名/リソース名`の組み合わせがMQTTのトピック名になります。
チャンネル名は`PicoBME280`にし、リソースは温度を`Temperature`、気圧を`Pressure`、湿度を`Humidity`としました。

![スクリーンショット 2025-06-03 19.12.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/d6da0bb5-4123-44ad-beb4-480294f48f21.png)

## ダッシュボード作成

ダッシュボードはBeebotteに保存されたデータを可視化して表示するものです。
温度、気圧、湿度を3つをTimeline Chatで、さらに温度をHeatmapで作成しました。作成方法は省略します。

## MMBasicのプログラム

Beebotteと通信するプログラムは上記のローカルのブローカと通信するプログラムと次の3点が異なります。

1. ユーザ認証のユーザ名とパスワードの指定
   両方ともBeebotteで作成したチャンネルの`チャンネルトークン（token_XXXXXXXX）`を指定します。
2. トピック名
   `チャンネル名/リソース名`にします
	1. 温度：`PicoBME280/Temperature`
	2. 気圧：PicoBME280/Pressure`
	3. 湿度：`PicoBME280/Humidity`
3. パブリッシュするデータ形式
   JSON形式`の{"data":データ,"write":true}`にします
   `"write":true`がないとBeebotteにデータが保存されず、ダッシュボードでグラフ化できません。

下記のプログラムがBeebotteへの接続、パブリッシュを実行する部分です。他の部分は省略しています。

```BASIC
' 変数tempに温度、presに気圧、humiに湿度のデータが格納されいる
' Beebotteのブローカーと接続
WEB Mqtt Connect "mqtt.beebotte.com", 1883, "token_XXXXX","token_XXXXX"
’ トピック名の設定
topicT$ = "PicoBME280/Temperature"  ' 温度のトピック
topicP$ = "PicoBME280/Pressure"　　　' 気圧のトピック
topicH$ = "PicoBME280/Humidity"　　　' 湿度のトピック
' メッセージの組立
msg1$   = "{" + Chr$(34) + "data"  + Chr$(34) + ":"
msg2$   = "," + Chr$(34) + "write" + Chr$(34) + ":true}"
msgT$   = msg1$ + Str$(temp, 3, 1) + msg2$  ' 温度
msgP$   = msg1$ + Str$(pres, 3, 1) + msg2$  ' 気圧
msgH$   = msg1$ + Str$(humi, 3, 1) + msg2$  ' 湿度
' ブローカへメッセージのパブリッシュ
WEB Mqtt publish topicT$, msgT$  ' 温度の送信
WEB Mqtt publish topicP$, msgP$  ' 気圧の送信
WEB Mqtt publish topicH$, msgH$  ' 湿度の送信
WEB mqtt Close
```

Chr$(34)はダブルコーテーションです。

## 動作確認

Beebotteのダッシュボードからも確認できるが`mosquitto_sub`コマンドでも下記のように確認できます。

```shell
$ mosquitto_sub -v -h mqtt.beebotte.com -t PicoBME280/# -u token_XXXXX -P token_XXXXX
PicoBME280/Humidity {"data": 65.8,"write":true}
PicoBME280/Pressure {"data": 989.7,"write":true}
PicoBME280/Temperature {"data": 23.5,"write":true}
....
```

トピック名`PicoBME280/#`はチャンネルPicoBME280のすべてのリソースを示しています。


ダッシュボードには次の図のようにグラフが作成されました。

![スクリーンショット 2025-06-03 21.13.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/bd8b76ac-7870-40b2-bc43-ed89cfaf6732.png)


# 参考サイト

- http://pwillard.com/files/book.pdf
-  [PicoMite User Manual](https://geoffg.net/Downloads/picomite/PicoMite_User_Manual.pdf)