VoE (Vendor over EtherCAT)
VoE 协议用于厂商自定义数据传输,支持 ETG.1000.6 Mailbox 通信规范(Mailbox Type 0x0F)。每个厂商可以定义自己的 VoE 头格式和数据结构。
通过 slave.VoE 访问。从站不支持 VoE 时为 null。
属性
| 类别 | 属性 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 超时 | DefaultTimeoutMs | int | 读写 | 默认超时参考值(毫秒),默认 500。各方法省略 timeoutMs 时固定按 500 毫秒执行,需其他超时请显式传入 |
| 结构 | VoEHeaderSize | int | 常量 | VoE 头部大小(6 字节:VendorID 4 + VendorType 2) |
| 状态 | LastStatus | MailboxStatus | 只读 | 最近一次邮箱事务状态(MailboxStatus 枚举) |
| 错误 | LastErrorCode | uint | 只读 | 最近一次错误值(原始 uint,非枚举) |
| 过滤 | AllowedVendorIds | HashSet<uint> | 只读 | VendorID 白名单(空名单 + StrictVendorFilter 为 false = 允许全部) |
| StrictVendorFilter | bool | 读写 | 严格模式: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) — 厂商 IDVendorType(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} 字节响应");
}