Java API 参考
Java SDK(Maven 包 com.darra.pnet,JNA 绑定原生 DarraPnet.dll)。含两种形态:服务模式(推荐) — PnetService 单一入口,经 Pnet Service 内置 HTTP API(端口 18840 固定)连接,由服务承载从站运行(JDK 内置 HttpURLConnection,不依赖 native DLL);native 直连(备选) — 应用内创建 PnetDevice → 初始化(PnetStackConfig)→ 启动 → 周期驱动(tick())→ 槽位 IO 读写。命名采用 Java 惯例(camelCase),语义与 C# 页一致。
单一 PROFINET 网口契约(audit-2026-08-11,用户裁定 2026-08-10):设备对外只开放一个 PROFINET 网口(工业现场常态)。网卡选择在 GUI / Service 配置层完成,服务侧单一权威 =
NetworkInterfaceName(读取链:环境变量DARRA_PNET_NIC> 运行配置 XML<Network/InterfaceName>> appsettings 出厂默认;驱动绑定 / pnal 绑定目标 / MAC 解析同源一致,无双配置歧义)。native 直连模式下PnetStackConfig的网卡名为栈绑定的唯一网口名;EnumerateInterfaces()仅作诊断/枚举用途。
import com.darra.pnet.*;
概览
| 类 | 包 | 职责 |
|---|---|---|
PnetDevice | com.darra.pnet | 设备创建 / 初始化 / 启停 / 周期驱动 |
PnetSlave | com.darra.pnet | 从站控制(栈状态 / 站名 / IP) |
PnetIo | com.darra.pnet | 槽位过程数据读写 |
PnetAlarm | com.darra.pnet | 报警发送 / 应答 |
PnetConfig | com.darra.pnet | 运行配置(站名 / IP / LED) |
PnetDiag | com.darra.pnet | 诊断统计 |
PnetStackConfig | com.darra.pnet.jnative | 栈配置(builder) |
PnetService — 服务模式(推荐,已实现)
经服务 HTTP API(端口 18840 固定)连接服务,由服务承载从站运行;SDK 与 Web API 同层。启停(POST /api/start|stop)/ IO(GET|POST /api/io)全部经服务转发,不直连 native。连接复用:JVM keep-alive 连接池按 host:port 复用底层 TCP 连接(对齐 C# 共享 HttpClient)。
import com.darra.pnet.service.PnetService;
try (PnetService service = new PnetService()) {
service.connect("127.0.0.1", PnetService.DEFAULT_PORT, null); // 端口固定 18840
service.start(); // POST /api/start
service.writeBool("I0.0", true); // 写输入位(设备 → 控制器)
service.writeInt16("IW2", (short) 0x1234); // 写输入字(大端)
boolean start = service.readBool("Q0.0"); // 读输出位(控制器 → 设备)
short cmd = service.readInt16("QW2"); // 读输出字(大端)
byte[][] io = service.getIo(); // 服务端过程映像快照([I 区, Q 区])
service.stop(); // POST /api/stop(幂等)
}
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
connect(host, port, apiKey) | void | 设备 | 写 | 连接服务(仅本地回环 127.0.0.1 可达,audit-2026-08-10:服务未开放局域网监听;端口固定 18840;服务端配置 API 密钥后必传) |
DEFAULT_PORT | int | 设备 | 只读 | 服务 HTTP API 固定端口 18840 |
start() | void | 设备 | 写 | 启动从站(POST /api/start,由服务承载;失败如实抛 PnetServiceException) |
stop() | void | 设备 | 写 | 停止从站(POST /api/stop,幂等) |
status() | PnetState | 设备 | 只读 | 服务端运行态(GET /api/status 映射) |
statusEx() | ServiceStatus | 设备 | 只读 | 服务端运行态快照(GET /api/status 一次取回 state / connected / errorCode;用户裁定 2026-08-10:错误码是调用契约的一部分,SDK 必须透出服务端 connected / errorCode) |
isConnected() / isStarted() | boolean | 设备 | 只读 | 会话 / 本地启动状态 |
readBool(address) / writeBool(address, value) | boolean / void | IO | 读写 | 位地址(I0.0 / Q0.0 / M1.6 / DB1.DBX0.0;Q 区只读,写抛异常) |
readInt16(address) / writeInt16(address, value) | short / void | IO | 读写 | 字地址(IW2 / QW2 / MW0 / DB1.DBW0,大端) |
readInt32(address) / writeInt32(address, value) | int / void | IO | 读写 | 双字地址(ID4 / QD4 / MD0 / DB1.DBD0,大端) |
getIo() | byte[][] | IO | 只读 | 服务端过程映像快照([0] = I 区,[1] = Q 区) |
parseAddress(text) | Address | IO | 静态 | 解析 HSL 式地址(对齐 C# PnetAddress.Parse) |
地址格式(与 C# 基准一致):I0.0 / IB0 / IW2 / ID4(I 区输入面)、Q0.0 / QB0 / QW2 / QD4(Q 区输出面,只读)、M0.0 / MB0 / MW100 / MD0(内部存储)、DB1.DBX0.0 / DB1.DBB2 / DB1.DBW0 / DB1.DBD4(DB 区槽位 1 数据块)。字 / 双字大端序,偏移即字节偏移、不强制 2 / 4 对齐(IW3 合法);连接服务模式为单一线性过程区,DB 仅槽位 1 有效(槽位 > 1 抛 PnetServiceException)。
statusEx() 返回 ServiceStatus(state() / connected() / errorCode() / errorCodeEnum()):connected() = 是否已与 IO 控制器建立周期数据交换(GET /api/status 的 connected 原值),errorCode() = 最近一次错误码原值(0 = 无错误;非零 = pnet 栈错误码),errorCodeEnum() = 枚举化映射(PnetRuntimeErrorCode:OK=0 / ERR_INIT=-1 / ERR_CFG=-2 / ERR_THREAD=-3 / ERR_RUNNING=-4 / ERR_PDI=-5 / UNKNOWN=-10000;未识别值如实返回 UNKNOWN,原始值仍经 errorCode() 透传)。
PnetDevice — 设备(native 直连,备选)
try (PnetDevice dev = new PnetDevice()) { // 加载 DarraPnet.dll(JNA 搜索路径)
dev.initialize(PnetStackConfig.builder() // 初始化栈
.stationName("darra-slave-01")
.ipText("192.168.1.100")
.periodUs(1000)
.build());
dev.start(); // 启动周期循环
dev.tick(); // 周期驱动(按 period_us 循环调用)
dev.stop();
} // try-with-resources 自动释放
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
PnetDevice() | PnetDevice | 设备 | 构造 | 创建设备实例(AutoCloseable,自动释放) |
initialize(PnetStackConfig config) | void | 设备 | 写 | 初始化栈(D_1001 + D_2001,幂等) |
start() | void | 设备 | 写 | 启动周期循环(D_2002) |
stop() | void | 设备 | 写 | 停止(D_2003) |
tick() | void | 设备 | 写 | 周期驱动(D_1004,应用线程按 period_us 循环调用) |
shutdown() / close() | void | 设备 | 写 | 释放设备(stop + D_2005 销毁,幂等) |
slave() | PnetSlave | 设备 | 只读 | 从站控制对象 |
state() | PnetState | 设备 | 只读 | 设备状态枚举 |
stackState() | PnetStackState | 设备 | 只读 | 栈状态枚举 |
isInitialized() / isStarted() | boolean | 设备 | 只读 | 初始化 / 启动状态 |
static version() | String | 设备 | 静态 | DLL 核心版本字符串 |
PnetSlave — 从站
PnetSlave slave = dev.slave();
slave.setName("darra-pnet-01");
slave.setIp("192.168.1.100", "255.255.255.0", "192.168.1.1");
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
stackState() | PnetStackState | 从站 | 只读 | 栈状态枚举 |
isRunning() | boolean | 从站 | 只读 | 是否运行中 |
setName(String stationName) | void | 从站 | 写 | 设置站点名 |
setIp(String ip, String mask, String gateway) | void | 从站 | 写 | 设置静态 IP 配置 |
applicationReady() | void | 从站 | 写 | 应用就绪(APPLRDY) |
abortConnections() | void | 从站 | 写 | 中止连接 |
signalLed(PnetLedState state) | void | 从站 | 写 | LED 状态 |
PnetIo — 槽位过程数据
PnetIo io = new PnetIo(dev);
io.writeInput(1, 1, new byte[] { (byte)0xAA, 0x01 }); // 设备 → 控制器
OutputReadResult out = io.readOutput(1, 1, 16); // 控制器 → 设备
if (out.isNewData()) { byte[] data = out.data(); }
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
plugModule(slot, moduleIdent, properties) | void | IO | 写 | 插入模块 |
plugSubmodule(slot, subslot, moduleIdent, submoduleIdent, ...) | void | IO | 写 | 插入子模块 |
pullModule(slot) / pullSubmodule(slot, subslot) | void | IO | 写 | 拔出模块 / 子模块 |
writeInput(slot, subslot, byte[] data) | void | IO | 写 | 写槽位输入(设备 → 控制器) |
inputIocs(slot, subslot) | PnetIoxs | IO | 只读 | 输入数据质量状态(IOPS) |
readOutput(slot, subslot, capacity) | OutputReadResult | IO | 只读 | 读槽位输出(控制器 → 设备,含 IOCS / 新增标志) |
writeOutputIocs(slot, subslot, iocs) | void | IO | 写 | 主动设置输出区 IOCS |
OutputReadResult:data() 输出数据字节、iops() 质量状态、isNewData() 是否新帧、mode() IO 模式。
PnetAlarm — 报警
dev.slave().alarm().sendProcess(1, 1, new byte[] { 0x01 });
dev.slave().alarm().sendAck(1, 1, 0, PnetAlarmType.PROCESS);
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
sendProcess(slot, subslot, byte[] payload) | void | 报警 | 写 | 发送过程报警 |
sendProcess(slot, subslot) | void | 报警 | 写 | 发送过程报警(无负载) |
sendAck(slot, subslot, alarmSeq, alarmType) | void | 报警 | 写 | 应答报警确认 |
PnetConfig — 配置
dev.slave().config().setStationName("darra-pnet-01");
dev.slave().config().setIpSuite("eth0", ipInt, maskInt, gwInt);
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
setStationName(String name) | void | 配置 | 写 | 设置站点名 |
setIpSuite(String interfaceName, int ipAddr, int ipMask, int ipGateway) | void | 配置 | 写 | 设置网络配置(IP 主机序 uint32) |
setLed(int ledRed, int ledGreen) | void | 配置 | 写 | 设置 LED |
PnetDiag — 诊断
PnetStackStats stats = new PnetDiag(dev).stackStats();
System.out.println(stats.cycles() + " 周期, " + stats.frameRx() + " 收帧");
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
stackStats() | PnetStackStats | 诊断 | 只读 | 栈统计(周期 / 收帧 / 发帧 / 抖动) |
wrapperErrorCode() | int | 诊断 | 只读 | 包装层错误码 |
lastError() | int | 诊断 | 只读 | 最近错误码 |
cycles() / frameRx() / frameTx() / missedTicks() / maxJitterUs() | long | 诊断 | 只读 | 周期 / 收帧 / 发帧 / 丢拍 / 最大抖动 |
完整示例
import com.darra.pnet.*;
import com.darra.pnet.jnative.PnetStackConfig;
try (PnetDevice dev = new PnetDevice()) {
dev.initialize(PnetStackConfig.builder()
.stationName("darra-pnet-01")
.ipText("192.168.1.100")
.periodUs(1000)
.build());
dev.start();
PnetIo io = new PnetIo(dev);
byte[] input = new byte[] { 0x00, 0x00, (byte) 0xAA };
for (int i = 0; i < 100; i++) {
dev.tick(); // 周期驱动
input[2] = (byte) (input[2] + 1);
io.writeInput(1, 1, input); // 设备 → 控制器
var out = io.readOutput(1, 1, 8); // 控制器 → 设备
Thread.sleep(10);
}
}
Maven 依赖
<dependency>
<groupId>com.darra</groupId>
<artifactId>darra-pnet</artifactId>
<version>1.0.0</version>
</dependency>