HTTP / MOTORSENSE ドライバ
概要
HTTP プロトコルベースの 2 つのモード:
HTTP— 外部システムが/api/v1/tag/{tagId}/valueまたは/api/httpへ値を push すると edge 内部キャッシュ (current_value_map) に bind されます。収集周期ごとにキャッシュから read します。MOTOR_SENSE— KOPENS Motor Sense API を polling してシグナル/状態データを収集します。別途plantpulse-edge-driver-motorsensor.jarが reflection でロードされます。
| 項目 | HTTP | MOTOR_SENSE |
|---|---|---|
opc_type | HTTP | MOTOR_SENSE |
| 実装クラス | plantpulse.driver.protocol.http.HTTPDriver | plantpulse.driver.protocol.motor_sense.MotorSenseDriver (別途 jar) |
| read | ✅ (キャッシュ) | ✅ (HTTP polling) |
| write | ✅ (bind()) | ❌ |
| セキュリティ | なし (REST 側で認証が必要な場合はプロキシ) | API Key + customer-id |
HTTP モード
OPC 登録フォーム
| フィールド | 意味 | 例 |
|---|---|---|
opc_agent_ip | (実際には未使用、識別用) | 127.0.0.1 |
opc_agent_port | (実際には未使用) | 0 |
timecycle | キャッシュ read 周期 (ms) | 1000 |
タグ plc_address 形式
自由なキー文字列です。bind(io_address, value) の io_address と 1:1 で対応します。
| 表記 | 意味 |
|---|---|
temperature | 外部から bind("temperature", "25.7") で入力された値 |
line/A/rpm | スラッシュを含む自由文字列も可 |
値の書き込み (POST /api/v1/tag/{tagId}/value)
curl -X POST http://<edge-host>/api/v1/tag/OPC_HTTP_TAG_00001/value \
-H "Content-Type: application/json" \
-d '{ "value": "42.5" }'
内部で HTTPDriver.bind(plc_address, "42.5") を呼び出し → 次の polling 周期でその値が read されます。
curl 登録例 (HTTP)
curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_HTTP_BIND",
"opc_type": "HTTP",
"opc_name": "External HTTP Bind",
"opc_agent_ip": "127.0.0.1",
"opc_agent_port": "0",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"tag_list": [
{
"tag_id": "OPC_HTTP_BIND_TAG_00001",
"tag_name": "ExtTemp",
"plc_address": "temperature",
"data_type": "Float"
}
]
}'
MOTOR_SENSE モード
特徴
- IP / Port の入力は不要 (HTTP プロトコル使用。ただし登録フォームでは OPC エージェントの IP/ポートが自動入力されます)
- タグ情報の手動入力は不要 — 自動生成 (
signals、health_indexの 2 個) - JSON 形式でデータを収集
- ASSET ごとにデータをグループ化して表示
OPC 登録フォーム
| フィールド | 意味 | 保存先 |
|---|---|---|
| API KEY | Motor Sense API 認証キー | options.api-key |
| 顧客 ID | 顧客識別子 | options.customer-id |
| アセットリスト URL | アセット一覧取得 URL | options.asset-list-url |
| アセットシグナル URL | アセットシグナルデータ URL | options.asset-signal-url |
| アセット状態指数 URL | アセット状態指数 URL | options.asset-status-url |
| 波形/スペクトラム ロード | 波形/スペクトラムデータをロードするか | options.load-waveform-spectrum (任意) |
URL は http:// または https:// で始まる必要があります (JS 側で検証)。
自動生成タグ
tag_id | tag_name | plc_address | data_type |
|---|---|---|---|
<OPC_ID>_TAG_00001 | signals | signals | String |
<OPC_ID>_TAG_00002 | health_index | health_index | String |
VALUE は JSON 配列文字列として保存されます (1 つのタグ内に複数 ASSET のデータ)。
signals VALUE 例
[
{
"asset_id": "4d4c097f-4449-4cf0-a7ec-b770e3950e00",
"sensor_number": "1300",
"created_at": 1768376660,
"temperature": 25.7,
"voltage": 3.31,
"rms_x": 0.1733,
"rms_y": 0.4156,
"rms_z": 0.4697,
"rms_xyz": 0.5476
}
]
health_index VALUE 例
[
{
"asset_id": "4d4c097f-4449-4cf0-a7ec-b770e3950e2a",
"time": "2021-12-21",
"imbalance_health": 0.98,
"misalignment_health": 1.0,
"looseness_health": 1.0,
"bearing_health": 1.0,
"asset_health": 0.99
}
]
curl 登録例 (MOTOR_SENSE)
curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_MS_PLANT_A",
"opc_type": "MOTOR_SENSE",
"opc_name": "Motor Sense Plant A",
"opc_agent_ip": "127.0.0.1",
"opc_agent_port": "0",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"options": {
"api-key": "YOUR_API_KEY",
"customer-id": "kopens-001",
"asset-list-url": "https://api.example.com/assets",
"asset-signal-url": "https://api.example.com/signals",
"asset-status-url": "https://api.example.com/health",
"load-waveform-spectrum": "false"
},
"tag_list": [
{
"tag_id": "OPC_MS_PLANT_A_TAG_00001",
"tag_name": "signals",
"plc_address": "signals",
"data_type": "String",
"description": "에셋의 시그널 데이터"
},
{
"tag_id": "OPC_MS_PLANT_A_TAG_00002",
"tag_name": "health_index",
"plc_address": "health_index",
"data_type": "String",
"description": "에셋의 상태 지수"
}
]
}'
MOTOR_SENSE 固有の動作差異
| 一般 PLC | MOTOR_SENSE |
|---|---|
isConnected() が false なら read を skip | isConnected()=false でも read を試行 (HTTP ベースのため一時的な切断が多い) |
| 画面に一般 TAG テーブルを表示 | ASSET ごとのカード (HEALTH INDEX / SIGNAL) を表示 |
| 更新 = 画面 reload | 1 秒周期のバックグラウンド更新 (ローディング表示なし) |
よくあるエラーと対処
| メッセージ / 症状 | 原因 | 対処 |
|---|---|---|
MOTOR_SENSE 드라이버를 사용하려면 plantpulse-edge-driver-motorsensor.jar를 classpath에 추가 | 別途 jar が未インストール | WebContent/WEB-INF/lib/ に jar を配置して再デプロイ |
401 Unauthorized (Motor Sense) | API KEY / customer-id の誤り | KOPENS から発行された正しいキーを使用。URL endpoint も確認 |
HTTP モードで value が常に空 | bind() の呼び出しがない、または plc_address と io_address が不一致 | POST /api/v1/tag/{tagId}/value で push した後、次の周期まで待機 |
tag write not supported for opc_type=... | HTTP 以外のプロトコルに write を呼び出した | write は HTTP プロトコルのタグのみ可能。後続の Phase 3 を参照 |
例集 (データ型別、HTTP モード)
HTTP モードは外部システムが push する自由文字列値をそのまま受け取ります。raw は String で、data_type / fomula は後処理に使用します。
Boolean
data_type | plc_address | push 例 (POST /api/v1/tag/.../value) | 備考 |
|---|---|---|---|
Boolean | pump1.run | {"value":"true"} | true/false 文字列 |
Boolean | door.open | {"value":"1"} | 1/0 も可 (後処理でキャスト) |
整数
data_type | plc_address | push 例 | 備考 |
|---|---|---|---|
Integer | counter.production | {"value":"12345"} | |
Long | counter.total | {"value":"9876543210"} | 32-bit 超過 |
実数
data_type | plc_address | push 例 | 備考 |
|---|---|---|---|
Float | temperature | {"value":"25.7"} | |
Double | power.kw | {"value":"1234.56789"} | 高精度 |
文字列
data_type | plc_address | push 例 | 備考 |
|---|---|---|---|
String | recipe.name | {"value":"R-2025-A"} | 自由文字列 |
String | barcode.last | {"value":"880699112"} | バーコードキャプチャの push |
Formula の活用 (HTTP)
| 用途 | data_type | fomula | 備考 |
|---|---|---|---|
| 外部 push 値のスケーリング | Float | ${VALUE}*1.8+32 | C → F |
| 2 つの外部値の合算 | Float | ${VALUE}+${EXT_OFFSET} | 他の HTTP タグを参照 |
curl 総合例 (HTTP push フロー)
# 1) OPC + 태그 등록
curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_HTTP_FULL",
"opc_type": "HTTP",
"opc_name": "External Bind Full",
"opc_agent_ip": "127.0.0.1",
"opc_agent_port": "0",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"tag_list": [
{"tag_id":"OPC_HTTP_FULL_T01", "tag_name":"PumpRun", "plc_address":"pump1.run", "data_type":"Boolean"},
{"tag_id":"OPC_HTTP_FULL_T02", "tag_name":"Counter", "plc_address":"counter.prod", "data_type":"Integer"},
{"tag_id":"OPC_HTTP_FULL_T03", "tag_name":"TempC", "plc_address":"temperature", "data_type":"Float"},
{"tag_id":"OPC_HTTP_FULL_T04", "tag_name":"TempF", "plc_address":"temperature", "data_type":"Float", "fomula":"${VALUE}*1.8+32"},
{"tag_id":"OPC_HTTP_FULL_T05", "tag_name":"BatchName", "plc_address":"recipe.name", "data_type":"String"}
]
}'
# 2) 외부에서 값 push
curl -X POST http://<edge-host>/api/v1/tag/OPC_HTTP_FULL_T01/value \
-H "Content-Type: application/json" -d '{"value":"true"}'
curl -X POST http://<edge-host>/api/v1/tag/OPC_HTTP_FULL_T03/value \
-H "Content-Type: application/json" -d '{"value":"25.7"}'
# 3) 다음 polling 주기 후 조회
curl -s http://<edge-host>/api/v1/tag/OPC_HTTP_FULL_T03/value | jq
curl -s http://<edge-host>/api/v1/tag/OPC_HTTP_FULL_T04/value | jq # fomula 적용된 화씨값