跳到主要内容

VoE (Vendor over EtherCAT)

VoE 协议用于厂商自定义数据传输,支持 ETG.1000.6 Mailbox 通信规范(Mailbox Type 0x0F)。每个厂商可以定义自己的 VoE 头格式和数据结构。

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

属性​

类别属性类型读写说明
超时DefaultTimeoutMsint读写默认超时参考值(毫秒),默认 500。各方法省略 timeoutMs 时固定按 500 毫秒执行,需其他超时请显式传入
结构VoEHeaderSizeint常量VoE 头部大小(6 字节:VendorID 4 + VendorType 2)
状态LastStatusMailboxStatus只读最近一次邮箱事务状态(MailboxStatus 枚举)
错误LastErrorCodeuint只读最近一次错误值(原始 uint,非枚举)
过滤AllowedVendorIdsHashSet<uint>只读VendorID 白名单(空名单 + StrictVendorFilter 为 false = 允许全部)
StrictVendorFilterbool读写严格模式:true 时白名单为空也拒绝收发,默认 false

基本操作​

Send(uint vendorId, ushort vendorType, byte[] data, int timeoutMs = 500)​

public bool Send(uint vendorId, ushort vendorType, byte[] data, int timeoutMs = 500)

发送 VoE 数据到从站。

参数:

  • vendorId (uint) — 厂商 ID (4字节)
  • vendorType (ushort) — 厂商类型 (2字节)
  • data (byte[]) — 要发送的数据
  • timeoutMs (int) — 超时时间(毫秒)

返回值:

  • bool — 成功返回 true

示例:

slave.VoE.Send(0x00000002, 0x0001, new byte[] { 0x01, 0x02, 0x03 });

Receive(int timeoutMs = 500)​

public VoEResponse? Receive(int timeoutMs = 500)

从从站接收 VoE 数据。

返回值:

  • VoEResponse? — VoE 响应对象,失败返回 null

SendAndReceive(uint vendorId, ushort vendorType, byte[] data, int timeoutMs = 500)​

public VoEResponse? SendAndReceive(uint vendorId, ushort vendorType, byte[] data, int timeoutMs = 500)

发送 VoE 数据并等待响应。

参数:

  • vendorId (uint) — 厂商 ID (4字节)
  • vendorType (ushort) — 厂商类型 (2字节)
  • data (byte[]) — 要发送的数据
  • timeoutMs (int) — 超时时间(毫秒)

返回值:

  • VoEResponse? — VoE 响应对象,失败返回 null

示例:

var response = slave.VoE.SendAndReceive(0x00000002, 0x0001, new byte[] { 0x10 });
if (response != null)
{
Console.WriteLine($"厂商ID: 0x{response.VendorId:X8}");
Console.WriteLine($"数据: {response.ToHexString()}");
}

相关结构:

VoEResponse​

  • VendorId (uint) — 厂商 ID
  • VendorType (ushort) — 厂商类型
  • Data (byte[]) — 响应数据
  • DataLength (int) — 数据长度
  • ToHexString() (string) — 数据格式化为十六进制字符串(如 "01 02 03")
  • ToString() (string) — 完整描述(如 "VoE Response: VendorID=0x00000002, VendorType=0x0001, DataLength=3")

VendorID 白名单​

收发过滤:默认空名单 + StrictVendorFilter 为 false = 允许全部厂商 ID;一旦添加条目即按白名单过滤。不在白名单内的 Send / SendRaw 返回 false,SendAndReceive 返回 null,ReceiveRaw 丢弃该帧。

AddAllowedVendor(uint vendorId)​

public void AddAllowedVendor(uint vendorId)

添加允许的 VendorID(如 0x00000002 = Beckhoff)。VendorID 0 为保留值,传入抛 ArgumentException。

ClearAllowedVendors()​

public void ClearAllowedVendors()

清空白名单,恢复「全部允许」默认行为(前提 StrictVendorFilter 为 false)。

原始帧操作​

SendRaw(byte[] frameData, int timeoutMs = 500)​

public bool SendRaw(byte[] frameData, int timeoutMs = 500)

发送 VoE 原始帧(用户自行组织帧格式,包括 VoE 头)。

返回值:

  • bool — 成功返回 true

ReceiveRaw(int timeoutMs = 500)​

public byte[]? ReceiveRaw(int timeoutMs = 500)

接收 VoE 原始帧。

返回值:

  • byte[]? — 原始帧数据,失败返回 null

SendRawAndReceive(byte[] frameData, int timeoutMs = 500)​

public byte[]? SendRawAndReceive(byte[] frameData, int timeoutMs = 500)

发送原始帧并等待响应。

返回值:

  • byte[]? — 响应的原始帧数据,失败返回 null

辅助方法​

BuildVoEFrame(uint vendorId, ushort vendorType, byte[]? data)​

public byte[] BuildVoEFrame(uint vendorId, ushort vendorType, byte[]? data)

构建标准 VoE 帧(VoE 头 + 数据)。

返回值:

  • byte[] — 构建的 VoE 帧

ParseVoEFrame(byte[] frame)​

public VoEResponse? ParseVoEFrame(byte[] frame)

解析 VoE 帧(头 + 数据)。帧长不足 6 字节解析失败返回 null。

返回值:

  • VoEResponse? — 解析后的 VoE 响应对象,解析失败返回 null

通知接收(Vendor-initiated Notification)​

StartNotificationListener()​

public bool StartNotificationListener()

启动 VoE 通知监听线程(整个主站只需调一次,重入安全)。成功后本实例自动订阅本从站任意厂商的通知。

返回值:

  • bool — 成功返回 true

NotificationReceived​

public event EventHandler<VoENotificationEventArgs>? NotificationReceived;

Vendor-initiated VoE 帧到达事件。需先调 StartNotificationListener 启动监听,再订阅本事件。

相关结构:

public class VoENotificationEventArgs : EventArgs
{
public ushort SlaveIndex { get; } // 从站编号
public uint VendorId { get; } // 厂商 ID
public ushort VendorType { get; } // 厂商类型
public byte[] Data { get; } // 通知数据
public DateTime Timestamp { get; } // 时间戳(UTC)
}

StopNotificationListener() / StopAllListeners()​

public void StopNotificationListener()        // 停本实例的订阅(不影响其他实例)
public static void StopAllListeners() // 停整个主站的监听线程
public static bool IsListenerRunning { get; } // 监听线程是否运行(主站级)

异步方法​

每个同步方法都有对应 Async 版本,后缀 Async,多接 CancellationToken cancellationToken = default:SendAsync / SendAndReceiveAsync / ReceiveAsync / SendRawAsync / ReceiveRawAsync / SendRawAndReceiveAsync。

完整示例​

厂商命令交互​

if (slave.VoE != null)
{
var response = slave.VoE.SendAndReceive(
vendorId: 0x00000002,
vendorType: 0x0001,
data: new byte[] { 0x01, 0x00 }
);

if (response != null)
Console.WriteLine(response.ToString());
}

批量数据传输​

if (slave.VoE != null)
{
byte[] payload = new byte[1024];
slave.VoE.Send(0x00000002, 0x1000, payload);

var reply = slave.VoE.Receive();
if (reply != null)
Console.WriteLine($"收到 {reply.DataLength} 字节响应");
}