基于Open62541库开发的OpcUa采集程序,找遍了全网都没有关于OpcUa注册读写方法的例子,在此分享关键代码如下,具体代码实例请按照自己开发需求进行完善:
UA_Client* client;
vector<UA_NodeId> nodeIdList;
vector<UA_NodeId> registerNodeIdList;
vector<UA_ReadValueId> readNodeIdList;
//UA_Client如何初始化及连接在此就不介绍了,网上有其他技术博客相关代码例子,请自己查找
//初始化
void Init()
{
int nsIndex, char* addr;
nsIndex = 1;
addr = "test1";
UA_NodeId nodeId1 = UA_NODEID_STRING(nsIndex, addr);
UA_NodeId dstNodeId;
/***重点1:如果用以上方法初始化NodeId,须用以下方法进行深拷贝后才能将NodeId放到集合里
,否则放进去后NodeId会失效***/
UA_NodeId_copy(&nodeId1, &dstNodeId);
nodeIdList.push_back(dstNodeId);
UA_NodeId nodeId2;
addr = "test2";
/***重点2:或者通过以下方法初始化NodeId放进集合里***/
UA_NodeId nodeId2 = UA_NODEID_STRING_ALLOC(nsIndex, addr);
nodeIdList.push_back(nodeId2);
}
//注册节点
void RegisterNodes()
{
UA_RegisterNodesRequest request;
UA_RegisterNodesRequest_init(&request);
request.nodesToRegister = &nodeIdList[0];
request.nodesToRegisterSize = nodeIdList.size();
UA_Client_renewSecureChannel(client);
UA_RegisterNodesResponse response = UA_Client_Service_registerNodes(client, request);
UA_StatusCode retval = response.responseHeader.serviceResult;
if (retval == UA_STATUSCODE_GOOD)
{
if (response.registeredNodeIdsSize != nodeIdList.size())
{
UA_RegisterNodesResponse_clear(&response);
return;
}
}
for (int i = 0; i < response.registeredNodeIdsSize; i++)
{
UA_ReadValueId readNode;
UA_ReadValueId_init(&readNode);
readNode.attributeId = UA_ATTRIBUTEID_VALUE;
UA_NodeId nodeId = response.registeredNodeIds[i];
UA_NodeId dstNodeId;
UA_NodeId_copy(&nodeId, &dstNodeId);
readNode.nodeId = dstNodeId;
registerNodeIdList.push_back(dstNodeId);
readNodeIdList.push_back(readNode);
}
UA_RegisterNodesResponse_clear(&response);
}
//读取节点数据
void ReadNodeValues()
{
UA_ReadRequest request;
UA_ReadRequest_init(&request);
request.nodesToRead = &readNodeIdList[0];
request.nodesToReadSize = readNodeIdList.size();
/***重点3:必须通过以下方法更新通道,否则不能正确读取注册后的节点数据***/
UA_Client_renewSecureChannel(client);
UA_ReadResponse response = UA_Client_Service_read(client, request);
UA_StatusCode retval = response.responseHeader.serviceResult;
if (retval == UA_STATUSCODE_GOOD)
{
if (response.resultsSize != readNodeIdList.size())
{
UA_ReadResponse_clear(&response);
return;
}
}
for (int i = 0; i < readNodeIdList.size(); ++i)
{
UA_DataValue *p = response.results;
if (p != NULL)
{
if (response.results[i].status == UA_STATUSCODE_GOOD)
{
UA_DataValue res = response.results[i];
if (!res.hasValue) // no value
{
continue;
}
UA_Variant m_value;
memcpy(&m_value, &res.value, sizeof(UA_Variant));
UA_Variant_init(&res.value);
double val = 0;
string dataType = m_value.type->typeName;
if (m_value.type == &UA_TYPES[UA_TYPES_FLOAT])
{
UA_Float *p = (UA_Float *)m_value.data;
val = *p;
}
else if (m_value.type == &UA_TYPES[UA_TYPES_BOOLEAN])
{
UA_Boolean *p = (UA_Boolean *)m_value.data;
if (*p == UA_FALSE)
{
val = 0;
}
else
{
val = 1;
}
}
else if (m_value.type == &UA_TYPES[UA_TYPES_INT16])
{
UA_Int16 *p = (UA_Int16 *)m_value.data;
val = *p;
}
else if...
//将读取到的数值放到相应数据字典里后续用吧
...
}
}
UA_ReadResponse_clear(&response);
}