概要
OPC UA(OPC Unified Architecture)は、産業オートメーション向けに設計されたオープンな通信規格・データモデル標準です。OPC Foundationが2008年に策定し(IEC 62541として国際標準化)、製造業・エネルギー・プロセス産業などにおけるデバイス間・システム間のデータ連携を目的としています。
従来のOPC(OLE for Process Control)がWindowsのCOM/DComponentモデルに依存していたのに対し、OPC UAはプラットフォームに依存しない(プラットフォーム非依存)設計となっており、LinuxやRTOS上でも動作します。通信プロトコル・セキュリティ・情報モデルを一体で定義している点が特徴で、単なる通信プロトコルではなく「産業データの意味論的な記述方法」も提供します。
OPC UAの主要な特徴は以下の通りです。
- プラットフォーム非依存:Windows/Linux/RTOS上で動作
- セキュリティ内包:認証・認可・暗号化を規格レベルで定義
- 情報モデル:データに意味論(セマンティクス)を付与するアドレス空間モデル
- スケーラブル:PLC・センサーからクラウドまで同一規格で接続
- 信頼性:セッション管理・サブスクリプションによる確実なデータ配信
歴史・背景
OPCからOPC UAへ
1996年に策定された従来のOPC(Classic OPC)はWindowsのCOM/DCOMに依存しており、以下の問題がありました。
- Windowsにしか対応できない
- ファイアウォール越えが困難(DCOMのポートが動的)
- セキュリティが脆弱
- 組み込み機器への搭載が事実上不可能
これらを解決するためOPC UAが2008年に策定されました。2016年以降は**Industrie 4.0(ドイツ)やIIoT(Industrial Internet of Things)**の基盤プロトコルとして注目が高まり、SiemensやGE、Beckhoffといった主要産業機器メーカーが製品に実装し始めました。
2018年にはMQTT上でOPC UAデータモデルを運ぶOPC UA Pub/Subが仕様に追加され、クラウドとの統合もよりシームレスになっています。
技術仕様
アドレス空間(Address Space)とノード
OPC UAの核心はアドレス空間と呼ばれる情報モデルです。すべてのデータは「ノード」として階層的に表現され、ノードIDで一意に識別されます。
Root
├── Objects
│ ├── Server
│ └── Factory
│ ├── Line1
│ │ ├── Machine001
│ │ │ ├── Temperature (Variable, ns=2;i=1001)
│ │ │ ├── Pressure (Variable, ns=2;i=1002)
│ │ │ └── StartMotor (Method, ns=2;i=1003)
│ │ └── Machine002
│ └── Line2
├── Types
│ ├── ObjectTypes
│ ├── VariableTypes
│ └── DataTypes
└── Views
ノードクラス
| ノードクラス | 説明 | 例 |
|---|---|---|
| Object | 物理/論理エンティティ | 機械、センサー |
| Variable | データ値 | 温度、圧力 |
| Method | 呼び出し可能な操作 | モーター起動 |
| DataType | データ型定義 | 構造体、列挙型 |
| ObjectType | オブジェクトの型定義 | ポンプ型 |
| ReferenceType | ノード間関係の種類 | HasComponent等 |
通信モデル
OPC UAは2種類の通信モデルを持ちます。
クライアント/サーバーモデル(従来型):
| サービス | 説明 |
|---|---|
| Read | 変数値の読み取り |
| Write | 変数値の書き込み |
| Browse | アドレス空間の探索 |
| Subscribe | 値変化の監視(Subscription) |
| Call | Methodの呼び出し |
| Translate | パスからNodeIDへの変換 |
Pub/Subモデル(2018年追加):
MQTT、AMQP、UDP上でOPC UAデータを非同期配信します。クライアント/サーバーのようなコネクション管理が不要で、IoTクラウドへの統合に向いています。
[PLC(OPC UA Pub)]
│ MQTT / AMQP
▼
[メッセージブローカー]
│
▼
[クラウド(OPC UA Sub)]
セキュリティモード
| モード | 説明 |
|---|---|
| None | 暗号化・署名なし(テスト用のみ) |
| Sign | メッセージ署名のみ(改ざん検知) |
| SignAndEncrypt | 署名+暗号化(本番推奨) |
X.509証明書による相互認証をサポートし、エンドポイント単位でセキュリティポリシーを設定できます。
トランスポート
| トランスポート | エンコーディング | ポート |
|---|---|---|
| OPC UA Binary (opc.tcp://) | バイナリ(コンパクト) | 4840 |
| OPC UA HTTPS | JSON/XML | 443 |
| OPC UA WebSocket | JSON | 4843 |
動作原理
セッション確立
Client Server
|-- GetEndpoints ----------------->| エンドポイント確認
|<-- Endpoints --------------------|
|-- CreateSecureChannel ----------->| TLSライクなチャネル確立
|<-- SecureChannel Created --------|
|-- CreateSession ----------------->| セッション作成
|<-- Session Created ---------------|
|-- ActivateSession(証明書)------>| 認証
|<-- Session Activated -------------|
| [Browse/Read/Write/Subscribe等]
|-- CloseSession ------------------>|
サブスクリプション(データ変化通知)
OPC UAのサブスクリプションは「監視項目(MonitoredItem)」を束ねた「サブスクリプション」として管理します。
Client Server
|-- CreateSubscription ------------>| (publishingInterval=500ms)
|<-- Subscription ID=1 -----------|
|-- CreateMonitoredItems(temp)--->| (samplingInterval=100ms)
|<-- MonitoredItem ID=10 ----------|
|-- CreateMonitoredItems(press)-->|
|<-- MonitoredItem ID=11 ----------|
| |
| 500ms後... |
|<-- Publish(temp=25.3, press=101)| まとめて通知
|-- PublishAck ------------------- >|
open62541での実装例
#include <open62541/server.h>
#include <open62541/server_config_default.h>
int main(void) {
UA_Server *server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
/* 温度センサーノードを追加 */
UA_VariableAttributes attr = UA_VariableAttributes_default;
UA_Double temperature = 25.3;
UA_Variant_setScalar(&attr.value, &temperature, &UA_TYPES[UA_TYPES_DOUBLE]);
attr.displayName = UA_LOCALIZEDTEXT("ja", "温度");
attr.dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId;
attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_NodeId tempNodeId = UA_NODEID_STRING(1, "Temperature");
UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
UA_NodeId variableTypeNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
UA_QualifiedName browseName = UA_QUALIFIEDNAME(1, "Temperature");
UA_Server_addVariableNode(server, tempNodeId, parentNodeId,
parentReferenceNodeId, browseName,
variableTypeNodeId, attr, NULL, NULL);
UA_Boolean running = true;
UA_Server_run(server, &running);
UA_Server_delete(server);
return 0;
}
用途・ユースケース
製造業(スマートファクトリー)
工場内の各機械(PLC、CNC、ロボット)がOPC UAサーバーとして動作し、MES(製造実行システム)やSCADAシステムがクライアントとしてデータを収集します。
[Siemens S7-1500 PLC] [Fanuc ロボット] [Beckhoff PC]
│ OPC UA │ OPC UA │ OPC UA
└──────────────────────┴─────────────────────┘
│
[OPC UA Aggregation Server]
│
[MES / SCADA System]
│
[クラウド(Azure/AWS)]
エネルギー管理(スマートグリッド)
発電所・変電所の機器がOPC UAで電力データを送信し、エネルギー管理システムが最適化を行います。IEC 61850との連携規格も策定されています。
PLCとRaspberry Piの統合
# Python OPC UA クライアント(opcua-asyncio)
import asyncio
from asyncua import Client
async def main():
url = "opc.tcp://plc.factory.local:4840"
async with Client(url=url) as client:
# ノードを名前で参照
temp_node = client.get_node("ns=2;i=1001")
temperature = await temp_node.read_value()
print(f"温度: {temperature} ℃")
# サブスクリプションで変化を監視
handler = MySubscriptionHandler()
subscription = await client.create_subscription(500, handler)
await subscription.subscribe_data_change(temp_node)
await asyncio.sleep(10) # 10秒間データ収集
class MySubscriptionHandler:
def datachange_notification(self, node, val, data):
print(f"値変化: {val}")
asyncio.run(main())
コンパニオン仕様(Companion Specification)
OPC UAには産業分野ごとの「コンパニオン仕様」があり、機器のデータモデルを標準化します。
| 分野 | コンパニオン仕様 |
|---|---|
| ロボット | OPC UA for Robotics |
| 工作機械 | OPC UA for Machine Tools (umati) |
| 薬品製造 | OPC UA for Pharma |
| エネルギー | OPC UA for Energy |
| 半導体 | SEMI S2, E164 |
実装・開発のポイント
主要実装
| 実装 | 言語 | ライセンス | 特徴 |
|---|---|---|---|
| open62541 | C | MPL 2.0 | 最軽量、組み込み対応 |
| opcua-asyncio | Python | LGPL | Pythonクライアント/サーバー |
| node-opcua | JavaScript | MIT | Node.jsエコシステム |
| Unified Automation | C++/NET | 商用 | 産業用途の商用実装 |
| prosys OPC UA | Java | 商用/評価版 | Java環境 |
組み込み機器での注意点
OPC UAはフル実装だとかなりのリソースを消費します。
| 機能 | 最小RAM要件(目安) |
|---|---|
| OPC UA Binary(最小構成) | 約64KB |
| セキュリティ(X.509) | 約256KB以上 |
| フル機能 | 1MB以上 |
Cortex-M4以上のマイコンであれば最小構成で動作可能です。open62541は「amalgamated」ビルドで単一C/Hファイルに圧縮でき、組み込みへの組み込みが容易です。
# open62541のamalgamatedビルド
cmake .. -DUA_ENABLE_AMALGAMATION=ON \
-DUA_ENABLE_ENCRYPTION=MBEDTLS \
-DCMAKE_BUILD_TYPE=MinSizeRel
他技術との比較
| 項目 | OPC UA | Modbus | MQTT | REST API |
|---|---|---|---|---|
| 情報モデル | ◎(セマンティクス) | × | × | △(OpenAPI) |
| セキュリティ | ◎(組み込み) | × | △(TLS外付け) | ○(TLS) |
| リアルタイム性 | ○ | ○ | ○ | △ |
| 組み込み適合 | △(リソース大) | ◎ | ◎ | ○ |
| 産業標準 | ◎(IEC 62541) | ◎ | △ | △ |
| クラウド統合 | ○(Pub/Sub拡張) | × | ◎ | ◎ |
Modbusはシンプルで超軽量ですが情報モデルがなく、大規模システムの統合には限界があります。OPC UAはその対極にあり、複雑なシステムにおける意味論的な相互運用性を実現します。MQTTとの組み合わせでは、OPC UA Pub/Subを使ってMQTTトピックにOPC UAデータモデルを乗せることで、両者の長所を活かした統合が実現できます。