MQTTクライアントドライバ
PlantPulse Edge の MQTTクライアントドライバは、Eclipse Paho mqttv3 1.2.5 ライブラリを ラップしたJava実装です。外部IIoTブローカー(HiveMQ / Mosquitto / EMQX / AWS IoT Core / Azure IoT Hub など)のトピックをsubscribeしてメッセージをインメモリキャッシュに保持し、 タグのポーリングサイクルごとにキャッシュ値を返します。writeは即時publish。
ソース: plantpulse.driver.protocol.mqtt_client.*
| クラス | 責務 |
|---|---|
MQTTClientDriver | ProtocolDriver 実装 — connect/read/write/close、トピックキャッシュ、lazy subscribe |
ライブラリ: lib/org.eclipse.paho.client.mqttv3-1.2.5.jar
Sparkplug B との違い
PlantPulse は2種類のMQTTベースドライバを別々に提供します。
| ドライバ | payload | 使用場面 |
|---|---|---|
MQTT_CLIENT(このページ) | 任意のString/JSON/binary | 一般的なIIoTブローカー、ユーザー定義トピック、ASCII / JSON payload |
SPARKPLUG_B | Sparkplug B Payload(Protobuf) | Cirrus Link / Tahu / Ignition 標準、NBIRTH/DBIRTH alias |
Sparkplug B は独自のワイヤーコーデックとalias学習ロジックが含まれているため、一般的なMQTTのみで十分な環境では このドライバの方が軽量で、標準のPaho APIだけで十分です。
動作フロー
broker ──PUBLISH──> Paho MqttClient ──MqttCallback.messageArrived(topic, payload)──> Driver
│
└─ lastValueByTopic.put(topic, new String(payload))
PlantPulse 폴러 ──read(addr)──> lastValueByTopic[addr] (in-memory hit)
write(addr, value) ──Paho.publish(topic, value, qos, retain=false)──> broker
readの最初の呼び出しでキャッシュミスの場合、lazy subscribe(QoSオプション値)後に空文字列を返します — 次のサイクルから
実際の値が入ります。 tag_map に登録されたトピックは、接続直後に preSubscribeFromTagMap() で
一括subscribeされ、最初のサイクルで即座に値が届く場合もあります(メッセージのpublish頻度によります)。
オプション
| キー | デフォルト値 | 説明 |
|---|---|---|
username | (なし) | ブローカー認証ユーザー名 |
password | (なし) | ブローカー認証パスワード |
tls | false | true → ssl://(デフォルト8883)、false → tcp://(デフォルト1883) |
qos | 0 | subscribe / publish QoS(0 / 1 / 2)。範囲外の値は自動的にクランプ。 |
keep-alive | 60 | keep-alive周期(秒) — MqttConnectOptions.setKeepAliveInterval |
clean-session | true | MqttConnectOptions.setCleanSession |
client-id | (自動) | 明示的なclient id。未指定時は PP-<opc_id>-<random6>(≤23文字)を自動生成 |
MqttConnectOptions.setAutomaticReconnect(true) が常に有効で、一時的なブローカー切断後に
自動再接続されます(Pahoのデフォルトbackoffを適用)。
Addressマッピング
| address | 動作 |
|---|---|
factory/line1/temp | 単一トピック — このトピックの最後のメッセージ |
device/+/status | wildcard(1段階) — マッチするトピックの最後のメッセージ(最も最近到着) |
factory/# | wildcard(マルチ) — 最後のセグメント、すべてのサブトピック |
"" / null | emptyを返す |
wildcard注意: Pahoのcallbackは、実際に到着したトピックごとに別エントリをキャッシュせず、
到着したトピック自体がキーになります。つまり device/+/status でsubscribeしても
lastValueByTopic には device/sensor01/status、device/sensor02/status が個別に入り、
ユーザーがwildcardトピック自体でreadするとキャッシュにはエントリがありません(wildcard自体は
publishの宛先ではないため)。wildcardパターンを登録する場合は、device/+/status のように登録した後、
readの結果として最後に到着したトピックの値を別途追跡する必要があります — 一般的な用途ではトピックごとに
明示的登録を推奨します。
write(publish)
client.publish(topic, value.getBytes(), qos, /*retain=*/ false);
valueのバイトがそのままpayloadとして送信されます(UTF-8デフォルトcharset)。retain=falseで固定されており、変更できません — ブローカーが最後のメッセージを保持しない ため、後から購読を開始したクライアントは次の書き込みが発生するまで値を受け取れません。 retainedメッセージが必要なコンシューマには、ブローカー側のブリッジや別のpublisherを設置してください。- QoSはオプション値のまま使用。QoS 1/2 の場合、Pahoが内部的にackまで再送信します。
接続ライフサイクル
| メソッド | 動作 |
|---|---|
connect() | options適用 → broker URL組み立て → MqttClient.connect() → tag_map 一括subscribe |
read() | キャッシュミス時にlazy subscribe → キャッシュヒットなら値を返す |
write() | publish(retain=false) |
close() | disconnect() + close()(best-effort、例外無視) → キャッシュクリア |
connectionLost(cause) | callbackで setConnected(false) — Pahoが自動再接続を試行 |
制限事項および今後の作業
- mTLS / クライアント証明書 — 現在はusername/passwordのみ。AWS IoT のようなX.509 mTLS環境は別途
truststore / keystore設定が必要(Paho
MqttConnectOptions.setSocketFactoryの公開は未実装)。 - retained / willメッセージ — 現在
retain=false固定、LWT未設定。 - wildcardキャッシュ分離 — wildcardパターン自体でreadすると結果が空(到着トピックごとのエントリ)。
- JSONパス抽出 — payloadがJSONでもドライバはraw Stringのみ返します。JSONPath抽出は
format/ 数式段階で処理が必要(または別途パーサーノード)。 - payloadエンコーディング — 現在はプラットフォームデフォルトcharsetを使用。binary payloadはUTF-8で壊れる可能性あり →
将来的に
payload-encodingオプション(utf8/iso-8859-1/base64)の公開を検討。
テスト場所
test/java/plantpulse/driver/protocol/mqtt_client/MQTTClientDriverTest.java — 31テスト。
- 初期状態 / メタ(
isConnected/isWriteSupported/isExternal/getDriverSource) - 未接続時のread/write/null/empty安全性
getDebugBaseUrl— tcp/ssl、明示ポート、デフォルトポート(1883/8883)- オプションパース — username/password/tls/keep-alive/clean-session/qos/client-id、不正値→デフォルト
- 静的ヘルパー —
clampQos、defaultClientId(長さ/random/null)、nullIfEmpty、parseInt、parseBool - 定数検証(
DEFAULT_PORT、DEFAULT_PORT_TLS、DEFAULT_KEEP_ALIVE_SEC、DEFAULT_QOS)
実際のブローカー依存の統合テストは別途 — 本単体テストは外部ブローカーなしで動作します。