AoE (ADS over EtherCAT)
AoE 协议实现了 ADS (Automation Device Specification) over EtherCAT 通信,支持 Beckhoff TwinCAT 和类似设备的 ADS 通信。
通过 slave.AoE 访问。从站不支持 AoE 时为 null。
属性
| 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|
| DefaultTimeoutMs | int | 只读 | 默认超时时间(毫秒),500 |
数据读写
Read(uint indexGroup, uint indexOffset, uint length, int timeoutMs = DefaultTimeoutMs)
public byte[]? Read(uint indexGroup, uint indexOffset, uint length, int timeoutMs = DefaultTimeoutMs)
读取 ADS 数据。
参数:
indexGroup(uint) — 索引组indexOffset(uint) — 索引偏移length(uint) — 读取长度timeoutMs(int) — 超时时间(毫秒)
返回值:
byte[]?— 读取的数据,失败返回null
示例:
byte[]? status = slave.AoE.Read(0x4020, 0, 4);
if (status != null)
{
uint value = BitConverter.ToUInt32(status, 0);
Console.WriteLine($"状态值: 0x{value:X8}");
}
Read<T>(uint indexGroup, uint indexOffset, int timeoutMs = DefaultTimeoutMs)
public T? Read<T>(uint indexGroup, uint indexOffset, int timeoutMs = DefaultTimeoutMs) where T : struct
泛型读取,自动按结构体大小读取并转换为指定类型。
参数:
indexGroup(uint) — 索引组indexOffset(uint) — 索引偏移timeoutMs(int) — 超时时间(毫秒)
返回值:
T?— 读取的值,失败返回null
示例:
uint? status = slave.AoE.Read<uint>(0x4020, 0);
int? position = slave.AoE.Read<int>(0x4020, 4);
Write(uint indexGroup, uint indexOffset, byte[] data, int timeoutMs = DefaultTimeoutMs)
public bool Write(uint indexGroup, uint indexOffset, byte[] data, int timeoutMs = DefaultTimeoutMs)
写入 ADS 数据。
参数:
indexGroup(uint) — 索引组indexOffset(uint) — 索引偏移data(byte[]) — 写入数据timeoutMs(int) — 超时时间(毫秒)
返回值:
bool— 成功返回true
Write<T>(uint indexGroup, uint indexOffset, T value, int timeoutMs = DefaultTimeoutMs)
public bool Write<T>(uint indexGroup, uint indexOffset, T value, int timeoutMs = DefaultTimeoutMs) where T : struct
泛型写入,自动将值转换为字节写入。
参数:
indexGroup(uint) — 索引组indexOffset(uint) — 索引偏移value(T) — 写入的值timeoutMs(int) — 超时时间(毫秒)
返回值:
bool— 成功返回true
示例:
slave.AoE.Write<uint>(0x4020, 0, 0x0006);
slave.AoE.Write<int>(0x4020, 4, 100000);
ReadWrite(uint indexGroup, uint indexOffset, uint readLength, byte[]? writeData = null, int timeoutMs = DefaultTimeoutMs)
public byte[]? ReadWrite(uint indexGroup, uint indexOffset, uint readLength, byte[]? writeData = null, int timeoutMs = DefaultTimeoutMs)
同时读写数据(ADS ReadWrite 命令)。
参数:
indexGroup(uint) — 索引组indexOffset(uint) — 索引偏移readLength(uint) — 读取长度writeData(byte[]?) — 写入数据(可选)timeoutMs(int) — 超时时间(毫秒)
返回值:
byte[]?— 读取的数据
设备信息
ReadDeviceInfo(int timeoutMs = DefaultTimeoutMs)
public (bool success, byte majorVer, byte minorVer, ushort build, string deviceName) ReadDeviceInfo(int timeoutMs = DefaultTimeoutMs)
读取 ADS 设备信息。
返回值:
success(bool) — 是否成功majorVer(byte) — 主版本号minorVer(byte) — 次版本号build(ushort) — 编译号deviceName(string) — 设备名称
示例:
var (success, major, minor, build, name) = slave.AoE.ReadDeviceInfo();
if (success)
Console.WriteLine($"设备: {name} v{major}.{minor}.{build}");
ReadState(int timeoutMs = DefaultTimeoutMs)
public (bool success, ushort adsState, ushort deviceState) ReadState(int timeoutMs = DefaultTimeoutMs)
读取 ADS 状态。
返回值:
success(bool) — 是否成功adsState(ushort) — ADS 状态deviceState(ushort) — 设备状态
相关结构:
0—Invalid无效状态1—Idle空闲2—Reset复位3—Init初始化4—Start启动5—Run运行6—Stop停止7—SaveConfig保存配置8—LoadConfig加载配置9—PowerFailure电源故障10—PowerGood电源正常11—Error错误12—Shutdown关闭13—Suspend挂起14—Resume恢复15—Config配置16—Reconfig重新配置
示例:
var (success, adsState, deviceState) = slave.AoE.ReadState();
if (success)
Console.WriteLine($"ADS 状态: {slave.AoE.GetAdsStateName(adsState)} ({adsState})");
WriteControl(ushort adsState, ushort deviceState, byte[]? data = null, int timeoutMs = DefaultTimeoutMs)
public bool WriteControl(ushort adsState, ushort deviceState, byte[]? data = null, int timeoutMs = DefaultTimeoutMs)
写入控制命令(切换设备状态)。
参数:
adsState(ushort) — 目标 ADS 状态deviceState(ushort) — 目标设备状态data(byte[]?) — 附加数据(可选)timeoutMs(int) — 超时时间(毫秒)
返回值:
bool— 成功返回true
示例:
slave.AoE.WriteControl(5, 0); // 切换到 Run 状态
GetAdsStateName(ushort adsState)
public string GetAdsStateName(ushort adsState)
获取 ADS 状态名称。
数据订阅
Subscribe(...)
public AoESubscription? Subscribe(
uint indexGroup, uint indexOffset, uint dataLength,
Action<AoENotificationEventArgs> callback,
AoETransmissionMode mode = AoETransmissionMode.OnChange,
int cycleTimeMs = 100)
订阅数据变化通知。
参数:
indexGroup(uint) — 索引组indexOffset(uint) — 索引偏移dataLength(uint) — 数据长度callback(Action<AoENotificationEventArgs>) — 数据变化回调mode(AoETransmissionMode) — 传输模式(默认OnChange)cycleTimeMs(int) — 检查周期(毫秒,默认 100)
返回值:
AoESubscription?— 订阅对象,失败返回null
AoETransmissionMode 枚举
public enum AoETransmissionMode : uint
{
NoTransmission = 0, // 无通知
Cyclic = 1, // 循环通知 - 按指定周期发送
OnChange = 2, // 变化通知 - 数据变化时发送
CyclicInDevice = 3, // 设备端循环通知
OnChangeInDevice = 4 // 设备端变化通知
}
示例:
var sub = slave.AoE.Subscribe(0x4020, 0, 4, e =>
{
uint value = BitConverter.ToUInt32(e.Data, 0);
Console.WriteLine($"数据变化: 0x{value:X8}");
});
Unsubscribe(AoESubscription subscription)
public bool Unsubscribe(AoESubscription subscription)
取消订阅。
UnsubscribeAll()
public void UnsubscribeAll()
取消所有订阅。
示例:
if (slave.AoE)
{
// AoE 可用
}
完整示例
类型化读写
if (slave.AoE)
{
// 泛型读取
uint? status = slave.AoE.Read<uint>(0x4020, 0);
Console.WriteLine($"状态: 0x{status:X8}");
// 泛型写入
slave.AoE.Write<uint>(0x4020, 0, 0x0006);
// 设备信息
var (ok, major, minor, build, name) = slave.AoE.ReadDeviceInfo();
if (ok) Console.WriteLine($"设备: {name} v{major}.{minor}.{build}");
}
数据订阅
if (slave.AoE)
{
var sub = slave.AoE.Subscribe(0x4020, 0, 4, e =>
{
Console.WriteLine($"数据变化, 订阅 ID: {e.SubscriptionId}");
});
Thread.Sleep(10000);
slave.AoE.UnsubscribeAll();
}