跳到主要内容

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=2WRITE=3READ_STATE=4READ_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_BYHANDLE0xF005
  • READ_STATE(ADS state + Device state)
  • ❌ ADS Notification(订阅)
  • ❌ SUMUP(多次 read 单次 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/