诊断
通过 device.Diagnostics() 读诊断与报警(DiagSnapshot() / GetAlarms() 仍可用)。
配合事件使用
建议通过 事件 驱动异常处理,而非自行轮询。 直接读取诊断属性适用于 UI 显示等场景。
运行态(Connected() / Status() / ErrorCode())见 属性与状态机。过程数据读写见 过程数据。
功能概览
| 功能 | 说明 |
|---|---|
| 诊断快照 | 链路、帧计数、看门狗、抖动、报警观测 |
| 现场问题对照 | 按症状选字段 |
| 报警 | 活动列表 / 历史 / 确认 |
诊断快照
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 可用性 | ok | bool | 只读 | 诊断是否可用。false = 设备未启动,读 message |
shared_memory_mapped | bool | 只读 | 过程数据是否已就绪 | |
message | string | 只读 | 不可用时的原因;可用时为空 | |
| 链路 | state | string | 只读 | 运行状态文案 |
link_up | bool | 只读 | 网卡链路是否 Up | |
connected | bool | 只读 | 周期数据是否正常 | |
active_iocr_count | uint32_t | 只读 | 已激活的 IO 连接数 | |
iocr_active | uint32_t | 只读 | IO 连接激活位图 | |
iocr_healthy | uint32_t | 只读 | IO 连接健康位图 | |
| 计数 | heartbeat | uint64_t | 只读 | 心跳计数 |
cycle_counter | uint64_t | 只读 | 周期循环计数 | |
last_error | uint64_t | 只读 | 最近错误码(0 = 无) | |
rx_frames / tx_frames | uint64_t | 只读 | 收 / 发总帧数 | |
rx_rt_frames / tx_rt_frames | uint64_t | 只读 | 收 / 发 RT 周期帧 | |
dropped_frames | uint64_t | 只读 | 被丢弃的帧 | |
invalid_frames | uint64_t | 只读 | 非法帧 | |
watchdog_trips | uint64_t | 只读 | 看门狗超时次数 | |
last_rx_tsc / last_tx_tsc | uint64_t | 只读 | 最近收 / 发帧 TSC | |
| 过程区 | input_area_length | uint32_t | 只读 | 输入区长度(字节) |
output_area_length | uint32_t | 只读 | 输出区长度(字节) | |
| 周期 | stack_cycles | uint64_t | 只读 | 周期计数 |
stack_frames_rx / stack_frames_tx | uint64_t | 只读 | 收 / 发帧 | |
stack_missed_ticks | uint64_t | 只读 | 错过的节拍 | |
stack_max_jitter_us | uint64_t | 只读 | 最大抖动(微秒) | |
| 报警观测 | stack_alarm_rx_count | uint64_t | 只读 | 收到控制器报警总数 |
stack_alarm_tx_ack_ok | uint64_t | 只读 | 本机报警被确认次数 | |
stack_alarm_tx_ack_fail | uint64_t | 只读 | 本机报警确认失败次数 | |
stack_alarm_ack_pending | uint64_t | 只读 | 在途报警(0/1) | |
stack_alarm_maint_state | uint64_t | 只读 | 维护请求状态 | |
stack_alarm_last_arep | uint32_t | 只读 | 最近控制器报警:Arep | |
stack_alarm_last_slot | uint32_t | 只读 | 最近控制器报警:槽位 | |
stack_alarm_last_subslot | uint32_t | 只读 | 最近控制器报警:子槽位 | |
stack_alarm_last_type | uint32_t | 只读 | 最近控制器报警:类型 | |
stack_alarm_last_seq | uint32_t | 只读 | 最近控制器报警:序列号 | |
stack_alarm_last_usi | uint32_t | 只读 | 最近控制器报警:USI | |
stack_alarm_last_len | uint32_t | 只读 | 最近控制器报警:负载长度 | |
| 错误 | error_code | int | 只读 | 错误码原值(0 = 无) |
DiagSnapshot()
PnSServiceDiagSnapshot DiagSnapshot();
PnSServiceDiagSnapshot GetDiag(); // 同一实现
一次取回当前诊断快照,适合界面刷新和日志。设备尚未启动时 ok == false,读 message,不视为异常。区长度看 input_area_length / output_area_length,不要写死。
返回值:
PnSServiceDiagSnapshot— 诊断数据快照
未连上服务抛 PnSException。
示例:
auto snap = device.DiagSnapshot();
if (!snap.ok)
{
printf("%s\n", snap.message.c_str());
return;
}
printf(snap.link_up ? "Up\n" : "Down\n");
printf(snap.connected ? "周期交换正常\n" : "未建立\n");
printf("帧: %llu / %llu\n",
static_cast<unsigned long long>(snap.rx_frames),
static_cast<unsigned long long>(snap.tx_frames));
printf("看门狗: %llu\n",
static_cast<unsigned long long>(snap.watchdog_trips));
现场问题对照
| 现场症状 | 看哪些字段 |
|---|---|
| 网线没插好 | DiagSnapshot().link_up |
| 周期数据通不通 | DiagSnapshot().connected |
| 看门狗反复跳 | DiagSnapshot().watchdog_trips |
| 帧在丢 | dropped_frames + invalid_frames |
| 周期稳不稳 | stack_max_jitter_us + stack_missed_ticks |
| 控制器报警没消化 | stack_alarm_ack_pending / stack_alarm_tx_ack_fail |
| 本机有没有活动报警 | GetAlarms() / AlarmCount() |
报警
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 计数 | AlarmCount() | int | 只读 | 活动报警总数。与 GetAlarms 同源 |
CriticalAlarmCount() | int | 只读 | Critical 报警数 | |
| 列表 | GetAlarms() | vector<PnSServiceAlarmItem> | 只读 | 当前活动报警。空列表 = 无活动报警,不是失败 |
GetAlarmHistory() | vector<PnSServiceAlarmItem> | 只读 | 历史。空列表 = 无历史 |
失败抛 PnSException。
GetAlarms()
std::vector<PnSServiceAlarmItem> GetAlarms();
当前活动报警。无活动报警返回空列表,不是失败。
示例:
for (const auto& a : device.GetAlarms())
printf("%s %s %s\n", a.id.c_str(), a.severity.c_str(), a.message.c_str());
GetAlarmHistory()
std::vector<PnSServiceAlarmItem> GetAlarmHistory();
报警历史。无历史返回空列表,不是失败。
示例:
for (const auto& a : device.GetAlarmHistory())
printf("%s %s %s\n", a.occurred_at.c_str(), a.severity.c_str(), a.message.c_str());
AcknowledgeAlarm()
void AcknowledgeAlarm(const std::string& id);
确认一条活动报警。ID 取自 GetAlarms()。
参数:
id(string) — 报警 ID。空串抛PnSException;无此 ID 抛PnSException
示例:
device.AcknowledgeAlarm("PnS.LinkDown");
AcknowledgeAllAlarms()
int AcknowledgeAllAlarms();
确认全部活动报警。
返回值:
int— 被确认条数(0 = 无活动报警)
示例:
int n = device.AcknowledgeAllAlarms();
PnSServiceAlarmItem
| 属性 | 类型 | 说明 |
|---|---|---|
| id | string | 报警 ID(如 PnS.LinkDown) |
| severity | string | 严重度:Info / Warning / Error / Critical |
| message | string | 报警消息 |
| occurred_at | string | 最近一次发生时间(ISO-8601 文本) |
| count | int | 发生次数(≥1) |
| source | string | 来源 |
I&M 标识
ImData() / GetIm()
PnSServiceImInfo ImData();
PnSServiceImInfo GetIm(); // 同一实现
I&M1–I&M3 已由原生栈启用并如实回读,I&M4 未启用。缺字段为空 / 0,不编。im14_supported 为 true 表示 I&M1–I&M4 这次读回成功(从站未启动读不到为 false、字段为空串);主站没写过时读到的是栈的出厂占位值。说明在 im_note。
示例:
auto im = device.ImData();
printf("%s vendor=0x%04X device=0x%04X\n",
im.station_name.c_str(), im.vendor_id, im.device_id);
应用记录
GetRecords()
PnSUserRecords GetRecords();
空列表不是失败。
示例:
auto recs = device.GetRecords();
printf("count=%d\n", recs.count);
复位
ResetDevice()
void ResetDevice(const std::string& mode);
mode | 行为 |
|---|---|
communication | 软停再启,记录保留 |
factory | 清空后全新启动 |
其它 mode 抛 PnSException。本调用不改 IP。
示例:
device.ResetDevice("communication");