跳到主要内容

AoE (ADS over EtherCAT)

AoE 协议实现了 ADS (Automation Device Specification) over EtherCAT 通信,支持与实现 ADS 协议的设备进行通信。

通过 slave.AoE 访问。从站不支持 AoE 时为 null。​

属性​

类别属性类型读写说明
协议能力IsSupportedbool只读从站是否支持 AoE 邮箱协议
ProtocolTypebyte只读邮箱协议类型 (AoE = 0x01)
ProtocolNamestring只读协议名称
错误与状态LastAoEErrorAoEResultCode只读最近一次 AoE 操作的 ADS 错误码,成功为 NoError
LastStatusMailboxStatus只读最近一次邮箱状态
LastErrorCodeuint只读最近一次错误码(与 LastAoEError 同源,以 uint 呈现)
统计StatisticsMailboxStatistics只读邮箱统计快照

除 InitAllSlavesNetId(默认 1000000 微秒)外,各方法的 timeoutUs 默认 500000 微秒(0.5 秒)。

数据读写​

Read(uint indexGroup, uint indexOffset, uint length, int timeoutUs = 500_000)​

public byte[]? Read(uint indexGroup, uint indexOffset, uint length, int timeoutUs = 500_000)

读取 ADS 数据。

参数:

  • indexGroup (uint) — 索引组
  • indexOffset (uint) — 索引偏移
  • length (uint) — 读取长度
  • timeoutUs (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}");
}

Write(uint indexGroup, uint indexOffset, byte[] data, int timeoutUs = 500_000)​

public bool Write(uint indexGroup, uint indexOffset, byte[] data, int timeoutUs = 500_000)

写入 ADS 数据。

参数:

  • indexGroup (uint) — 索引组
  • indexOffset (uint) — 索引偏移
  • data (byte[]) — 写入数据
  • timeoutUs (int) — 超时时间(微秒)

返回值:

  • bool — 成功返回 true

示例:

slave.AoE.Write(0x4020, 0, BitConverter.GetBytes((uint)0x0006));

ReadWrite(uint indexGroup, uint indexOffset, uint readLength, byte[]? writeData = null, int timeoutUs = 500_000)​

public byte[]? ReadWrite(uint indexGroup, uint indexOffset, uint readLength, byte[]? writeData = null, int timeoutUs = 500_000)

同时读写数据(ADS ReadWrite 命令)。

参数:

  • indexGroup (uint) — 索引组
  • indexOffset (uint) — 索引偏移
  • readLength (uint) — 读取长度
  • writeData (byte[]?) — 写入数据(可选)
  • timeoutUs (int) — 超时时间(微秒)

返回值:

  • byte[]? — 读取的数据

设备信息​

ReadDeviceInfo(int timeoutUs = 500_000)​

public (bool success, byte majorVer, byte minorVer, ushort build, string deviceName) ReadDeviceInfo(int timeoutUs = 500_000)

读取 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 timeoutUs = 500_000)​

public (bool success, ushort adsState, ushort deviceState) ReadState(int timeoutUs = 500_000)

读取 ADS 状态。

返回值:

  • success (bool) — 是否成功
  • adsState (ushort) — ADS 状态
  • deviceState (ushort) — 设备状态

相关结构:

  • 0 — Invalid 无效状态
  • 1 — Idle 空闲
  • 2 — Reset 复位
  • 3 — Init 初始化
  • 4 — Start 启动
  • 5 — Run 运行
  • 6 — Stop 停止
  • 7 — SaveCfg 保存配置
  • 8 — LoadCfg 加载配置
  • 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 状态: {DarraEtherCAT.Slave.AoEInstance.GetAdsStateName(adsState)} ({adsState})");

WriteControl(ushort adsState, ushort deviceState, byte[]? data = null, int timeoutUs = 500_000)​

public bool WriteControl(ushort adsState, ushort deviceState, byte[]? data = null, int timeoutUs = 500_000)

写入控制命令(切换设备状态)。

参数:

  • adsState (ushort) — 目标 ADS 状态
  • deviceState (ushort) — 目标设备状态
  • data (byte[]?) — 附加数据(可选)
  • timeoutUs (int) — 超时时间(微秒)

返回值:

  • bool — 成功返回 true

示例:

slave.AoE.WriteControl(5, 0);  // 切换到 Run 状态

GetAdsStateName(ushort adsState)​

public static string GetAdsStateName(ushort adsState)

获取 ADS 状态名称。

数据订阅​

Subscribe(...)​

public AoESubscription? Subscribe(
uint indexGroup, uint indexOffset, uint dataLength,
Action<AoENotificationEventArgs> callback,
AoETransmissionMode mode = DarraEtherCAT.Slave.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()

取消所有订阅。

DelNotification(uint notificationHandle, int timeoutUs = 500_000)​

public bool DelNotification(uint notificationHandle, int timeoutUs = 500_000)

底层删除从站设备通知句柄 (ADS Command 0x07)。常规场景应使用 Unsubscribe / UnsubscribeAll,此方法仅在持有原始 handle 且需手动清理时调用。

参数:

  • notificationHandle (uint) — 由 ADS AddNotification 返回的句柄
  • timeoutUs (int) — 超时时间(微秒),默认 500000

返回值:

  • bool — 成功返回 true

示例:

// 已知 handle 的低层清理路径
slave.AoE.DelNotification(handle);

DelNotificationAsync(uint notificationHandle, int timeoutUs = 500_000, CancellationToken cancellationToken = default)​

public Task<bool> DelNotificationAsync(uint notificationHandle, int timeoutUs = 500_000, CancellationToken cancellationToken = default)

异步版本的 DelNotification,用于 UI / 后台线程清理设备通知。

参数:

  • notificationHandle (uint) — 由 ADS AddNotification 返回的句柄
  • timeoutUs (int) — 超时时间(微秒),默认 500000
  • cancellationToken (CancellationToken) — 取消令牌

返回值:

  • Task<bool> — 成功返回 true

示例:

await slave.AoE.DelNotificationAsync(handle, cancellationToken: ct);

AoE 配置​

SetConfig(byte[] targetNetId, ushort targetPort, byte[] sourceNetId, ushort sourcePort)​

public bool SetConfig(byte[] targetNetId, ushort targetPort, byte[] sourceNetId, ushort sourcePort)

设置 AoE 路由配置(AMS NetID 和端口)。

参数:

  • targetNetId (byte[]) — 目标 AMS NetID(6 字节)
  • targetPort (ushort) — 目标 AMS 端口
  • sourceNetId (byte[]) — 源 AMS NetID(6 字节)
  • sourcePort (ushort) — 源 AMS 端口

返回值:

  • bool — 成功返回 true

示例:

byte[] targetNetId = { 5, 80, 187, 177, 1, 1 };
byte[] sourceNetId = { 192, 168, 1, 100, 1, 1 };
slave.AoE.SetConfig(targetNetId, 851, sourceNetId, 32768);

InitializeSlaveNetId(byte[] netId, int timeoutUs = 500_000)​

public bool InitializeSlaveNetId(byte[] netId, int timeoutUs = 500_000)

初始化从站 AoE Net ID(ETG.1020 §9.4)。在 INIT→PreOp 状态切换期间调用,将 Net ID 写入从站 ADS 路由表。

参数:

  • netId (byte[]) — 6 字节的 AMS Net ID
  • timeoutUs (int) — 超时时间(微秒)

返回值:

  • bool — 成功返回 true

示例:

byte[] netId = { 5, 80, 187, 177, 1, 1 };
slave.AoE.InitializeSlaveNetId(netId);

InitializeSlaveNetIdAsync(byte[] netId, int timeoutUs = 500_000, CancellationToken cancellationToken = default)​

public Task<bool> InitializeSlaveNetIdAsync(byte[] netId, int timeoutUs = 500_000, CancellationToken cancellationToken = default)

异步版本的 InitializeSlaveNetId,避免阻塞调用线程。

参数:

  • netId (byte[]) — 6 字节的 AMS Net ID
  • timeoutUs (int) — 超时时间(微秒)
  • cancellationToken (CancellationToken) — 取消令牌

返回值:

  • Task<bool> — 成功返回 true

示例:

byte[] netId = { 5, 80, 187, 177, 1, 1 };
await slave.AoE.InitializeSlaveNetIdAsync(netId, cancellationToken: ct);

ADS IndexGroup 读写 (非通用网关)​

通过 ADS IndexGroup 访问从站已实现的 CoE/SoE 对象 (ETG.1020 路由表)。不是邮箱网关、不是 SCADA、不是符号名访问。从站未实现对应 IndexGroup 时读返回 null、写返回 false。

ReadCoEViaAoE(ushort index, byte subindex, uint readLength, int timeoutUs = 500_000)​

public byte[]? ReadCoEViaAoE(ushort index, byte subindex, uint readLength, int timeoutUs = 500_000)

通过 AoE 路由读取 CoE 对象(IndexGroup=0xF302)。

参数:

  • index (ushort) — CoE 对象索引
  • subindex (byte) — CoE 子索引
  • readLength (uint) — 期望读取长度
  • timeoutUs (int) — 超时时间(微秒)

返回值:

  • byte[]? — 读取的数据,失败返回 null

示例:

// 通过 AoE 网关读取 CoE 对象 0x6041:0(状态字)
byte[]? data = slave.AoE.ReadCoEViaAoE(0x6041, 0, 2);
if (data != null)
{
ushort statusWord = BitConverter.ToUInt16(data, 0);
Console.WriteLine($"状态字: 0x{statusWord:X4}");
}

WriteCoEViaAoE(ushort index, byte subindex, byte[] data, int timeoutUs = 500_000)​

public bool WriteCoEViaAoE(ushort index, byte subindex, byte[] data, int timeoutUs = 500_000)

通过 AoE 路由写入 CoE 对象(IndexGroup=0xF302)。

参数:

  • index (ushort) — CoE 对象索引
  • subindex (byte) — CoE 子索引
  • data (byte[]) — 写入数据
  • timeoutUs (int) — 超时时间(微秒)

返回值:

  • bool — 成功返回 true

示例:

// 通过 AoE 网关写入 CoE 对象 0x6040:0(控制字)
slave.AoE.WriteCoEViaAoE(0x6040, 0, BitConverter.GetBytes((ushort)0x000F));

WriteCoEViaAoEAsync(ushort index, byte subindex, byte[] data, int timeoutUs = 500_000, CancellationToken cancellationToken = default)​

public Task<bool> WriteCoEViaAoEAsync(ushort index, byte subindex, byte[] data, int timeoutUs = 500_000, CancellationToken cancellationToken = default)

异步版本的 WriteCoEViaAoE,适合 UI 主线程发起的远程 CoE 写入。

参数:

  • index (ushort) — CoE 对象索引
  • subindex (byte) — CoE 子索引
  • data (byte[]) — 写入数据
  • timeoutUs (int) — 超时时间(微秒)
  • cancellationToken (CancellationToken) — 取消令牌

返回值:

  • Task<bool> — 成功返回 true

示例:

await slave.AoE.WriteCoEViaAoEAsync(0x6040, 0,
BitConverter.GetBytes((ushort)0x000F), cancellationToken: ct);

ReadSoEViaAoE(uint idn, uint readLength, int timeoutUs = 500_000)​

public byte[]? ReadSoEViaAoE(uint idn, uint readLength, int timeoutUs = 500_000)

通过 AoE 路由读取 SoE IDN(IndexGroup=0xF420)。

参数:

  • idn (uint) — SoE IDN 编号
  • readLength (uint) — 期望读取长度
  • timeoutUs (int) — 超时时间(微秒)

返回值:

  • byte[]? — 读取的数据,失败返回 null

WriteSoEViaAoE(uint idn, byte[] data, int timeoutUs = 500_000)​

public bool WriteSoEViaAoE(uint idn, byte[] data, int timeoutUs = 500_000)

通过 AoE 路由写入 SoE IDN(IndexGroup=0xF420)。

参数:

  • idn (uint) — SoE IDN 编号
  • data (byte[]) — 写入数据
  • timeoutUs (int) — 超时时间(微秒)

返回值:

  • bool — 成功返回 true

WriteSoEViaAoEAsync(uint idn, byte[] data, int timeoutUs = 500_000, CancellationToken cancellationToken = default)​

public Task<bool> WriteSoEViaAoEAsync(uint idn, byte[] data, int timeoutUs = 500_000, CancellationToken cancellationToken = default)

异步版本的 WriteSoEViaAoE,可与 await / CancellationToken 协作。

参数:

  • idn (uint) — SoE IDN 编号
  • data (byte[]) — 写入数据
  • timeoutUs (int) — 超时时间(微秒)
  • cancellationToken (CancellationToken) — 取消令牌

返回值:

  • Task<bool> — 成功返回 true

示例:

await slave.AoE.WriteSoEViaAoEAsync(idn: 32,
BitConverter.GetBytes((uint)1500), cancellationToken: ct);

完整示例​

数据读写​

if (slave.AoE != null)
{
// 读取数据
byte[]? status = slave.AoE.Read(0x4020, 0, 4);
if (status != null)
Console.WriteLine($"状态: 0x{BitConverter.ToUInt32(status, 0):X8}");

// 写入数据
slave.AoE.Write(0x4020, 0, BitConverter.GetBytes((uint)0x0006));

// 设备信息
var (ok, major, minor, build, name) = slave.AoE.ReadDeviceInfo();
if (ok) Console.WriteLine($"设备: {name} v{major}.{minor}.{build}");
}

数据订阅​

if (slave.AoE != null)
{
var sub = slave.AoE.Subscribe(0x4020, 0, 4, e =>
{
Console.WriteLine($"数据变化, 订阅 ID: {e.SubscriptionId}");
});

Thread.Sleep(10000);
slave.AoE.UnsubscribeAll();
}

跨协议 IndexGroup 读写​

if (slave.AoE != null)
{
// 从站须实现 IndexGroup 0xF302, 否则返回 null
byte[]? statusWord = slave.AoE.ReadCoEViaAoE(0x6041, 0, 2);
if (statusWord != null)
Console.WriteLine($"状态字: 0x{BitConverter.ToUInt16(statusWord, 0):X4}");

bool wrote = slave.AoE.WriteCoEViaAoE(0x6040, 0, BitConverter.GetBytes((ushort)0x000F));
if (!wrote)
Console.WriteLine("CoE-via-AoE 写入失败 (从站可能未实现 0xF302)");

byte[]? idnData = slave.AoE.ReadSoEViaAoE(32, 4);
if (idnData != null)
Console.WriteLine($"IDN 32 值: {BitConverter.ToUInt32(idnData, 0)}");
}

AoE 订阅子系统​

ADS DeviceNotification (Command 0x06/0x07/0x08) 的托管包装。 slave.AoE.Subscriptions 入口, 内部跨主站路由 native callback. 订阅后从设备主动推送数据变化, 不再依赖轮询。

Subscriptions​

public AoESubscriptionManager Subscriptions { get; }

订阅管理器单例, 首次访问惰性创建。 同一主站的所有 slave 共享 native 回调线程。

Subscribe(uint indexGroup, uint indexOffset, uint dataLength, AoETransmissionMode, int maxDelayMs, int cycleTimeMs)​

public AoESubscription? Subscribe(uint indexGroup, uint indexOffset, uint dataLength,
AoETransmissionMode mode = DarraEtherCAT.Slave.AoETransmissionMode.OnChange,
int maxDelayMs = 100,
int cycleTimeMs = 100)

创建并注册一个新订阅。 内部依次: 启动监听器 → AddDeviceNotification (0x06) → 注册 DLL 回调 → 加入订阅表。 失败返回 null.

参数:

  • indexGroup (uint) — ADS 索引组
  • indexOffset (uint) — ADS 索引偏移
  • dataLength (uint) — 数据长度 (字节)
  • mode (AoETransmissionMode) — 传输模式
  • maxDelayMs (int) — 最大延迟 (毫秒), 默认 100
  • cycleTimeMs (int) — 循环周期 (毫秒), 默认 100

返回值:

  • AoESubscription? — 订阅对象 (含 Id / NotificationHandle / IsActive)

相关结构:

详见 AoETransmissionMode。

Unsubscribe(Guid id) / Unsubscribe(AoESubscription)​

public bool Unsubscribe(Guid subscriptionId)
public bool Unsubscribe(AoESubscription subscription)

取消单个订阅: 移除事件处理器 → 注销 DLL 回调 → DeleteDeviceNotification (0x07).

UnsubscribeAll() / GetActiveSubscriptions() / GetSubscription(Guid)​

public void UnsubscribeAll()
public AoESubscription[] GetActiveSubscriptions()
public AoESubscription? GetSubscription(Guid subscriptionId)

批量管理 API. UnsubscribeAll 在 master 退出前必须调用以避免设备侧句柄泄漏。

订阅事件​

public event EventHandler<AoENotificationEventArgs>? DataNotification;
public event EventHandler<AoESubscriptionErrorEventArgs>? Error;
public event EventHandler<AoESubscription>? SubscriptionStateChanged;

相关结构:

public class AoENotificationEventArgs : EventArgs
{
public Guid SubscriptionId { get; }
public uint NotificationHandle { get; }
public ushort SlaveIndex { get; }
public uint IndexGroup { get; }
public uint IndexOffset { get; }
public byte[] Data { get; }
public DateTime Timestamp { get; }
public ulong DeviceTimestamp { get; } // 100ns 单位
}

public class AoESubscriptionErrorEventArgs : EventArgs
{
public Guid SubscriptionId { get; }
public string ErrorMessage { get; }
public Exception? Exception { get; }
public DateTime Timestamp { get; }
}

public class AoESubscription
{
public Guid Id { get; }
public uint NotificationHandle { get; }
public ushort SlaveIndex { get; }
public uint IndexGroup { get; }
public uint IndexOffset { get; }
public uint DataLength { get; }
public AoETransmissionMode TransmissionMode { get; }
public bool IsActive { get; }
public DateTime CreatedAt { get; }
public object? Tag { get; set; }
}

订阅管理器属性​

public int SubscriptionCount { get; }      // 当前订阅数量
public bool IsListenerRunning { get; } // native 监听线程是否运行
public int DefaultTimeoutMs { get; set; } // 订阅注册默认超时 (默认 500)

示例:

var sub = slave.AoE.Subscriptions.Subscribe(
indexGroup: 0xF021,
indexOffset: 0x1000,
dataLength: 4,
mode: DarraEtherCAT.Slave.AoETransmissionMode.OnChange,
maxDelayMs: 50,
cycleTimeMs: 100);

slave.AoE.Subscriptions.DataNotification += (s, e) =>
Console.WriteLine($"slave={e.SlaveIndex} data={BitConverter.ToInt32(e.Data,0)}");

slave.AoE.Subscriptions.Error += (s, e) =>
Console.WriteLine($"订阅错误: {e.ErrorMessage}");

// 退出前清理
slave.AoE.Subscriptions.UnsubscribeAll();

AoE 错误处理​

AoEResultCode​

public enum AoEResultCode : uint
{
NoError = 0x00,
InternalError = 0x01,
NoRealTime = 0x02,
InsertMailboxError = 0x04,
TargetPortNotFound = 0x06,
TargetMachineNotFound = 0x07,
UnknownCommandId = 0x08,
InvalidAmsLength = 0x0E,
InvalidAmsNetId = 0x0F,
PortDisabled = 0x12,
AmsSyncTimeout = 0x15,
DeviceInvalidGroup = 0x0700,
DeviceInvalidOffset = 0x0701,
DeviceNotReady = 0x0705,
DeviceTimeout = 0x0712,
DeviceAccessDenied = 0x071C,
// 更多见源码 (ETG.1020 Table 16)
}

ETG.1020 Table 16 定义的 AoE/ADS 结果码。 由 LastAoEError 暴露。

AoELastError​

public struct AoELastError
{
public uint ResultCode; // 完整 32-bit
public ushort ErrorClass; // High word
public ushort ErrorCode; // Low word
public ushort LastCommand; // 失败的 ADS command id
public bool HasError;
public AoEResultCode ResultCodeEnum { get; }
public string Message { get; }
}

最近一次 AoE 调用失败的完整记录。

主请求接口​

InitAllSlavesNetId(byte[]? masterNetId = null, int timeoutUs = 1_000_000)​

public int InitAllSlavesNetId(byte[]? masterNetId = null, int timeoutUs = 1_000_000)

为所有支持 AoE 的从站派发 InitializeSlaveNetId。返回成功写入的从站数,小于 0 表示失败。masterNetId == null 时使用 DLL 默认 NetID(全 0)。

InitializeSlaveNetId(byte[] netId, int timeoutUs)​

public bool InitializeSlaveNetId(byte[] netId, int timeoutUs = 500_000)

设置当前 slave 的 AMS NetID (6 字节).

SendFragmented(byte[] payload, ushort packetNumber, int timeoutUs)​

public bool SendFragmented(byte[] payload, ushort packetNumber, int timeoutUs = 500_000)

ADS Fragmentation 发送 (ETG.1020 §9.3). 大数据自动分片, 配合 ReadWrite 内部触发使用。

ReadWriteWithStatus(uint indexGroup, uint indexOffset, uint readLength, byte[]? writeData = null, int timeoutUs)​

public (bool success, byte[]? data) ReadWriteWithStatus(uint indexGroup, uint indexOffset, uint readLength, byte[]? writeData = null, int timeoutUs = 500_000)

与 ReadWrite 同路, 但显式返回成功标志(ReadWrite 失败返回 null, 无法区分"纯写入成功"与"失败")。

ReadWriteEx(uint indexGroup, uint indexOffset, uint readLength, byte[]? writeData = null, int timeoutUs)​

public (bool success, byte[]? data, uint actualReadLength) ReadWriteEx(uint indexGroup, uint indexOffset, uint readLength, byte[]? writeData = null, int timeoutUs = 500_000)

在 ReadWriteWithStatus 基础上再返回实际读取字节数(可小于 readLength, 对齐 ETG.1020 变长响应)。

SendCommand(ushort targetPort, ushort commandId, byte[]? commandData = null, int timeoutUs)​

public (bool success, byte[]? responseData) SendCommand(ushort targetPort, ushort commandId, byte[]? commandData = null, int timeoutUs = 500_000)

向指定 AMS 端口发送原始 ADS 命令, 返回响应数据。

SetConfig(byte[] targetNetId, ushort targetPort, byte[] sourceNetId, ushort sourcePort)​

public bool SetConfig(byte[] targetNetId, ushort targetPort, byte[] sourceNetId, ushort sourcePort)

设置 AoE 通信路由 (源/目标 NetID + Port).

WriteControl(ushort adsState, ushort deviceState, byte[]? data = null, int timeoutUs)​

public bool WriteControl(ushort adsState, ushort deviceState, byte[]? data = null, int timeoutUs = 500_000)

ADS WriteControl (Command 0x05): 切换 ADS 状态机 (Run/Stop/Reset/Config).

AddNotification / DelNotification (低层接口)​

public uint? AddNotification(uint indexGroup, uint indexOffset, uint length,
uint transMode, uint maxDelay, uint cycleTime, int timeoutUs = 500_000)
public bool DelNotification(uint notificationHandle, int timeoutUs = 500_000)

直接注册/注销设备通知。 Subscriptions 内部调用; 用户代码一般使用上层 Subscribe API. maxDelay / cycleTime 单位为 100ns.

ReadCoEViaAoE / WriteCoEViaAoE / ReadSoEViaAoE / WriteSoEViaAoE​

public byte[]? ReadCoEViaAoE(ushort index, byte subindex, uint readLength, int timeoutUs = 500_000)
public bool WriteCoEViaAoE(ushort index, byte subindex, byte[] data, int timeoutUs = 500_000)
public byte[]? ReadSoEViaAoE(uint idn, uint readLength, int timeoutUs = 500_000)
public bool WriteSoEViaAoE(uint idn, byte[] data, int timeoutUs = 500_000)

跨协议 IndexGroup 方法。 通过 ADS Read/Write 访问 CoE/SoE 对象, 仅当从站实现对应 IndexGroup 时成功。 不是邮箱网关, 不是符号名访问。

异步全套​

数据读写与通知类方法提供 Async 版本,后缀 Async,多接 CancellationToken cancellationToken = default(SetConfig / ReadDeviceInfo / ReadState / SendFragmented 等无异步版本):

  • Read — ReadAsync
  • Write — WriteAsync
  • ReadWrite — ReadWriteAsync
  • ReadWriteWithStatus — ReadWriteWithStatusAsync
  • WriteControl — WriteControlAsync
  • AddNotification — AddNotificationAsync
  • DelNotification — DelNotificationAsync
  • ReadCoEViaAoE — ReadCoEViaAoEAsync
  • WriteCoEViaAoE — WriteCoEViaAoEAsync
  • ReadSoEViaAoE — ReadSoEViaAoEAsync
  • WriteSoEViaAoE — WriteSoEViaAoEAsync
  • InitializeSlaveNetId — InitializeSlaveNetIdAsync

示例:

var ct = new CancellationTokenSource(TimeSpan.FromSeconds(2)).Token;
byte[]? data = await slave.AoE.ReadCoEViaAoEAsync(0x6041, 0, 2, cancellationToken: ct);