跳到主要内容

初始化

推荐方式

强烈建议使用 Darra 配置工具导出的 DENI 文件进行初始化。 DENI 文件包含完整的网络配置(网口、从站、PDO 映射、DC 设置等),可确保配置的一致性和正确性。 使用 DENI 文件管理设备硬件设施将获得更好的兼容性与通用性。

工厂方法​

EtherCATMaster 通过静态工厂方法创建实例,不使用 new 构造函数。

EtherCATMaster.create()​

public static EtherCATMaster create()
public static EtherCATMaster create(short masterIndex)

创建主站实例,流式 API 入口。无参版本自动分配编号,带参版本指定编号。必须通过 setENI() 或 SetNetwork() 设置配置,然后调用 build() 初始化。

返回值:

  • EtherCATMaster — 主站实例

示例:

EtherCATMaster master = EtherCATMaster.create()
.setENI("C:\\EtherCAT\\MyProject.xml")
.build()
.master;

if (master == null) {
System.out.println("初始化失败");
return;
}
master.setState(EcState.OP);

EtherCATMaster.createFromJsonFile(String jsonFilePath)​

public static EtherCATMaster createFromJson(String jsonConfig)
public static EtherCATMaster createFromJsonFile(String jsonFilePath)

通过 JSON 配置一步完成主站初始化。内部自动执行初始化、网络配置和状态转换全流程。

示例:

try (EtherCATMaster master = EtherCATMaster.createFromJsonFile("C:\\config.json")) {
System.out.println("从站数量: " + master.SlaveCount());
}

流式配置​

setENI(String path)​

public EtherCATMaster setENI(String path)

加载 DENI/ENI 配置文件(延迟配置,build 时生效)。

参数:

  • path (String) — DENI 或 ENI 配置文件路径

示例:

EtherCATMaster master = EtherCATMaster.create()
.setENI("C:\\EtherCAT\\MyProject.xml");

SetNetwork(String primary, String secondary)​

public EtherCATMaster SetNetwork(String primary)
public EtherCATMaster SetNetwork(String primary, String secondary)
public int setNetwork(String adapter) // 返回从站数
public int setNetwork(String adapter, String redundantAdapter) // 返回从站数

通过网口名称设置主网口和可选的冗余网口(链式调用版延迟配置;setNetwork 立即设置并返回扫描到的从站数量)。

示例:

EtherCATMaster master = EtherCATMaster.create()
.SetNetwork("\\Device\\NPF_{...}");

// 冗余模式
EtherCATMaster master = EtherCATMaster.create()
.SetNetwork("\\Device\\NPF_{primary}", "\\Device\\NPF_{secondary}");

setEsiFile(String path)​

public EtherCATMaster setEsiFile(String path)

加载单个 ESI 文件(延迟配置,build() 时走 native EcEsi_LoadFile)。可多次调用。

备注

如果使用 DENI 文件,通常不需要单独加载 ESI。

setEsiFiles(String path)​

public EtherCATMaster setEsiFiles(String path)

加载 ESI 文件目录(延迟配置,build() 时走 native EcEsi_LoadDirectory)。可多次调用。

enableAutoStartup()​

public EtherCATMaster enableAutoStartup()

标记需要自动配置从站(build 时执行)。

备注

如果使用 ENI/DENI 文件,通常不需要调用此方法。已有启动参数的从站会被完整跳过,不会被覆盖或补充。此方法仅对未配置的从站生效(自动从 ESI/MDP/SM 生成 PDO/DC/启动参数)。

2.5.x MDP 自动编排

2.5.x 起,启用 enableAutoStartup() 后主站会在进入 OP 时自动检测并配置模块化设备(MDP)(GCAN-8200 等),自动读取已检测模块并下发对应启动参数。详见 MDP。

链式调用覆盖规则

setENI 和 SetNetwork 都可以设置网口。当两者同时使用时,后调用的方法覆盖前面的冲突配置:

// setENI 在后 -> 使用 ENI 文件中的网口配置
EtherCATMaster master = EtherCATMaster.create()
.SetNetwork("以太网 1")
.setENI("C:\\config.xml"); // <- ENI 中的网口覆盖 SetNetwork

// SetNetwork 在后 -> SetNetwork 的网口覆盖 ENI
EtherCATMaster master = EtherCATMaster.create()
.setENI("C:\\config.xml")
.SetNetwork("以太网 1"); // <- 覆盖 ENI 中的网口

ENI/DENI 文件中的从站配置、PDO 映射、DC 设置等始终保留,仅网口配置受覆盖规则影响。enableAutoStartup() 仅对未配置的从站生效,ENI/DENI 已配置的从站会被完整跳过。

构建​

build()​

public BuildResult build()

构建并初始化主站(终结方法)。执行流程:验证配置 → 加载 ESI(setEsiFile / setEsiFiles 队列走 native EcEsi_LoadFile / EcEsi_LoadDirectory,失败不阻断)→ 加载 ENI → EcEsi_AutoMatchAll(已扫到从站且 ESI 入库存时)→ 自动配置。

返回值:

  • BuildResult — 包含主站实例、从站数量、成功标志和消息

BuildResult 结构:

public static class BuildResult {
public final boolean success; // 是否成功(从站数为 0 时为 false)
public final int slaveCount; // 从站数量
public final short masterIndex; // 主站索引
public final String message; // 成功/失败消息
public final EtherCATMaster master; // 主站实例(配置缺失/读文件失败时为 null;从站数为 0 时仍为当前实例)
}

示例:

BuildResult result = EtherCATMaster.create()
.setENI("C:\\EtherCAT\\config.xml")
.SetNetwork("\\Device\\NPF_{...}")
.enableAutoStartup()
.build();

if (!result.success) {
System.out.println("初始化失败: " + result.message);
return;
}

EtherCATMaster master = result.master;
master.setState(EcState.OP);

Validate()​

public ValidationResult Validate()

build 前配置预检查,不执行实际构建。检查 ENI 文件存在性、主站实例上限等。

返回值:

  • ValidationResult — 包含 IsValid (boolean) 和 Errors (List<String>) 字段

示例:

EtherCATMaster master = EtherCATMaster.create().setENI("config.xml");
EtherCATMaster.ValidationResult result = master.Validate();
if (!result.IsValid) {
for (String error : result.Errors) {
System.out.println("配置错误: " + error);
}
return;
}
master.build();

资源释放​

close()​

@Override
public void close()

关闭并清空内存,停止主站和数据采集线程。实现 AutoCloseable 接口,支持 try-with-resources。

try (EtherCATMaster master = EtherCATMaster.create()) {
master.SetNetwork("\\Device\\NPF_{...}");
master.setState(EcState.OP);
master.Start();
// ...
} // 自动释放

Stop()​

public void Stop()

停止主站和 PDO 线程,但保留实例(可后续重新启动)。

emergencyCloseNics()​

public static void emergencyCloseNics()

紧急清理所有主站资源 / 释放网卡句柄。在进程异常退出时调用,避免资源泄漏。

示例:

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
EtherCATMaster.emergencyCloseNics();
}));

多实例管理​

getActiveInstanceCount()​

public static int getActiveInstanceCount()

当前活跃的主站实例数量。

getMaxInstanceCount()​

public static int getMaxInstanceCount()

允许的最大主站实例数量。

网络扫描​

网卡枚举范围

默认只列出已绑定 DarraRT_Eth 的物理有线口。虚拟网卡、WiFi、TAP 不进列表。ASIX 等 USB 有线网卡按物理有线口保留。未绑定口不要当作主口候选(见 isBoundProtocol())。

NetworkInfo.getAvailableNetworks(boolean isRedundant, boolean needSlavesNum)​

public static List<NetworkInfo> getAvailableNetworks(boolean isRedundant, boolean needSlavesNum)
public static List<NetworkInfo> getAvailableNetworks()

获取网卡列表。默认只含已绑定的物理有线口。needSlavesNum=true 时同时扫描每张口的从站数。无参重载不扫描从站数。

参数:

  • isRedundant (boolean) — 是否筛选冗余网络适配器
  • needSlavesNum (boolean) — 是否检测每个网卡上的从站数量(需扫描,较慢)

返回值:

  • List<NetworkInfo> — 网络适配器信息列表

NetworkInfo 结构:

public class NetworkInfo {
public String getName() // 适配器系统名称(用于 SetNetwork)
public String getDescription() // 适配器描述(用户可读)
public String getMacAddress() // MAC 地址
public Integer getSlaveCount() // 从站数量(需 needSlavesNum=true)
public Integer getRedundantSlaveCount() // 受冗余保护的从站数量
public Boolean isBoundProtocol() // 是否已绑定 DarraRT_Eth
public boolean isUp() // 网卡是否在线
}

示例:

List<NetworkInfo> adapters = NetworkInfo.getAvailableNetworks(false, true);
for (NetworkInfo a : adapters) {
Integer count = a.getSlaveCount();
if (count == null || count == 0) continue;
int branch = count - (a.getRedundantSlaveCount() != null ? a.getRedundantSlaveCount() : 0);
System.out.println(a.getDescription() + ": " + count + " 个从站 (分支 " + branch + ")");
}

NetworkInfo.quickSlaveCount(String adapterName)​

public static int quickSlaveCount(String adapterName)

快速从站计数(不读取 EEPROM,仅 BRD)。DENI / 下拉数量走这条。要选用从站请走完整扫描 EtherCATMaster.readSlaveInfo()。数量不得当 0 丢弃。

返回值:

  • int — 检测到的从站数量

EtherCATMaster.readSlaveInfo(String adapterName)​

public static int readSlaveInfo(String adapterName)

扫描从站,扫描结果通过 NetworkInfo.getScannedSlaveInfoList() 获取。

ScannedSlaveInfo 结构:

public static class ScannedSlaveInfo {
public int vendorId; // 厂商 ID
public int productCode; // 产品代码
public int revision; // 修订版本号
public int serialNumber; // 序列号
public String name; // 设备名称
public short configAddr; // 配置地址
public short aliasAddr; // 别名地址
public short parent; // 父从站编号(0=主站是父节点)
public byte topology; // 拓扑类型 (0~4)
public byte activePorts; // 活动端口位图
public byte entryPort; // 入口端口
public byte parentPort; // 父从站上的端口号
public byte physicalType; // 物理端口类型
}

示例:

// 1. 执行扫描
EtherCATMaster.readSlaveInfo("\\Device\\NPF_{...}");

// 2. 获取扫描结果
List<NetworkInfo.ScannedSlaveInfo> slaves = NetworkInfo.getScannedSlaveInfoList();
for (NetworkInfo.ScannedSlaveInfo s : slaves) {
System.out.printf("[%d] %s (VID=0x%08X, PID=0x%08X)%n",
s.configAddr & 0xFFFF, s.name, s.vendorId, s.productCode);
}

NetworkInfo.abortScan()​

public static void abortScan()

中止所有正在进行的扫描操作。用于关闭窗口或取消操作时快速中断阻塞的网络扫描。

示例:

// 在后台线程中扫描
Thread scanThread = new Thread(() -> EtherCATMaster.readSlaveInfo(adapterName));
scanThread.start();

// 用户点击取消
NetworkInfo.abortScan();

版本与授权​

getSerialNumber()​

public static String getSerialNumber()

获取当前设备的序列号(用于授权验证)。

返回值:

  • String — 设备序列号,获取失败时返回空字符串

完整示例​

使用 DENI 文件(推荐)​

EtherCATMaster.BuildResult result = EtherCATMaster.create()
.setENI("C:\\EtherCAT\\MyProject.xml")
.build();

if (!result.success) {
System.out.println("初始化失败: " + result.message);
return;
}

EtherCATMaster master = result.master;
master.setState(EcState.OP);
master.Start();

动态扫描网口​

List<NetworkInfo> adapters = NetworkInfo.getAvailableNetworks(false, true);
NetworkInfo target = adapters.stream()
.filter(a -> a.getSlaveCount() != null && a.getSlaveCount() > 0)
.findFirst().orElse(null);
if (target == null) return;

EtherCATMaster.BuildResult result = EtherCATMaster.create()
.SetNetwork(target.getName())
.setEsiFiles("C:\\ESI")
.enableAutoStartup()
.build();

if (!result.success) return;
EtherCATMaster master = result.master;

冗余模式 (自动识别冗余对)​

List<NetworkInfo> adapters = NetworkInfo.getAvailableNetworks(false, true);
List<NetworkInfo> pair = new java.util.ArrayList<>();
for (NetworkInfo a : adapters) {
if (a.getRedundantSlaveCount() != null && a.getRedundantSlaveCount() > 0) pair.add(a);
}
if (pair.size() < 2) return; // 没找到冗余对

try (EtherCATMaster master = EtherCATMaster.create()) {
master.SetNetwork(pair.get(0).getName(), pair.get(1).getName());
master.setENI("C:\\config.xml");
master.build();
master.setState(EcState.OP);
master.Start();
}

多实例(多网卡独立总线)​

每个主站实例管理一条独立的 EtherCAT 总线,使用不同的网卡。创建新实例无需重启,即时生效。

多实例要求
  • 每个实例必须使用不同的网卡 — 同一网卡不能被多个实例同时使用,SDK 会自动检测并阻止重复绑定
  • CPU 核心自动分配 — 每个实例自动占用不同的 CPU 核心,无需手动设置
  • Mailbox Gateway 端口自动偏移 — 每个实例自动分配不同的端口号
  • 授权与日志共享 — 所有实例共享同一授权状态和日志系统,无冲突
// 实例 1 — 绑定第一张网卡
EtherCATMaster master1 = EtherCATMaster.create();
master1.SetNetwork("\\Device\\NPF_{nic1}");
master1.setState(EcState.OP);
master1.Start();

// 实例 2 — 绑定第二张网卡(即时生效,无需重启)
EtherCATMaster master2 = EtherCATMaster.create();
master2.SetNetwork("\\Device\\NPF_{nic2}");
master2.setState(EcState.OP);
master2.Start();

System.out.println("活跃主站数: " + EtherCATMaster.getActiveInstanceCount());

// 释放时自动归还网卡和端口
master2.close(); // 释放后该网卡可被新实例使用