メインコンテンツまでスキップ

WebSocket クライアントドライバ

概要

WebSocket ドライバは、外部 streaming server (ws / wss) の endpoint にクライアントとして接続し、 受信したメッセージをキャッシュして、収集周期ごとに read() すると最新値を返す push モデルである。

項目
opc_typeWEBSOCKET
実装クラスplantpulse.driver.protocol.websocket.WebSocketDriver
基盤ライブラリjava.net.http.HttpClient.WebSocket (Java 21 runtime 標準 API)
read✅ (メッセージキャッシュ)
write✅ (sendText)
セキュリティTLS (wss) — options.tls=true

HTTP ドライバが外部システムの push (REST POST) を受け取るモデルであるのに対し、WebSocket ドライバは edge が クライアントとして outbound 接続 し streaming メッセージを受け取るモデルである。


OPC 登録フォーム / オプション

フィールド意味デフォルト値
host / portWebSocket サーバーアドレス192.168.10.99 / 8765, stream.example.com / 443
options.pathendpoint path//stream/v1, /realtime/tag
options.tlswss を使用するかfalsetrue (wss) / false (ws)
options.subscribe-message接続直後に送信するメッセージ (オプション){"op":"subscribe","topic":"line1.tempC"}
timecycleread 周期 (ms)1000

実際の endpoint URL: <scheme>://<host>:<port><path> (scheme は ws / wss)


タグ plc_address 形式

表記意味
空値または _raw_最後に受信したメッセージ 全体 (String)
JSON top-level キー (例: tempC)メッセージが JSON の場合、該当キーの値 (String に変換)

例) サーバーが {"tempC":25.7,"humid":40.2} を push した場合:

plc_address結果
_raw_{"tempC":25.7,"humid":40.2}
tempC25.7
humid40.2

動作フロー

  1. connect() 時に HttpClient.newWebSocketBuilder().buildAsync(...) で endpoint に接続。
  2. (オプション) subscribe-message があれば一度 sendText を送信。
  3. サーバーが送信するすべてのテキストメッセージを onText で蓄積 → fragment 終了時に handleMessage() を呼び出し。
  4. handleMessage() はメッセージ全体を _raw_ キーに保存。メッセージが { で始まる場合は JSON parsing 後、 top-level キーごとにもキャッシュ。
  5. 収集周期ごとに PLC collector が read(plc_address) を呼び出し → キャッシュ lookup → その値を返す。
  6. write(value) 呼び出し時は sendText でそのまま server へ送信。

onError 発生時は connected=false で処理。自動再接続は上位 layer の reconnect ポリシーに委任する。


curl 登録例

curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_WS_LINE1",
"opc_type": "WEBSOCKET",
"opc_name": "Line1 WebSocket Stream",
"opc_agent_ip": "192.168.10.99",
"opc_agent_port": "8765",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"options": {
"path": "/stream/v1",
"tls": "false",
"subscribe-message": "{\"op\":\"subscribe\",\"topic\":\"line1\"}"
},
"tag_list": [
{"tag_id":"OPC_WS_LINE1_T01","tag_name":"TempC","plc_address":"tempC","data_type":"Float"},
{"tag_id":"OPC_WS_LINE1_T02","tag_name":"Humid","plc_address":"humid","data_type":"Float"},
{"tag_id":"OPC_WS_LINE1_T03","tag_name":"Raw", "plc_address":"_raw_","data_type":"String"}
]
}'

よくあるエラーと対処

メッセージ / 症状原因対処
[WS] connect 실패: ...handshake...URL / path の誤り、サーバー未稼働wscat -c ws://<host>:<port><path> で直接検証
[WS] connect 실패: ...timeout...5 秒以内にハンドシェイクが完了しないファイアウォール / ポート / TLS 設定を点検
read() が常に空文字列サーバーがメッセージを送信していない / subscribe-message 未設定サーバーコンソールで broadcast の流れを確認。必要な subscribe payload を登録
JSON キーごとの read が空メッセージが JSON でない / 入れ子 (nested)_raw_ で受け取った後に後処理、または別途 parser を用意。(現在の driver は top-level のみ抽出)
TLS 証明書エラー自己署名 (self-signed)運用環境では valid cert の使用を推奨。暫定的には cacerts を追加

制限事項 / 今後の拡張

  • JSON path 非対応: 現時点で a.b.c の深い階層の抽出は未実装。top-level key のみ。必要な場合は ${VALUE} での後処理、または今後のオプション導入で対応。
  • 自動再接続は内蔵していない: PLC collector の reconnect 周期 / ポリシーに依存。独自のバックオフは今後対応。
  • binary frame 非対応: text frame (onText) のみ処理。JSON などのテキスト streaming が主用途。
  • per-message-deflate / ヘッダー認証: 標準 HttpClient.WebSocket の基本機能のみ使用。カスタムヘッダーは今後オプション化予定。

参考

  • Java 標準 java.net.http.WebSocket API: <https://docs.oracle.com/en/java/javase/17/docs/api/java.net.http/java/net/http/WebSocket.html>
  • 手軽な dummy server: Python websockets ライブラリ — python -m websockets.server.run :8765