诊断
通过 svc.diagnostics 读诊断与报警(diag_snapshot / alarms 仍可用,同一数据)。
配合事件使用
建议通过 事件 驱动异常处理,而非自行轮询。 直接读取诊断属性适用于 UI 显示等场景。
运行态(connected / state / error_code)见 属性与状态机。过程数据读写见 过程数据。
功能概览
| 功能 | 说明 |
|---|---|
| 诊断快照 | 链路、帧计数、看门狗、抖动、报警观测 |
| 现场问题对照 | 按症状选字段 |
| 过程数据质量 | IOPS / IOCS |
| 报警 | 活动列表 / 历史 / 确认 |
诊断快照
| 分组 | 属性 | 类型 | 说明 |
|---|---|---|---|
| 可用性 | ok | bool | 诊断是否可用。False = 设备未启动,读 message |
| 可用性 | shared_memory_mapped | bool | 过程数据是否已就绪 |
| 可用性 | message | str | 不可用时的原因;可用时为空 |
| 可用性 | timestamp | datetime | None | 快照生成时刻。解析失败为 None |
| 链路 | state | str | 运行状态文案 |
| 链路 | link_up | bool | 网卡链路是否 Up |
| 链路 | connected | bool | 周期数据是否正常 |
| 链路 | active_iocr_count | int | 已激活的 IO 连接数 |
| 链路 | iocr_active | int | IO 连接激活位图 |
| 链路 | iocr_healthy | int | IO 连接健康位图 |
| 计数 | heartbeat | int | 心跳计数 |
| 计数 | cycle_counter | int | 周期循环计数 |
| 计数 | last_error | int | 最近错误码(0 = 无) |
| 计数 | rx_frames / tx_frames | int | 收 / 发总帧数 |
| 计数 | rx_rt_frames / tx_rt_frames | int | 收 / 发 RT 周期帧 |
| 计数 | dropped_frames | int | 被丢弃的帧 |
| 计数 | invalid_frames | int | 非法帧 |
| 计数 | watchdog_trips | int | 看门狗超时次数 |
| 计数 | last_rx_tsc / last_tx_tsc | int | 最近收 / 发帧 TSC |
| 过程区 | input_area_length | int | 输入区长度(字节) |
| 过程区 | output_area_length | int | 输出区长度(字节) |
| 周期 | stack_cycles | int | 周期计数 |
| 周期 | stack_frames_rx / stack_frames_tx | int | 收 / 发帧 |
| 周期 | stack_missed_ticks | int | 错过的节拍 |
| 周期 | stack_max_jitter_us | int | 最大抖动(微秒) |
| 报警观测 | stack_alarm_rx_count | int | 收到控制器报警总数 |
| 报警观测 | stack_alarm_tx_ack_ok | int | 本机报警被确认次数 |
| 报警观测 | stack_alarm_tx_ack_fail | int | 本机报警确认失败次数 |
| 报警观测 | stack_alarm_ack_pending | int | 在途报警(0/1) |
| 报警观测 | stack_alarm_maint_state | int | 维护请求状态 |
| 报警观测 | stack_alarm_last_arep | int | 最近控制器报警:Arep |
| 报警观测 | stack_alarm_last_slot | int | 最近控制器报警:槽位 |
| 报警观测 | stack_alarm_last_subslot | int | 最近控制器报警:子槽位 |
| 报警观测 | stack_alarm_last_type | int | 最近控制器报警:类型 |
| 报警观测 | stack_alarm_last_seq | int | 最近控制器报警:序列号 |
| 报警观测 | stack_alarm_last_usi | int | 最近控制器报警:USI |
| 报警观测 | stack_alarm_last_len | int | 最近控制器报警:负载长度 |
| 错误 | error_code | int | 错误码原值(0 = 无) |
| 错误 | error_code_enum | PnSRuntimeErrorCode | 上项的枚举形态。未识别值为 UNKNOWN |
diag_snapshot
@property
def diag_snapshot(self) -> PnSServiceDiagSnapshot
一次取回当前诊断快照,适合界面刷新和日志。设备尚未启动时 ok == False,读 message,不视为异常。也可写成 PnSDiagSnapshot。
示例:
snap = svc.diag_snapshot
if not snap.ok:
print(snap.message)
else:
print("Up" if snap.link_up else "Down")
print("周期交换正常" if snap.connected else "未建立")
print(f"帧: {snap.rx_frames} / {snap.tx_frames}")
print(f"看门狗: {snap.watchdog_trips}")
现场问题对照
| 现场症状 | 看哪些字段 |
|---|---|
| 网线没插好 | diag_snapshot.link_up |
| 周期数据通不通 | diag_snapshot.connected |
| 看门狗反复跳 | diag_snapshot.watchdog_trips |
| 帧在丢 | dropped_frames + invalid_frames |
| 周期稳不稳 | stack_max_jitter_us + stack_missed_ticks |
| 控制器报警没消化 | stack_alarm_ack_pending / stack_alarm_tx_ack_fail |
| 本机有没有活动报警 | alarms / alarm_count |
过程数据质量
io_status
@property
def io_status(self) -> PnSServiceIoStatus
IOPS / IOCS 快照。0x80 = GOOD,0x00 = BAD。掉线如实全 BAD。未启动 / 失败返回空状态,判据全 False。也可写成 PnSIoStatus。
| 属性 | 类型 | 说明 |
|---|---|---|
| input_iops / input_iocs | bytes | 输入 IOPS / IOCS |
| output_iops / output_iocs | bytes | 输出 IOPS / IOCS |
| input_valid | bool | 本轮收到过 I 区 |
| output_valid | bool | 本轮写过 Q 区且已送达控制器(掉线、未送出 = False) |
| input_data_good | bool | 收到过且输入 IOPS 全 GOOD |
| output_data_good | bool | 写过且输出 IOPS 全 GOOD |
| output_consumed | bool | 输出 IOCS 全 GOOD |
| all_good | bool | 上面三项都真 |
示例:
if not svc.io_status.all_good:
print(svc.io_status)
报警
| 分组 | 属性 | 类型 | 说明 |
|---|---|---|---|
| 计数 | alarm_count | int | 活动报警总数。与 alarms 同源 |
| 计数 | critical_alarm_count | int | Critical 报警数 |
| 列表 | alarms | list[PnSServiceAlarm] | 当前活动报警。空列表 = 无活动报警,不是失败 |
| 列表 | alarm_history | list[PnSServiceAlarm] | 历史(最近 500 条,时间升序)。空列表 = 无历史 |
alarms
@property
def alarms(self) -> list
当前活动报警。无活动报警返回空列表,不是失败。也可写成 PnSAlarmItem。
示例:
for a in svc.alarms:
print(a)
alarm_history
@property
def alarm_history(self) -> list
报警历史(最近 500 条,时间升序)。无历史返回空列表,不是失败。
示例:
for a in svc.alarm_history:
print(a.occurred_at, a.severity, a.message)
acknowledge_alarm
def acknowledge_alarm(self, alarm_id: str) -> None
确认一条活动报警。ID 取自 alarms。空 id 抛 PnSServiceError;无此 ID 也抛。ack_alarm 同义。
示例:
svc.acknowledge_alarm("PnS.LinkDown")
acknowledge_all_alarms
def acknowledge_all_alarms(self) -> int
确认全部活动报警。ack_all_alarms 同义。
返回值:
int— 被确认条数(0 = 无活动报警)
示例:
n = svc.acknowledge_all_alarms()
PnSServiceAlarm
| 属性 | 类型 | 说明 |
|---|---|---|
| id | str | 报警 ID(如 PnS.LinkDown) |
| severity | str | 严重度:Info / Warning / Error / Critical |
| message | str | 报警消息 |
| occurred_at | datetime | None | 最近一次发生时间。解析失败为 None |
| count | int | 发生次数(≥1) |
| source | str | 来源 |
标识
im_data
@property
def im_data(self) -> PnSServiceImData
订货号、序列号、站名。缺字段保持空 / 0 / False。也可写成 PnSImData。
示例:
im = svc.im_data
print(im.station_name, hex(im.vendor_id), hex(im.device_id), im.order_id)