跳到主要内容

诊断

通过 device.Diagnostics 读诊断与报警(DiagSnapshot / Alarms 仍可用,同一数据)。​

配合事件使用

建议通过 事件 驱动异常处理,而非自行轮询。 直接读取诊断属性适用于 UI 显示等场景。

运行态(Connected / State / ErrorCode)见 属性与状态机,本页只讲诊断快照、IOPS/IOCS 和报警。过程数据读写见 过程数据。

功能概览​

功能说明
诊断快照链路、帧计数、看门狗、抖动、报警观测
IOPS / IOCS过程数据质量:数据 GOOD 还是 BAD
现场问题对照按症状选字段
报警活动列表 / 历史 / 确认
用户记录用户区记录表(D_2014)
复位通信复位 / 工厂复位

诊断快照​

类别属性类型访问说明
可用性Okbool只读诊断是否可用。false = 设备未启动,读 Message
SharedMemoryMappedbool只读过程数据是否已就绪
Messagestring只读不可用时的原因;可用时为空
TimestampDateTime只读快照生成时刻
链路Statestring只读运行状态文案
LinkUpbool只读网卡链路是否 Up
Connectedbool只读周期数据是否正常
ActiveIocrCountuint只读已激活的 IO 连接数
IocrActiveuint只读IO 连接激活位图
IocrHealthyuint只读IO 连接健康位图
计数Heartbeatulong只读心跳计数
CycleCounterulong只读周期循环计数
LastErrorulong只读最近错误码(0 = 无)
RxFrames / TxFramesulong只读收 / 发总帧数
RxRtFrames / TxRtFramesulong只读收 / 发 RT 周期帧
DroppedFramesulong只读被丢弃的帧
InvalidFramesulong只读非法帧
WatchdogTripsulong只读看门狗超时次数
LastRxTsc / LastTxTsculong只读最近收 / 发帧 TSC
过程区InputAreaLengthuint只读输入区长度(字节)
OutputAreaLengthuint只读输出区长度(字节)
周期StackCyclesulong只读周期计数
StackFramesRx / StackFramesTxulong只读收 / 发帧
StackMissedTicksulong只读错过的节拍
StackMaxJitterUsulong只读最大抖动(微秒)
报警观测StackAlarmRxCountulong只读收到控制器报警总数
StackAlarmTxAckOkulong只读本机报警被确认次数
StackAlarmTxAckFailulong只读本机报警确认失败次数
StackAlarmAckPendingulong只读在途报警(0/1)
StackAlarmMaintStateulong只读维护请求状态
StackAlarmLastArepuint只读最近控制器报警:Arep
StackAlarmLastSlotuint只读最近控制器报警:槽位
StackAlarmLastSubslotuint只读最近控制器报警:子槽位
StackAlarmLastTypeuint只读最近控制器报警:类型
StackAlarmLastSequint只读最近控制器报警:序列号
StackAlarmLastUsiuint只读最近控制器报警:USI
StackAlarmLastLenuint只读最近控制器报警:负载长度
错误ErrorCodeint只读错误码原值(0 = 无)
ErrorCodeEnumPnSRuntimeErrorCode只读上项的枚举形态。未识别值为 Unknown

DiagSnapshot​

public PnSDiagSnapshot DiagSnapshot { get; }

一次取回当前诊断快照,适合界面刷新和日志。设备尚未启动时 Ok == false,读 Message,不视为异常。

返回值:

  • PnSDiagSnapshot — 诊断数据快照

失败抛 PnSServiceException。GetDiag 已废弃,用本属性。

示例:

PnSDiagSnapshot snap = device.DiagSnapshot;
if (!snap.Ok)
{
Console.WriteLine(snap.Message);
return;
}

Console.WriteLine(snap.LinkUp ? "Up" : "Down");
Console.WriteLine(snap.Connected ? "周期交换正常" : "未建立");
Console.WriteLine($"帧: {snap.RxFrames} / {snap.TxFrames}");
Console.WriteLine($"看门狗: {snap.WatchdogTrips}");

IOPS / IOCS​

IoStatus​

public PnSIoStatus IoStatus { get; }

每个过程数据字节对应一个状态字节:0x80 = GOOD,0x00 = BAD。掉线如实全 BAD,不虚构 GOOD。未启动或读不到返回 PnSIoStatus.Empty(判据全 false),不抛。device.Diagnostics.IoStatus 与本属性同一数据。

返回值:

  • PnSIoStatus — IOPS / IOCS 快照
类别属性类型访问说明
状态字节InputIops / InputIocsbyte[]只读I 区:控制器提供 / 本设备消费后回报。返回拷贝,改了不影响本对象
OutputIops / OutputIocsbyte[]只读Q 区:本设备提供 / 控制器消费后回报
判据InputValid / OutputValidbool只读本轮收到过 I 区 / 写过 Q 且已送达控制器(掉线、未送出 = false)
InputDataGoodbool只读收到过 I 且输入 IOPS 全 GOOD
OutputDataGoodbool只读写过 Q 且输出 IOPS 全 GOOD
OutputConsumedbool只读输出 IOCS 全 GOOD(控制器已消费)
AllGoodbool只读输入数据有效 + 输出数据有效 + 输出已消费
工厂PnSIoStatus.EmptyPnSIoStatus只读空状态(未启动 / 读不到)。判据全 false

示例:

PnSIoStatus io = device.IoStatus;
if (!io.AllGood)
{
Console.WriteLine(io);
if (!io.InputDataGood)
Console.WriteLine("控制器送来的数据不可用");
}

现场问题对照​

现场症状看哪些字段
网线没插好DiagSnapshot.LinkUp
周期数据通不通DiagSnapshot.Connected
看门狗反复跳DiagSnapshot.WatchdogTrips
帧在丢DroppedFrames + InvalidFrames
周期稳不稳StackMaxJitterUs + StackMissedTicks
控制器报警没消化StackAlarmAckPending / StackAlarmTxAckFail
本机有没有活动报警Alarms / AlarmCount

报警​

类别属性类型访问说明
计数AlarmCountint只读活动报警总数。与 Alarms 同源
CriticalAlarmCountint只读Critical 报警数
列表AlarmsList<PnSAlarmItem>只读当前活动报警。空列表 = 无活动报警,不是失败
AlarmHistoryList<PnSAlarmItem>只读历史(最近 500 条,时间升序)。空列表 = 无历史

GetAlarms / GetAlarmHistory 已废弃,用属性。失败抛 PnSServiceException。

Alarms​

public List<PnSAlarmItem> Alarms { get; }

当前活动报警。无活动报警返回空列表,不是失败。

返回值:

  • List<PnSAlarmItem> — 活动报警列表

示例:

foreach (PnSAlarmItem a in device.Alarms)
Console.WriteLine(a.ToString());

AlarmHistory​

public List<PnSAlarmItem> AlarmHistory { get; }

报警历史(最近 500 条,时间升序)。无历史返回空列表,不是失败。

返回值:

  • List<PnSAlarmItem> — 历史列表

示例:

foreach (PnSAlarmItem a in device.AlarmHistory)
Console.WriteLine($"{a.OccurredAt:s} {a.Severity} {a.Message}");

AcknowledgeAlarm​

public void AcknowledgeAlarm(string id)

确认一条活动报警。ID 取自 Alarms。

参数:

  • id (string) — 报警 ID。空串抛 ArgumentException;无此 ID 抛 PnSServiceException

示例:

device.AcknowledgeAlarm("PnS.LinkDown");

AcknowledgeAllAlarms​

public int AcknowledgeAllAlarms()

确认全部活动报警。

返回值:

  • int — 被确认条数(0 = 无活动报警)

示例:

int n = device.AcknowledgeAllAlarms();
PnSAlarmItem
属性类型说明
Idstring报警 ID(如 PnS.LinkDown)
Severitystring严重度:Info / Warning / Error / Critical
Messagestring报警消息
OccurredAtDateTime最近一次发生时间
Countint发生次数(≥1)
Sourcestring来源

用户记录​

Records​

public PnSUserRecords Records { get; }

取用户区记录表(D_2014,Index 0x0000–0x7FFF)。缺字段默认 0 / 空,不虚构。没有记录返回空表,不是失败。device.Diagnostics.Records 与本属性同一数据。

这个表里没有 I&M 记录

用户区记录(0x0000–0x7FFF)和 I&M(0xAFF0–0xAFF4)是两个不同的索引空间,走两个不同端点:本属性读 /api/records,只覆盖用户区;I&M 在 ImData(/api/im)。

别把两个端点当成一张表去找 —— 在 Records 里翻 I&M 的 index 是找不到的。

失败抛 PnSServiceException:服务不可达是 ServiceUnreachable,服务端非 200 是 NativeError(带服务端 errorCode)。GetRecords 已废弃,用本属性。

返回值:

  • PnSUserRecords — 记录表

示例:

PnSUserRecords recs = device.Records;
foreach (PnSUserRecord r in recs.Records)
Console.WriteLine(
$"slot {r.Slot}/{r.Subslot} index 0x{r.Index:X4} len {r.Length} {r.DataHex}");
PnSUserRecords
属性类型说明
RecordsPnSUserRecord[]记录数组(空 = 没有记录,不是失败)
Countint服务端计数(缺字段为 0,不按数组长度回填)
TimestampDateTime快照生成时刻(缺字段为 DateTime.MinValue)
PnSUserRecord
属性类型说明
Slotushort槽位
Subslotushort子槽位
Indexushort记录 Index
Lengthushort负载字节数
DataHexstring负载十六进制(缺字段为空串)

复位​

ResetDevice()​

public void ResetDevice(string mode)

复位从站。走服务端既有的启停状态机,不杀服务进程。

mode行为
"communication"软停再启,应用参数记录保留
"factory"销毁后全新启动,应用参数记录清空

通讯参数 / IP 的复位不由本方法负责,仍由控制器 DCP ResetToFactory 触发。

参数:

  • mode (string) — "communication" 或 "factory"。空串或其它值抛 ArgumentException

失败: 服务不可达 / 服务端拒绝抛 PnSServiceException(带服务端 errorCode)。这是慢操作(内部停止 / 销毁再重启可达数秒),别当失败误杀。

示例:

device.ResetDevice("communication");
还在换过程数据时不要复位

控制器还在周期交换时复位,控制器侧会掉站、诊断刷屏。要等断开后再做。