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

Beckhoff TwinCAT/ADS ドライバ

概要

Beckhoff TwinCAT の AMS/ADS over TCP。JNI / 外部ライブラリなしで、Beckhoff が公開している infosys AMS/ADS wire spec のみを用いて単一 JVM 内で socket 直接通信を行います。

項目
opc_typeADS
実装クラスplantpulse.driver.protocol.ads.ADSDriver
ライブラリ(なし — 独自実装。Beckhoff infosys 公開 spec)
read良好 (indexGroup/Offset またはシンボルハンドル)
write良好 (isWriteSupported() = true)
デフォルトポート48898 (ADS over TCP)
デフォルト AMS ポート851 (PLC Runtime 1)
セキュリティなし (TCP 直結、ADS Secure 非対応)
TwinCAT ルータへのアクセス

ADS 通信には、PC/PLC の AMS Router に登録された静的ルートが必要です。PLC 側の TwinCAT System Manager で Edge の AmsNetId をルートとして登録した上で、本ドライバがその NetId 宛にリクエストします。


クラス / 構造

ADSDriver (BaseProtocolDriver)
├── AmsTcpHeader 6 byte reserved + length(LE)
├── AmsHeader 32 byte target/source NetId+Port + cmd + state + dataLen + err + invokeId
├── AdsRead.buildRequest(indexGroup, indexOffset, length)
├── AdsWrite.buildRequest(indexGroup, indexOffset, data)
├── AdsResponse.parse(payload) — errorCode + data
├── AdsCommand — READ / WRITE / READ_STATE / READ_WRITE 상수, IGRP_*
└── AdsCodec — putUInt16/32LE, getUInt16/32LE, getInt32LE

リクエスト-レスポンスのマッチングは AtomicInteger invokeIdCounter が発行する 32-bit invokeId で行われ、単一 socket 上で synchronized sendCommand(...) により直列化されます。シンボル名 → handle の変換結果は symbolHandleCache (HashMap) にキャッシュされます。


wire フォーマット概要

AMS/TCP Header (6) | AMS Header (32) | ADS payload (가변)
└ reserved(2) len(4)│└ tgtNetId(6) tgtPort(2) srcNetId(6) srcPort(2) cmd(2) state(2) dataLen(4) err(4) invokeId(4)
  • すべての整数フィールドは little-endian。
  • AmsNetId は 6 byte (例 5.40.40.116.1.1)。
  • cmd : READ=2, WRITE=3, READ_STATE=4, READ_WRITE=9
  • stateFlags : STATEFLAG_REQ_RESP = 0x0004 (応答要求)。

OPC 登録オプション (options)

キー意味デフォルト
target-netidPLC AmsNetId、例 5.40.40.116.1.1host + .1.1
target-portAMS 対象ポート (PLC Runtime)851
source-netidローカル AmsNetId127.0.0.1.1.1
source-portローカル AMS ポート32905
connect-timeout接続タイムアウト (ms)3000
read-timeout応答待ちタイムアウト (ms)3000

connect() の直後に READ_STATE を呼び出してハンドシェイクを検証します — 失敗時は connected=false


タグアドレス形式

表記意味indexGroup
M0:4%M offset 0、4 byteIGRP_PLC_RW_MB (0x4020)
I0:2%I offset 0、2 byteIGRP_PLC_RW_IB (0x4000)
Q0:1%Q offset 0IGRP_PLC_RW_QB (0x4030)
DB10:4DB10 offset 0IGRP_PLC_RW_DB (0x4040)
0x4020:0x10:4直接 indexGroup:indexOffset:length 指定(そのまま)
MAIN.fCounter:REALシンボリック (ReadWrite + IGRP_GET_SYMHANDLE_BYNAME → キャッシュ)(handle ベース)

: の後には byte 長、または BOOL / INT / DINT / REAL / LREAL / STRING などの TwinCAT 型キーワードを指定でき、 sizeOfTypeKeyword(...) が byte 長を決定します。


データエンコード / デコード

decode(byte[], data_type) / encode(value, data_type, hintLen) が little-endian で処理します:

data_typebyte備考
Boolean / Bool1data[0] != 0
Byte1unsigned
Short / Int / Integer / Word2signed 16
UInt162unsigned
Int32 / DWord4signed 32
UInt324unsigned
Float / REAL4IEEE 754
Long / Int64 / LWord8signed
Double / LREAL8IEEE 754
StringNUTF-8、NUL-terminated 処理

対応 / 非対応

  • ✅ Memory area read/write (M / I / Q / DB)
  • ✅ シンボル名 → handle (IGRP_GET_SYMHANDLE_BYNAME = 0xF003) → IGRP_RW_SYMVAL_BYHANDLE (0xF005)
  • READ_STATE (ADS state + Device state)
  • ❌ ADS Notification (購読)
  • ❌ SUMUP (複数 read の 1 回 wrapping)
  • ❌ ADS Secure / TLS

テストカバレッジ

test/java/plantpulse/driver/protocol/ads/

クラステスト数
AdsAddressParseTest10
AdsCodecTest11
AdsReadTest5
AdsResponseTest5
AdsSpecComplianceTest23
AdsWriteTest5
AmsHeaderTest6
AmsNetIdTest7
AmsTcpHeaderTest7

合計 79 テスト。


参考

  • Beckhoff infosys: TwinCAT ADS / AMS over TCP wire format
  • コード: src/plantpulse/driver/protocol/ads/