EoE (Ethernet over EtherCAT)
EoE 协议通过 EtherCAT 总线实现以太网通信,支持配置 IP/MAC/DNS 地址和以太网帧收发,符合 ETG.1000.6 和 ETG.1020 标准。
通过 slave.EoE() 访问。
属性
读写属性实时操作:getter 从设备读取当前值,setter 校验格式后立即写入设备。
| 属性 | 类型 | 读写 | 说明 |
|---|---|---|---|
| IP() / IP(String) | String | 读写 | IP 地址(点分十进制) |
| Subnet() / Subnet(String) | String | 读写 | 子网掩码 |
| Gateway() / Gateway(String) | String | 读写 | 默认网关 |
| MAC() / MAC(String) | String | 读写 | MAC 地址(格式 "AA:BB:CC:DD:EE:FF") |
| DNS() / DNS(String) | String | 读写 | DNS 服务器地址 |
示例:
EoE eoe = slave.EoE();
// 读取
System.out.println("IP: " + eoe.IP());
System.out.println("MAC: " + eoe.MAC());
// 写入
eoe.IP("192.168.1.100");
eoe.Subnet("255.255.255.0");
eoe.Gateway("192.168.1.1");
eoe.MAC("AA:BB:CC:DD:EE:FF");
eoe.DNS("8.8.8.8");
以太网帧收发
SendFrame(byte[] frame, int timeoutMs)
public boolean SendFrame(byte[] frame, int timeoutMs)
public boolean SendFrame(byte[] frame)
发送以太网帧。
参数:
frame(byte[]) — 帧数据timeoutMs(int) — 超时时间(毫秒,默认 500)
返回值:
boolean— 成功返回true
SendFrameWithTimestamp(byte[] frame, long timestamp, int timeoutMs)
public boolean SendFrameWithTimestamp(byte[] frame, long timestamp, int timeoutMs)
public boolean SendFrameWithTimestamp(byte[] frame, long timestamp)
发送以太网帧并附加时间戳(ETG.1000.6 Table 78)。在帧末尾附加 4 字节时间戳。
参数:
frame(byte[]) — 帧数据timestamp(long) — DC 时间戳(纳秒)timeoutMs(int) — 超时时间(毫秒,默认 500)
返回值:
boolean— 成功返回true
ReceiveFrame(int timeoutMs)
public byte[] ReceiveFrame(int timeoutMs)
public byte[] ReceiveFrame()
接收以太网帧。
参数:
timeoutMs(int) — 超时时间(毫秒,默认 500)
返回值:
byte[]— 接收到的帧数据,失败返回null
示例:
EoE eoe = slave.EoE();
boolean sent = eoe.SendFrame(frameData);
byte[] received = eoe.ReceiveFrame();
if (received != null)
System.out.println("收到 " + received.length + " 字节");
地址过滤器 (ETG.1020)
addAddressFilter(byte[] mac, int timeoutMs)
public boolean addAddressFilter(byte[] mac, int timeoutMs)
添加单个 MAC 地址到过滤器列表。先读取已有过滤器,追加新地址后重新设置。
参数:
mac(byte[]) — MAC 地址(6 字节)timeoutMs(int) — 超时时间(毫秒)
返回值:
boolean— 成功返回true
removeAddressFilter(byte[] mac, int timeoutMs)
public boolean removeAddressFilter(byte[] mac, int timeoutMs)
从过滤器列表中移除指定 MAC 地址。
参数:
mac(byte[]) — MAC 地址(6 字节)timeoutMs(int) — 超时时间(毫秒)
返回值:
boolean— 成功返回true
getAddressFilters(int timeoutMs)
public List<byte[]> getAddressFilters(int timeoutMs)
public List<byte[]> getAddressFilters()
获取当前 MAC 地址过滤器列表。
参数:
timeoutMs(int) — 超时时间(毫秒,可选)
返回值:
List<byte[]>— MAC 地址列表(每个 6 字节)
ClearAddressFilters(int timeoutMs)
public boolean ClearAddressFilters(int timeoutMs)
public boolean ClearAddressFilters()
清空所有地址过滤器。
返回值:
boolean— 成功返回true
示例:
EoE eoe = slave.EoE();
byte[] mac = { (byte) 0xAA, (byte) 0xBB, (byte) 0xCC,
(byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
eoe.addAddressFilter(mac, 500);
List<byte[]> filters = eoe.getAddressFilters();
for (byte[] f : filters) {
System.out.printf("过滤器: %02X:%02X:%02X:%02X:%02X:%02X%n",
f[0] & 0xFF, f[1] & 0xFF, f[2] & 0xFF,
f[3] & 0xFF, f[4] & 0xFF, f[5] & 0xFF);
}
eoe.ClearAddressFilters();
ICMP Ping
通过 EoE 总线向从站背后的 IP 设备发送 ICMP Echo Request,验证三层网络连通性。
ping(String targetIp)
public EoEPingResult ping(String targetIp)
public EoEPingResult ping(String targetIp, int timeoutMs, int ttl)
发送 ICMP Echo 并等待响应(同步阻塞)。
参数:
targetIp(String) — 目标 IP(点分十进制,如"192.168.1.10")timeoutMs(int) — 超时(毫秒,默认 5000)ttl(int) — IP TTL(默认 64)
返回值:
EoEPingResult— Ping 结果
pingAsync(String targetIp)
public CompletableFuture<EoEPingResult> pingAsync(String targetIp)
public CompletableFuture<EoEPingResult> pingAsync(String targetIp, int timeoutMs, int ttl)
异步版 Ping,返回 CompletableFuture 不阻塞调用线程。
EoEPingResult
public static class EoEPingResult {
public boolean Success; // 是否成功
public double RoundTripTimeMs; // 往返时间(毫秒)
public String TargetAddress; // 目标地址
public byte TTL; // TTL
public String ErrorMessage; // 失败时的错误描述
}
示例:
EoE eoe = slave.EoE();
// 同步 Ping
EoEPingResult r = eoe.ping("192.168.1.10");
if (r.Success) {
System.out.printf("Ping 成功: RTT=%.2fms TTL=%d%n", r.RoundTripTimeMs, r.TTL & 0xFF);
} else {
System.out.println("Ping 失败: " + r.ErrorMessage);
}
// 异步 Ping
eoe.pingAsync("192.168.1.10").thenAccept(result -> {
System.out.println(result);
});
完整示例
网络配置
EoE eoe = slave.EoE();
// 读取当前配置
System.out.println("当前 IP: " + eoe.IP());
System.out.println("当前 MAC: " + eoe.MAC());
// 设置新配置
eoe.IP("10.0.0.100");
eoe.Subnet("255.255.255.0");
eoe.Gateway("10.0.0.1");
eoe.DNS("10.0.0.1");
帧收发
EoE eoe = slave.EoE();
// 发送帧
boolean sent = eoe.SendFrame(frameData);
// 发送带时间戳的帧
eoe.SendFrameWithTimestamp(frameData, System.nanoTime());
// 接收帧
byte[] received = eoe.ReceiveFrame(1000);
if (received != null)
System.out.println("收到 " + received.length + " 字节");
异步接收 Hook
EoE 的接收 Hook 把"轮询 ReceiveFrame"换成事件驱动:从站推帧时 SDK 主回调线程调用 listener,无需上层用 while-poll。每个 master 仅允许一个全局 Hook(最后注册者覆盖)。
setReceiveHook(ReceiveHookListener listener)
public boolean setReceiveHook(ReceiveHookListener listener)
public interface ReceiveHookListener {
void onFrame(short slaveIndex, byte[] frameData);
}
注册接收 Hook,传 null 等价 clearReceiveHook()。
返回值:
boolean— DLL 接受注册返回true;DLL 未导出或注册失败返回false
clearReceiveHook()
public boolean clearReceiveHook()
清除 Hook,停止异步推送。
示例:
EoE eoe = slave.EoE();
eoe.setReceiveHook((slvIdx, data) -> {
System.out.printf("Slave %d 推帧, %d 字节%n", slvIdx, data.length);
// 推荐: 入队后由业务线程处理, 不在此线程做重活 (DLL RX 线程上下文)
});
// 用完关闭
eoe.clearReceiveHook();
Hook 在 DLL 的 RX 线程被调用,禁止在此线程内调用 slave.SetState() / master.start() 等耗时 / 锁主流程的 API。建议入队 BlockingQueue 后由业务线程消费。
异步收发 (CompletableFuture)
public CompletableFuture<Boolean> sendFrameAsync(byte[] frame, int timeoutMs)
public CompletableFuture<Boolean> sendFrameAsync(byte[] frame)
public CompletableFuture<byte[]> receiveFrameAsync(int timeoutMs)
public CompletableFuture<byte[]> receiveFrameAsync()
把同步 SendFrame / ReceiveFrame 包到 CompletableFuture 上,便于和现有 Java 异步链组合(thenApply / whenComplete 等)。底层使用 ForkJoinPool.commonPool(),子类可覆盖 defaultExecutor() 改用自定义线程池。
示例:
eoe.sendFrameAsync(frame, 500)
.thenCompose(ok -> eoe.receiveFrameAsync(1000))
.whenComplete((reply, ex) -> {
if (ex != null) ex.printStackTrace();
else System.out.println("收 " + reply.length + " 字节");
});
sendFrameAsync 在底层返回 false 时抛 EoEProtocolException;receiveFrameAsync 超时返回 null,不视为异常。