诊断
通过 device.Diagnostics 读诊断与报警(DiagSnapshot / Alarms 仍可用,同一数据)。
建议通过 事件 驱动异常处理,而非自行轮询。 直接读取诊断属性适用于 UI 显示等场景。
运行态(Connected / State / ErrorCode)见 属性与状态机,本页只讲诊断快照、IOPS/IOCS 和报警。过程数据读写见 过程数据。
功能概览
| 功能 | 说明 |
|---|---|
| 诊断快照 | 链路、帧计数、看门狗、抖动、报警观测 |
| IOPS / IOCS | 过程数据质量:数据 GOOD 还是 BAD |
| 现场问题对照 | 按症状选字段 |
| 报警 | 活动列表 / 历史 / 确认 |
| 用户记录 | 用户区记录表(D_2014) |
| 复位 | 通信复位 / 工厂复位 |
诊断快照
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 可用性 | Ok | bool | 只读 | 诊断是否可用。false = 设备未启动,读 Message |
SharedMemoryMapped | bool | 只读 | 过程数据是否已就绪 | |
Message | string | 只读 | 不可用时的原因;可用时为空 | |
Timestamp | DateTime | 只读 | 快照生成时刻 | |
| 链路 | State | string | 只读 | 运行状态文案 |
LinkUp | bool | 只读 | 网卡链路是否 Up | |
Connected | bool | 只读 | 周期数据是否正常 | |
ActiveIocrCount | uint | 只读 | 已激活的 IO 连接数 | |
IocrActive | uint | 只读 | IO 连接激活位图 | |
IocrHealthy | uint | 只读 | IO 连接健康位图 | |
| 计数 | Heartbeat | ulong | 只读 | 心跳计数 |
CycleCounter | ulong | 只读 | 周期循环计数 | |
LastError | ulong | 只读 | 最近错误码(0 = 无) | |
RxFrames / TxFrames | ulong | 只读 | 收 / 发总帧数 | |
RxRtFrames / TxRtFrames | ulong | 只读 | 收 / 发 RT 周期帧 | |
DroppedFrames | ulong | 只读 | 被丢弃的帧 | |
InvalidFrames | ulong | 只读 | 非法帧 | |
WatchdogTrips | ulong | 只读 | 看门狗超时次数 | |
LastRxTsc / LastTxTsc | ulong | 只读 | 最近收 / 发帧 TSC | |
| 过程区 | InputAreaLength | uint | 只读 | 输入区长度(字节) |
OutputAreaLength | uint | 只读 | 输出区长度(字节) | |
| 周期 | StackCycles | ulong | 只读 | 周期计数 |
StackFramesRx / StackFramesTx | ulong | 只读 | 收 / 发帧 | |
StackMissedTicks | ulong | 只读 | 错过的节拍 | |
StackMaxJitterUs | ulong | 只读 | 最大抖动(微秒) | |
| 报警观测 | StackAlarmRxCount | ulong | 只读 | 收到控制器报警总数 |
StackAlarmTxAckOk | ulong | 只读 | 本机报警被确认次数 | |
StackAlarmTxAckFail | ulong | 只读 | 本机报警确认失败次数 | |
StackAlarmAckPending | ulong | 只读 | 在途报警(0/1) | |
StackAlarmMaintState | ulong | 只读 | 维护请求状态 | |
StackAlarmLastArep | uint | 只读 | 最近控制器报警:Arep | |
StackAlarmLastSlot | uint | 只读 | 最近控制器报警:槽位 | |
StackAlarmLastSubslot | uint | 只读 | 最近控制器报警:子槽位 | |
StackAlarmLastType | uint | 只读 | 最近控制器报警:类型 | |
StackAlarmLastSeq | uint | 只读 | 最近控制器报警:序列号 | |
StackAlarmLastUsi | uint | 只读 | 最近控制器报警:USI | |
StackAlarmLastLen | uint | 只读 | 最近控制器报警:负载长度 | |
| 错误 | ErrorCode | int | 只读 | 错误码原值(0 = 无) |
ErrorCodeEnum | PnSRuntimeErrorCode | 只读 | 上项的枚举形态。未识别值为 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 / InputIocs | byte[] | 只读 | I 区:控制器提供 / 本设备消费后回报。返回拷贝,改了不影响本对象 |
OutputIops / OutputIocs | byte[] | 只读 | Q 区:本设备提供 / 控制器消费后回报 | |
| 判据 | InputValid / OutputValid | bool | 只读 | 本轮收到过 I 区 / 写过 Q 且已送达控制器(掉线、未送出 = false) |
InputDataGood | bool | 只读 | 收到过 I 且输入 IOPS 全 GOOD | |
OutputDataGood | bool | 只读 | 写过 Q 且输出 IOPS 全 GOOD | |
OutputConsumed | bool | 只读 | 输出 IOCS 全 GOOD(控制器已消费) | |
AllGood | bool | 只读 | 输入数据有效 + 输出数据有效 + 输出已消费 | |
| 工厂 | PnSIoStatus.Empty | PnSIoStatus | 只读 | 空状态(未启动 / 读不到)。判据全 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 |
报警
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 计数 | AlarmCount | int | 只读 | 活动报警总数。与 Alarms 同源 |
CriticalAlarmCount | int | 只读 | Critical 报警数 | |
| 列表 | Alarms | List<PnSAlarmItem> | 只读 | 当前活动报警。空列表 = 无活动报警,不是失败 |
AlarmHistory | List<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
| 属性 | 类型 | 说明 |
|---|---|---|
| Id | string | 报警 ID(如 PnS.LinkDown) |
| Severity | string | 严重度:Info / Warning / Error / Critical |
| Message | string | 报警消息 |
| OccurredAt | DateTime | 最近一次发生时间 |
| Count | int | 发生次数(≥1) |
| Source | string | 来源 |
用户记录
Records
public PnSUserRecords Records { get; }
取用户区记录表(D_2014,Index 0x0000–0x7FFF)。缺字段默认 0 / 空,不虚构。没有记录返回空表,不是失败。device.Diagnostics.Records 与本属性同一数据。
用户区记录(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
| 属性 | 类型 | 说明 |
|---|---|---|
| Records | PnSUserRecord[] | 记录数组(空 = 没有记录,不是失败) |
| Count | int | 服务端计数(缺字段为 0,不按数组长度回填) |
| Timestamp | DateTime | 快照生成时刻(缺字段为 DateTime.MinValue) |
PnSUserRecord
| 属性 | 类型 | 说明 |
|---|---|---|
| Slot | ushort | 槽位 |
| Subslot | ushort | 子槽位 |
| Index | ushort | 记录 Index |
| Length | ushort | 负载字节数 |
| DataHex | string | 负载十六进制(缺字段为空串) |
复位
ResetDevice()
public void ResetDevice(string mode)
复位从站。走服务端既有的启停状态机,不杀服务进程。
mode | 行为 |
|---|---|
"communication" | 软停再启,应用参数记录保留 |
"factory" | 销毁后全新启动,应用参数记录清空 |
通讯参数 / IP 的复位不由本方法负责,仍由控制器 DCP ResetToFactory 触发。
参数:
mode(string) —"communication"或"factory"。空串或其它值抛ArgumentException
失败: 服务不可达 / 服务端拒绝抛 PnSServiceException(带服务端 errorCode)。这是慢操作(内部停止 / 销毁再重启可达数秒),别当失败误杀。
示例:
device.ResetDevice("communication");
控制器还在周期交换时复位,控制器侧会掉站、诊断刷屏。要等断开后再做。