诊断
通过 device.diagnostics() 读诊断与报警(diagSnapshot() / getAlarms() 仍可用)。
配合事件使用
建议用 事件 处理异常,而非自行轮询。 直接读取诊断方法适用于 UI 显示等场景。
运行态(connected() / status() / errorCodeEnum())见 属性与状态机,本页只讲诊断快照、IOPS/IOCS 和报警。过程数据读写见 过程数据。
功能概览
| 功能 | 说明 |
|---|---|
| 诊断快照 | 链路、帧计数、看门狗、抖动、报警观测 |
| 现场问题对照 | 按症状选字段 |
| 过程数据质量 | IOPS / IOCS:数据 GOOD 还是 BAD |
| 报警 | 活动列表 / 历史 / 确认 |
诊断快照
| 类别 | 成员 | 类型 | 说明 |
|---|---|---|---|
| 可用性 | ok() | boolean | 诊断是否可用。false = 设备未启动,读 message() |
| 可用性 | sharedMemoryMapped() | boolean | 过程数据是否已就绪 |
| 可用性 | message() | String | 不可用时的原因;可用时为空 |
| 可用性 | timestamp() | String | 快照时刻。缺字段为空 |
| 链路 | state() | String | 运行状态文案 |
| 链路 | linkUp() | boolean | 网卡链路是否 Up |
| 链路 | connected() | boolean | 周期数据是否正常 |
| 链路 | activeIocrCount() | long | 已激活的 IO 连接数 |
| 链路 | iocrActive() / iocrHealthy() | long | IO 连接激活 / 健康位图 |
| 计数 | heartbeat() / cycleCounter() | long | 心跳 / 周期循环计数 |
| 计数 | lastError() | long | 最近错误码(0 = 无) |
| 计数 | rxFrames() / txFrames() | long | 收 / 发总帧数 |
| 计数 | rxRtFrames() / txRtFrames() | long | 收 / 发 RT 周期帧 |
| 计数 | droppedFrames() / invalidFrames() | long | 被丢弃 / 非法帧 |
| 计数 | watchdogTrips() | long | 看门狗超时次数 |
| 计数 | lastRxTsc() / lastTxTsc() | long | 最近收 / 发帧 TSC |
| 过程区 | inputAreaLength() / outputAreaLength() | long | I 区 / Q 区长度(字节) |
| 周期 | stackCycles() | long | 周期计数 |
| 周期 | stackFramesRx() / stackFramesTx() | long | 收 / 发帧 |
| 周期 | stackMissedTicks() | long | 错过的节拍 |
| 周期 | stackMaxJitterUs() | long | 最大抖动(微秒) |
| 报警观测 | stackAlarmRxCount() | long | 收到控制器报警总数 |
| 报警观测 | stackAlarmTxAckOk() / stackAlarmTxAckFail() | long | 本机报警被确认 / 确认失败 |
| 报警观测 | stackAlarmAckPending() | long | 在途报警(0/1) |
| 报警观测 | stackAlarmMaintState() | long | 维护请求状态 |
| 报警观测 | stackAlarmLastArep() 等 | long | 最近控制器报警:Arep / Slot / Subslot / Type / Seq / Usi / Len |
| 错误 | errorCode() | int | 错误码原值(0 = 无) |
| 错误 | errorCodeEnum() | PnSRuntimeErrorCode | 上项的枚举。未识别值为 UNKNOWN |
diagSnapshot()
public PnSDiagSnapshot diagSnapshot()
public PnSDiagSnapshot getDiag()
一次取回当前诊断快照,适合界面刷新和日志。两方法同义。设备尚未启动时 ok() == false,读 message(),不视为异常。
示例:
PnSDiagSnapshot snap = device.diagSnapshot();
if (!snap.ok()) {
System.out.println(snap.message());
return;
}
System.out.println(snap.linkUp() ? "Up" : "Down");
System.out.println(snap.connected() ? "周期交换正常" : "未建立");
System.out.println("帧: " + snap.rxFrames() + " / " + snap.txFrames());
System.out.println("看门狗: " + snap.watchdogTrips());
现场问题对照
| 现场症状 | 看哪些字段 |
|---|---|
| 网线没插好 | diagSnapshot().linkUp() |
| 周期数据通不通 | diagSnapshot().connected() |
| 看门狗反复跳 | diagSnapshot().watchdogTrips() |
| 帧在丢 | droppedFrames() + invalidFrames() |
| 周期稳不稳 | stackMaxJitterUs() + stackMissedTicks() |
| 控制器报警没消化 | stackAlarmAckPending() / stackAlarmTxAckFail() |
| 本机有没有活动报警 | getAlarms() / alarmCount() |
| 过程数据能不能信 | ioStatus().allGood() |
过程数据质量
ioStatus()
public PnSIoStatus ioStatus()
每个过程数据字节对应一个状态字节:0x80 = GOOD,0x00 = BAD。掉线如实全 BAD,不虚构 GOOD。未启动或失败返回 PnSIoStatus.empty(),不抛。
| 类别 | 成员 | 类型 | 说明 |
|---|---|---|---|
| 状态字节 | inputIops() / inputIocs() | byte[] | I 区:控制器提供 / 本设备消费后回报。拷贝,改了不影响本对象 |
| 状态字节 | outputIops() / outputIocs() | byte[] | Q 区:本设备提供 / 控制器消费后回报 |
| 判据 | inputValid() / outputValid() | boolean | 本轮是否收到过 I 区 / Q 写过且已送达控制器(掉线、未送出 = false) |
| 判据 | inputDataGood() | boolean | 收到过 I 且输入 IOPS 全 GOOD |
| 判据 | outputDataGood() | boolean | 写过 Q 且输出 IOPS 全 GOOD |
| 判据 | outputConsumed() | boolean | 输出 IOCS 全 GOOD(控制器已消费) |
| 判据 | allGood() | boolean | 输入有效 + 输出有效 + 输出已消费 |
| 工厂 | PnSIoStatus.empty() | 静态方法 | 空状态(未启动 / 读不到) |
public enum PnSIoxs {
BAD(0x00), // 数据无效
GOOD(0x80) // 数据有效
}
示例:
PnSIoStatus io = device.ioStatus();
if (!io.allGood()) {
System.out.println(io);
if (!io.inputDataGood())
System.out.println("控制器送来的数据不可用");
}
报警
public int alarmCount()
public int criticalAlarmCount()
public java.util.List<AlarmItem> getAlarms()
public java.util.List<AlarmItem> getAlarmHistory()
public void ackAlarm(String id)
public int ackAllAlarms()
无活动报警返回空列表,不是失败。历史最近 500 条,时间升序。失败抛 PnSServiceException。
getAlarms()
public java.util.List<AlarmItem> getAlarms()
当前活动报警。无活动报警返回空列表,不是失败。
示例:
for (PnSService.AlarmItem a : device.getAlarms())
System.out.println(a);
getAlarmHistory()
public java.util.List<AlarmItem> getAlarmHistory()
报警历史(最近 500 条,时间升序)。无历史返回空列表,不是失败。
示例:
for (PnSService.AlarmItem a : device.getAlarmHistory())
System.out.println(a.occurredAt() + " " + a.severity() + " " + a.message());
ackAlarm(String id)
public void ackAlarm(String id)
确认一条活动报警。ID 取自 getAlarms()。空串 / 无此 ID 抛 PnSServiceException。
示例:
device.ackAlarm("PnS.LinkDown");
ackAllAlarms()
public int ackAllAlarms()
确认全部活动报警。返回被确认条数(0 = 无活动报警)。
示例:
int n = device.ackAllAlarms();
AlarmItem
| 属性 | 类型 | 说明 |
|---|---|---|
id() | String | 报警 ID(如 PnS.LinkDown) |
severity() | String | 严重度:Info / Warning / Error / Critical |
message() | String | 报警消息 |
occurredAt() | OffsetDateTime | 最近一次发生时间。解析失败为 null |
count() | int | 发生次数(≥1) |
source() | String | 来源 |
I&M 标识
getImData()
public ImData getImData()
设备标识。I&M1–I&M3 已由原生栈启用并如实回读,I&M4 未启用(主站没写过时读到的是栈的出厂占位值)。缺字段保持空 / 0 / false,不虚构。imSupported() 是 String,不是 int;这次读到什么看 im14Supported() / imNote()。
| 类别 | 成员 | 类型 | 说明 |
|---|---|---|---|
| I&M0 | vendorId() / deviceId() | int | 厂商 / 设备 ID |
| I&M0 | orderId() | String | 订货号 |
| I&M0 | serialNumber() | String | 序列号 |
| I&M0 | hardwareRevision() / softwareRevision() | String | 硬件 / 软件版本 |
| 身份 | stationName() | String | 站点名 |
| 身份 | productName() | String | 产品名 |
| 能力 | imSupported() | String | 已启用的 I&M 记录集,按原生栈掩码如实拼;从站未启动时只报 I&M0 |
| 能力 | im14Supported() | boolean | I&M1–4 是否读回成功;从站未启动读不到为 false,字段为空串 |
| I&M1–4 | im1TagFunction() / im1TagLocation() | String | 功能标签 / 安装位置 |
| I&M1–4 | im2Date() | String | 日期 |
| I&M1–4 | im3Descriptor() | String | 描述 |
| I&M1–4 | im4SignatureHex() | String | 签名(十六进制) |
| 工程 | imNote() | String | I&M 口径说明 |
| 工程 | projectOrderNumber() | String | 工程订货号 |
| 工程 | projectHardwareRelease() / projectSoftwareRelease() | String | 工程硬件 / 软件版本 |
示例:
PnSService.ImData im = device.getImData();
System.out.println(im.stationName());
System.out.println(im.orderId());
用户记录
getRecords()
public UserRecords getRecords()
用户区记录。空列表不是失败。
public static final class UserRecord {
public int slot() { }
public int subslot() { }
public int index() { }
public int length() { }
public String dataHex() { }
}
public static final class UserRecords {
public UserRecord[] records() { }
public int count() { }
public String timestamp() { }
}
示例:
PnSService.UserRecords recs = device.getRecords();
int n = recs.count();
复位
resetDevice(String mode)
public void resetDevice(String mode)
复位设备。mode 非法 / 服务拒绝抛 PnSServiceException。这是慢操作,不要当失败误杀。
参数:
mode(String) —communication通信复位(软停再启,记录保留);factory工厂复位(销毁后全新启动,记录清空)
示例:
device.resetDevice("communication");