属性与状态机
看状态用命名空间函数,不必构造。做 IO:构造 → Start() → 写 Q / 读 I。主站是否已周期交换看 Connected()。
Start() 失败返回 false,写入 LastError(),不抛。读写 IO 失败抛 PnSException。
属性
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 静态 | IsServiceReady() | bool | 只读 | 本机服务是否就绪 |
LastError() | const std::string& | 只读 | 全应用最近一次失败文案(sticky,成功路径不清空) | |
LastErrorCode() | PnSErrorCode | 只读 | 全应用最近一次失败的调用错误码。从未失败为 Success | |
ServiceConnected() | bool | 只读 | 主站是否周期交换。服务没起来 = false | |
ServiceState() | PnSState | 只读 | 运行态。服务没起来 = Unknown | |
ServiceWaitReason() | std::string | 只读 | 等待原因。服务没起来 = 「服务未就绪」 | |
ServiceStatusMessage() | std::string | 只读 | 状态文案。服务没起来 = 「服务未就绪」 | |
| 连接与会话 | Connected() | bool | 只读 | IO 控制器是否已经建立周期数据交换。true 才表示周期数据在换 |
Attached() | bool | 只读 | 本 SDK 会话是否已连上本机服务。Stop 不改变 | |
IsRunning() | bool | 只读 | IO 设备是否已启用(Start 之后、Stop 之前) | |
| 运行态 | Status() | PnSState | 只读 | 运行态。等于 StatusEx().state。读不到真实状态为 Unknown |
StatusEx() | PnSServiceStatus | 只读 | 一次取回 state / connected / error_code | |
WaitReason() | std::string | 只读 | 本会话等待原因。主站已连时为空 | |
EverConnected() | bool | 只读 | 是否曾与 IO 控制器建立过连接。true 且 Connected 为 false = 掉线 | |
| 错误码 | ErrorCode() | PnSRuntimeErrorCode | 只读 | 最近一次运行错误。未识别值 Unknown |
ErrorCodeRaw() | int | 只读 | 运行错误原值(0 = 无错误)。未识别值仍经本函数透传 | |
ErrorMessage() | std::string | 只读 | 运行错误中文消息 | |
LastServiceError() | const std::string& | 只读 | 本会话最近一次失败文案(sticky,成功路径不清空) | |
| 报警 | AlarmCount() | int | 只读 | 活动报警总数。与 GetAlarms 同源 |
CriticalAlarmCount() | int | 只读 | Critical 报警数 | |
GetAlarms() | vector<PnSServiceAlarmItem> | 只读 | 活动报警。见 [诊断 · 报警](./diagnostics#报警) | |
GetAlarmHistory() | vector<PnSServiceAlarmItem> | 只读 | 历史报警。见 [诊断 · 报警](./diagnostics#报警) | |
| 诊断与过程数据 | Events() | PnSEvents& | 只读 | 本机运行态事件。见 [事件](./events) |
DiagSnapshot() | PnSServiceDiagSnapshot | 只读 | 一次取回链路、帧计数、看门狗、抖动。读不到时 ok 为 false | |
ProcessData() | PnSProcessData | 只读 | 过程数据子对象。见 [过程数据](./io) | |
| 本机会话 | Host() | const std::string& | 只读 | 本会话连接的服务主机 |
Port() | uint16_t | 只读 | 本会话连接的服务端口 |
同名命名空间函数与 PnSService:: 静态函数等价,不必构造:IsServiceReady()、LastError()、LastErrorCode()、ServiceConnected()、ServiceState()、ServiceWaitReason()、ServiceStatusMessage()。服务没起来写 LastError(),不抛。
PnSState
运行态。取值见 枚举参考。
PnSRuntimeErrorCode
运行错误码。取值见 枚举参考。
启停
Start()
bool Start();
使能 IO 设备。已 Start 且尚未 Stop 则幂等返回 true。这不是主站已周期交换,主站是否在换数据看 Connected()。
返回值:
bool—true成功;失败返回false
失败写入静态 LastError(),不抛。
示例:
if (!device.Start())
printf("%s\n", LastError().c_str());
Stop()
void Stop();
停用 IO 设备。实例仍在,可再次 Start()。未 Start 或已 Stop 则幂等返回。失败写 LastError(),不抛。
不是 Close():Stop 不结束 SDK 会话。
示例:
device.Stop();
运行态
Status()
运行态。Start / Stop 只管启用 / 停用 IO 设备;本函数始终按现场如实读。读不到真实状态为 Unknown。未连上服务时抛 PnSException,不必构造时用 ServiceState()。
PnSState Status();
示例:
if (device.Status() == PnSState::Running)
printf("周期数据交换正常\n");
StatusEx()
PnSServiceStatus StatusEx();
一次取回 state / connected / error_code、等待文案、报警计数。未连上服务时抛 PnSException。snap.connected == true 表示已与 IO 控制器建立周期数据交换。运行错误枚举用 device.ErrorCode()。
struct PnSServiceStatus
{
PnSState state = PnSState::Disconnected;
bool connected = false;
int error_code = 0;
std::string wait_reason;
std::string status_message;
int alarm_count = 0;
int critical_alarm_count = 0;
bool ever_connected = false;
};
示例:
auto snap = device.StatusEx();
if (snap.connected)
printf("周期交换正常\n");
WaitReason()
std::string WaitReason();
本会话等待原因。主站已连时为空。循环 if (!device.Connected()) 时读本函数或 LastServiceError()。
示例:
if (!device.Connected())
printf("%s\n", device.WaitReason().c_str());
EverConnected()
bool EverConnected();
是否曾与 IO 控制器建立过连接。false = 从未连过;true 且 Connected() == false = 掉线。掉线后此判别仍保留。未连上服务 = false。
示例:
if (!device.Connected() && device.EverConnected())
printf("掉线\n");
Connected()
bool Connected();
IO 控制器是否已经建立周期数据交换。true 才表示周期数据在换。未连上服务时改用 ServiceConnected(),不抛。不必构造时用 ServiceConnected()。
Start() 之后本值仍可能是 false。
示例:
if (device.Connected())
printf("主站在换周期数据\n");
错误码
ErrorCode()
PnSRuntimeErrorCode ErrorCode();
最近一次运行错误(枚举)。未识别值 Unknown。原值仍经 ErrorCodeRaw() 透传。中文消息用 ErrorMessage()。未连上服务 = Ok。
示例:
PnSRuntimeErrorCode err = device.ErrorCode();
std::string text = device.ErrorMessage();
int raw = device.ErrorCodeRaw();
ErrorCodeRaw()
int ErrorCodeRaw();
运行错误原值(0 = 无错误)。未识别值仍经本函数透传。未连上服务 = 0。
示例:
int raw = device.ErrorCodeRaw();
ErrorMessage()
std::string ErrorMessage();
运行错误中文消息。未识别码返回带原值的说明,不丢信息。
示例:
printf("%s\n", device.ErrorMessage().c_str());
LastServiceError()
const std::string& LastServiceError() const;
本会话最近一次失败文案(sticky)。成功路径不清空。循环 if (!Connected()) 时若本值为空,读 WaitReason()。
示例:
printf("%s\n", device.LastServiceError().c_str());
LastError() / LastErrorCode()
static const std::string& LastError();
static PnSErrorCode LastErrorCode();
全局,不必构造。成功路径不清空。读写 IO 失败抛 PnSException,code() 为 SDK 调用错误码。
PnSErrorCode
SDK 调用错误码。取值见 枚举参考。
C 语言码 ≠ 本枚举码(-4..-8 同值不同义),跨语言换算必须走 PnSErrorCodeFromNative(int)(constexpr,可用于 static_assert),禁止裸 static_cast。
示例:
try {
device.WriteBool("Q0.0", true);
} catch (const PnSException& ex) {
printf("%s code=%d\n", ex.what(), ex.code());
}
诊断
DiagSnapshot()
PnSServiceDiagSnapshot DiagSnapshot();
一次取回链路、帧计数、看门狗、抖动。读不到时 ok == false,读 message,不视为异常。字段见 诊断。
示例:
auto snap = device.DiagSnapshot();
if (!snap.ok)
printf("%s\n", snap.message.c_str());
完整示例
#include "pns.hpp"
#include <cstdio>
using namespace darra::pns;
int main()
{
PnSService device;
if (!device.Start())
return 1;
while (running)
{
if (!device.Connected())
{
printf("%d\n", static_cast<int>(device.Status()));
printf("%s\n", device.WaitReason().c_str());
printf("%s\n", device.ErrorMessage().c_str());
continue;
}
device.WriteBool("Q0.0", true);
bool fromPlc = device.ReadBool("I0.0");
(void)fromPlc;
}
device.Stop();
return 0;
}