跳到主要内容

诊断

通过 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()longIO 连接激活 / 健康位图
计数heartbeat() / cycleCounter()long心跳 / 周期循环计数
计数lastError()long最近错误码(0 = 无)
计数rxFrames() / txFrames()long收 / 发总帧数
计数rxRtFrames() / txRtFrames()long收 / 发 RT 周期帧
计数droppedFrames() / invalidFrames()long被丢弃 / 非法帧
计数watchdogTrips()long看门狗超时次数
计数lastRxTsc() / lastTxTsc()long最近收 / 发帧 TSC
过程区inputAreaLength() / outputAreaLength()longI 区 / 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&M0vendorId() / deviceId()int厂商 / 设备 ID
I&M0orderId()String订货号
I&M0serialNumber()String序列号
I&M0hardwareRevision() / softwareRevision()String硬件 / 软件版本
身份stationName()String站点名
身份productName()String产品名
能力imSupported()String已启用的 I&M 记录集,按原生栈掩码如实拼;从站未启动时只报 I&M0
能力im14Supported()booleanI&M1–4 是否读回成功;从站未启动读不到为 false,字段为空串
I&M1–4im1TagFunction() / im1TagLocation()String功能标签 / 安装位置
I&M1–4im2Date()String日期
I&M1–4im3Descriptor()String描述
I&M1–4im4SignatureHex()String签名(十六进制)
工程imNote()StringI&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");