跳到主要内容

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() 同一数据。

PnSDiagnosticscom.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();
}

看状态不必 newPnSService.isServiceReady() / serviceConnected() / serviceWaitReason()

过程数据

方式访问说明
过程数据device.processData().inputsMapping(Class) / outputsMapping(Class)0 拷贝,映射一次
过程数据device.processData()快照 readStruct / writeStructin() / 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.PackedpackedSize / 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());