PnSService
PROFINET IO Device 的入口。启动设备、写 Q / 读 I、看运行态和诊断。
本 SDK 只做 PROFINET IO Device,不提供其它现场总线协议的入口。
类结构
PnSService // 设备实例
│
├── ProcessData() → PnSProcessData // 写 Q / 读 I
│ ├── InputsMapping<T>() / OutputsMapping<T>() // 0 拷贝,映射一次
│ ├── Read<T>() / Write<T>() / SetOutputs() // 快照,值不会自己变
│ ├── In() // 读 I(模块输入),只读
│ └── Out() // 写 Q(模块输出),可写
├── Events() → PnSEvents // 运行态事件
│ ├── ConnectedChanged // 周期交换通断
│ ├── StateChanged // 运行态变化
│ ├── ErrorOccurred // 运行错误
│ └── Logged // 上面每条都会再打这条
├── Diagnostics() → PnSDiagnostics // 诊断与报警
│ ├── Snapshot() // 诊断快照
│ ├── Alarms() / AlarmHistory() // 本机报警 / 历史
│ └── Records() // 用户区记录
│
├── Connected() / Status() / WaitReason() // 周期交换 / 运行态 / 等待原因
├── EverConnected() / ErrorCode() // 曾经连上 / 运行错误
└── ImData() // I&M 标识
写 Q(模块输出,设备 → 控制器),读 I(模块输入,控制器 → 设备)。扁平
DiagSnapshot()/GetAlarms()仍可用,与Diagnostics()同一数据。
用法
启停
#include "pns.hpp"
using namespace darra::pns;
PnSService device;
if (!device.Start())
return;
while (running)
{
if (!device.Connected())
{
// device.WaitReason()
continue;
}
device.WriteBool("Q0.0", true); // 写 Q
bool fromPlc = device.ReadBool("I0.0"); // 读 I
}
device.Stop();
看状态不必构造:IsServiceReady() / ServiceConnected() / ServiceWaitReason()。
过程数据
| 方式 | 访问 | 说明 |
|---|---|---|
| 过程数据 | device.ProcessData().InputsMapping<T>() / OutputsMapping<T>() | 0 拷贝,映射一次 |
| 过程数据 | device.ProcessData() | 快照 Read / Write、In() / Out() 字节 |
标识
auto im = device.ImData();
std::string name = im.station_name;
uint16_t vendor = im.vendor_id;
uint16_t product = im.device_id;
过程数据读写
结构体按声明顺序字节紧排,必须 #pragma pack(push, 1)(未 pack 编译期 static_assert 不过)。字 / 双字为大端。详见 过程数据。
金路径是 0 拷贝:映射一次,源头变字段自己变。要宿主数值走「自动转换」的类型化访问器(大端编解码)。I 侧返回 const T& 只读(控制器每周期整段覆盖,写 I 静默无效),Q 侧返回 T& 可写。
#pragma pack(push, 1)
struct FromPlc
{
uint8_t a;
int16_t b;
uint8_t flag;
};
#pragma pack(pop)
// 0 拷贝:映射一次
const FromPlc& inp = device.ProcessData().InputsMapping<FromPlc>();
FromPlc& outp = device.ProcessData().OutputsMapping<FromPlc>();
uint8_t present = inp.a; // 总线刷新后自己变(I 侧只读)
outp.a = 1; // 直接落 Q 过程映像
// 快照:拷出来不会自己变
FromPlc rx = device.ProcessData().Read<FromPlc>();
device.ProcessData().Out()[0].Content(0x11);
uint8_t v = device.ProcessData().In()[0].Content();
诊断与报警
通过 device.Diagnostics() 读诊断与报警。详见 诊断。事件见 事件。
auto snap = device.Diagnostics().Snapshot();
if (!snap.ok)
printf("%s\n", snap.message.c_str());
for (const auto& a : device.Diagnostics().Alarms())
printf("%s\n", a.message.c_str());