PnSService
PROFINET IO Device 的入口。启动设备、写 Q / 读 I、看运行态和诊断。实现 AutoCloseable,用 try-with-resources。
本 SDK 只做 PROFINET IO Device,不提供其它现场总线协议的入口。
类结构
PnSService // 设备实例(AutoCloseable)
│
├── processData() → ProcessData // 写 Q / 读 I
│ ├── inputsMapping(Class) / outputsMapping(Class) // 0 拷贝,映射一次
│ ├── readStruct / writeStruct // 快照,值不会自己变
│ ├── in() // 读 I(模块输入),只读
│ └── out() // 写 Q(模块输出),可写
├── events() → PnSEvents // 运行态事件
│ ├── addConnectedChangedListener // 周期交换通断
│ ├── addStateChangedListener // 运行态变化
│ ├── addErrorOccurredListener // 运行错误
│ └── addLoggedListener // 上面每条都会再打这条
├── diagnostics() → PnSDiagnostics // 诊断子对象(快照 / IOPS / 报警 / 记录)
│ ├── snapshot() // 诊断快照
│ ├── ioStatus() // IOPS / IOCS
│ ├── getAlarms() / getAlarmHistory() // 本机报警 / 历史
│ └── getRecords() // 用户区记录
│
├── connected() / status() / waitReason() // 周期交换 / 运行态 / 等待原因
├── everConnected() / errorCodeEnum() // 曾经连上 / 运行错误
└── getImData() // I&M 标识
写 Q(模块输出,设备 → 控制器),读 I(模块输入,控制器 → 设备)。扁平方法
diagSnapshot()/getAlarms()仍可用,与diagnostics()同一数据。
PnSDiagnostics 在 com.darra.pns.service 子包里(和入口 PnSService 同一个包)。要写出这个类型名就 import com.darra.pns.service.PnSDiagnostics; —— 不是 com.darra.pns.PnSDiagnostics,那个包只有 PnSDiagSnapshot / PnSIoStatus 这类快照类型。
用法
启停
import com.darra.pns.service.PnSService;
try (PnSService device = new PnSService()) {
device.start();
while (running) {
if (!device.connected()) {
// device.waitReason()
continue;
}
device.writeBool("Q0.0", true); // 写 Q
boolean fromPlc = device.readBool("I0.0"); // 读 I
}
device.stop();
}
看状态不必 new:PnSService.isServiceReady() / serviceConnected() / serviceWaitReason()。
过程数据
| 方式 | 访问 | 说明 |
|---|---|---|
| 过程数据 | device.processData().inputsMapping(Class) / outputsMapping(Class) | 0 拷贝,映射一次 |
| 过程数据 | device.processData() | 快照 readStruct / writeStruct、in() / out() 字节 |
标识
PnSService.ImData im = device.getImData();
String name = im.stationName();
int vendor = im.vendorId();
int product = im.deviceId();
过程数据读写
字 / 双字为大端。详见 过程数据。
金路径是 0 拷贝:映射一次,源头变字段自己变。Structure 字段是托管缓存 —— 读最新要 read(),改完要 write()。
import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;
@FieldOrder({"a", "b", "flag"})
class FromPlc extends Structure {
public byte a;
public short b;
public boolean flag;
public FromPlc() { super(ALIGN_NONE); }
}
// 0 拷贝:映射一次
FromPlc inp = device.processData().inputsMapping(FromPlc.class);
FromPlc outp = device.processData().outputsMapping(FromPlc.class);
inp.read(); // 过程映像 → 托管缓存
byte present = inp.a; // 总线刷新后自己变
outp.a = 1;
outp.write(); // 托管缓存 → 过程映像
device.processData().out().get(0).setContent((byte) 0x11);
byte v = device.processData().in().get(0).getContent();
快照走 readStruct / writeStruct(实现 ProcessData.Packed 的 packedSize / pack / unpack)—— 拷出来的实例不会自己变。
诊断与报警
通过 device.diagnostics() 读诊断(只读快照:链路、帧计数、看门狗、抖动与报警观测)。详见 诊断。事件见 事件。
import com.darra.pns.PnSDiagSnapshot;
PnSDiagSnapshot snap = device.diagnostics().snapshot();
if (!snap.ok())
System.out.println(snap.message());
for (PnSService.AlarmItem a : device.diagnostics().getAlarms())
System.out.println(a.message());