跳到主要内容

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 时抛 EoEProtocolExceptionreceiveFrameAsync 超时返回 null,不视为异常。