Skip to content

Commit

Permalink
Parameterize OPC UA Instance Name of Alarm Source Object
Browse files Browse the repository at this point in the history
  • Loading branch information
m-meingast committed Jul 23, 2024
1 parent 6fcfc3c commit dd3079d
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 31 deletions.
52 changes: 36 additions & 16 deletions src/com/opc_ua/opcua_ac_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ COPC_UA_AC_Layer::~COPC_UA_AC_Layer() {

EComResponse COPC_UA_AC_Layer::openConnection(char *paLayerParameter) {
EComResponse eRetVal = e_InitTerminated;
CParameterParser parser(paLayerParameter, ';', scmNumberOfParameters);
CParameterParser parser(paLayerParameter, ';');
size_t nrOfParams = parser.parseParameters();
if(nrOfParams == scmNumberOfParameters) {
if(nrOfParams == scmNumberOfAlarmParameters || nrOfParams == scmNumberOfEventParameters) {
std::string mode = parser[Mode];
mInitType = parser[InitType];
mHandler = static_cast<COPC_UA_HandlerAbstract*>(&getExtEvHandler<COPC_UA_Local_Handler>());
if(mode == scmModeINITMSG || mode == scmModeINITUSERTEXT) {
eRetVal = initOPCUAType(mode, mInitType, parser[TypeName]);
} else if (mode == scmModeTRIGGER) {
eRetVal = createOPCUAObject(mInitType, parser[TypeName]);
eRetVal = createOPCUAObject(mInitType, parser[TypeName], parser[PathToInstance] ? parser[PathToInstance] : std::string());
} else {
DEVLOG_ERROR("[OPC UA A&C LAYER]: Wrong usage of layer parameters! Expected first param: %s | %s | %s, actual: %s\n", scmModeINITMSG.c_str(), scmModeINITUSERTEXT.c_str(), scmModeTRIGGER.c_str(), mode.c_str());
return eRetVal;
Expand Down Expand Up @@ -190,7 +190,7 @@ EComResponse COPC_UA_AC_Layer::initOPCUAType(const std::string &paMode, const st
return eRetVal == e_InitOk ? addOPCUATypeProperties(server, paMode, paTypeName) : eRetVal;
}

EComResponse COPC_UA_AC_Layer::createOPCUAObject(const std::string &paType, const std::string &paTypeName) {
EComResponse COPC_UA_AC_Layer::createOPCUAObject(const std::string &paType, const std::string &paTypeName, const std::string &paPathToInstance) {
std::string browsePathPrefix;
if(paType == scmTypeALARM) {
browsePathPrefix = scmAlarmTypeBrowsePath;
Expand All @@ -209,34 +209,49 @@ EComResponse COPC_UA_AC_Layer::createOPCUAObject(const std::string &paType, cons
localHandler->enableHandler();
UA_Server *server = localHandler->getUAServer();
if(paType == scmTypeALARM) {
if(createOPCUAObjectNode(server) != UA_STATUSCODE_GOOD) {
std::string objectBrowsePath;
if(createOPCUAObjectNode(server, paPathToInstance, objectBrowsePath) != UA_STATUSCODE_GOOD) {
return e_InitTerminated;
}
if(addOPCUACondition(server) != UA_STATUSCODE_GOOD) {
std::string conditionBrowsePath;
if(addOPCUACondition(server, objectBrowsePath, conditionBrowsePath) != UA_STATUSCODE_GOOD) {
return e_InitTerminated;
}
mMemberActionInfo.reset(new CActionInfo(*this, CActionInfo::UA_ActionType::eWrite, std::string()));
if(initializeMemberActions() != e_InitOk) {
if(initializeMemberActions(conditionBrowsePath) != e_InitOk) {
return e_InitTerminated;
}
}
return e_InitOk;
}

UA_StatusCode COPC_UA_AC_Layer::createOPCUAObjectNode(UA_Server *paServer) {
UA_StatusCode COPC_UA_AC_Layer::createOPCUAObjectNode(UA_Server *paServer, const std::string &paPathToInstance, std::string &paBrowsePath) {
if(!COPC_UA_Helper::isBrowsePathValid(paPathToInstance)) {
return UA_STATUSCODE_BAD;
}
std::string instanceNameStr(getFBNameFromConnection());
if(instanceNameStr.empty()) {
DEVLOG_ERROR("[OPC UA A&C LAYER]: Retrieving FB Instance Name failed!");
return UA_STATUSCODE_BAD;
}

COPC_UA_Local_Handler* localHandler = static_cast<COPC_UA_Local_Handler*>(mHandler);
CSinglyLinkedList<UA_NodeId*> referencedNodes;
paBrowsePath = COPC_UA_ObjectStruct_Helper::getMemberBrowsePath(paPathToInstance, instanceNameStr);
UA_StatusCode status = localHandler->splitAndCreateFolders(paBrowsePath, instanceNameStr, referencedNodes); // Overwrites instanceNameStr to the same value as before, but we get the OPC UA folders
if(status != UA_STATUSCODE_GOOD || referencedNodes.isEmpty()) {
DEVLOG_ERROR("[OPC UA A&C LAYER]: Creating OPC UA Folders failed, Browsepath: %s, StatusCode: %s\n", paBrowsePath.c_str(), UA_StatusCode_name(status));
return UA_STATUSCODE_BAD;
}

char *instanceName = getNameFromString(instanceNameStr);
char *browsePath = getNameFromString(COPC_UA_ObjectStruct_Helper::getMemberBrowsePath("/Objects", instanceNameStr));
char *browsePath = getNameFromString(paBrowsePath);
const UA_NodeId *parentNodeId = *referencedNodes.back();
mConditionSourceId = UA_NODEID_STRING(1, browsePath); // TODO Change 1 to namespaceIndex
UA_ObjectAttributes attr = UA_ObjectAttributes_default;
attr.eventNotifier = UA_EVENTNOTIFIER_SUBSCRIBE_TO_EVENT;
attr.displayName = UA_LOCALIZEDTEXT(smEmptyString, instanceName);
UA_StatusCode status = UA_Server_addObjectNode(paServer, mConditionSourceId,
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
status = UA_Server_addObjectNode(paServer, mConditionSourceId,
*parentNodeId,
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, instanceName), // TODO Change 1 to namespaceIndex
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
Expand All @@ -253,12 +268,16 @@ UA_StatusCode COPC_UA_AC_Layer::createOPCUAObjectNode(UA_Server *paServer) {
if(status != UA_STATUSCODE_GOOD) {
DEVLOG_ERROR("[OPC UA A&C LAYER]: Adding reference to Object Node failed. StatusCode %s\n", UA_StatusCode_name(status));
}
for(CSinglyLinkedList<UA_NodeId*>::Iterator itReferencedNodes = referencedNodes.begin(); itReferencedNodes != referencedNodes.end(); ++itReferencedNodes) {
UA_NodeId_delete(*itReferencedNodes);
}
return status;
}

UA_StatusCode COPC_UA_AC_Layer::addOPCUACondition(UA_Server *paServer) {
UA_StatusCode COPC_UA_AC_Layer::addOPCUACondition(UA_Server *paServer, const std::string &paPathToInstance, std::string &paBrowsePath) {
char *conditionName = getNameFromString(scmAlarmConditionName);
char *conditionBrowsePath = getNameFromString(COPC_UA_ObjectStruct_Helper::getMemberBrowsePath("/Objects/OPCUAMessageHandlerTest", scmAlarmConditionName));
paBrowsePath = COPC_UA_ObjectStruct_Helper::getMemberBrowsePath(paPathToInstance, scmAlarmConditionName);
char *conditionBrowsePath = getNameFromString(paBrowsePath);
mConditionInstanceId = UA_NODEID_STRING(1, conditionBrowsePath); // TODO Change 1 to namespaceIndex
UA_StatusCode status = UA_Server_createCondition(paServer, mConditionInstanceId, mTypeNodeId,
UA_QUALIFIEDNAME(1, conditionName), mConditionSourceId,
Expand All @@ -285,13 +304,14 @@ UA_StatusCode COPC_UA_AC_Layer::addOPCUACondition(UA_Server *paServer) {
return status;
}

forte::com_infra::EComResponse COPC_UA_AC_Layer::initializeMemberActions() {
forte::com_infra::EComResponse COPC_UA_AC_Layer::initializeMemberActions(const std::string &paParentBrowsePath) {
mMemberActionInfo.reset(new CActionInfo(*this, CActionInfo::UA_ActionType::eWrite, std::string()));
size_t numPorts = getCommFB()->getNumSD();
const SFBInterfaceSpec *interfaceSpec = getCommFB()->getFBInterfaceSpec();
const CStringDictionary::TStringId *dataPortNameIds = interfaceSpec->mDINames;
for(size_t i = 0; i < numPorts; i++) {
std::string dataPortName = getPortNameFromConnection(dataPortNameIds[i+2], true);
std::string memberBrowsePath(COPC_UA_ObjectStruct_Helper::getMemberBrowsePath("/Objects/OPCUAMessageHandlerTest/AlarmCondition", dataPortName));
std::string memberBrowsePath(COPC_UA_ObjectStruct_Helper::getMemberBrowsePath(paParentBrowsePath, dataPortName));
UA_NodeId *nodeId = COPC_UA_ObjectStruct_Helper::createStringNodeIdFromBrowsepath(memberBrowsePath);
mMemberActionInfo->getNodePairInfo().emplace_back(nodeId, memberBrowsePath);
}
Expand Down
15 changes: 9 additions & 6 deletions src/com/opc_ua/opcua_ac_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class COPC_UA_AC_Layer : public COPC_UA_Layer {
enum Parameters {
Mode,
InitType,
TypeName
TypeName,
PathToInstance
};

static const std::string scmModeINITMSG;
Expand All @@ -59,7 +60,9 @@ class COPC_UA_AC_Layer : public COPC_UA_Layer {

static char smEmptyString[];

static const size_t scmNumberOfParameters = 3;
static const size_t scmNumberOfAlarmParameters = 4;

static const size_t scmNumberOfEventParameters = 3;

COPC_UA_HandlerAbstract *mHandler;

Expand Down Expand Up @@ -91,11 +94,11 @@ class COPC_UA_AC_Layer : public COPC_UA_Layer {

forte::com_infra::EComResponse initOPCUAType(const std::string &paMode, const std::string &paType, const std::string &paTypeName);

forte::com_infra::EComResponse createOPCUAObject(const std::string &paType, const std::string &paTypeName);
forte::com_infra::EComResponse createOPCUAObject(const std::string &paType, const std::string &paTypeName, const std::string &paPathToInstance);

UA_StatusCode createOPCUAObjectNode(UA_Server *paServer);
UA_StatusCode createOPCUAObjectNode(UA_Server *paServer, const std::string &paPathToInstance, std::string &paBrowsePath);

UA_StatusCode addOPCUACondition(UA_Server *paServer);
UA_StatusCode addOPCUACondition(UA_Server *paServer, const std::string &paPathToInstance, std::string &paBrowsePath);

forte::com_infra::EComResponse createAlarmType(UA_Server *paServer, const std::string &paTypeName);

Expand All @@ -109,7 +112,7 @@ class COPC_UA_AC_Layer : public COPC_UA_Layer {

UA_StatusCode addVariableNode(UA_Server *paServer, const std::string &paParentTypeName, char *paVariableName, CIEC_ANY &paVariableType);

forte::com_infra::EComResponse initializeMemberActions();
forte::com_infra::EComResponse initializeMemberActions(const std::string &paParentBrowsePath);

bool isOPCUAObjectPresent(std::string &paBrowsePath);

Expand Down
18 changes: 9 additions & 9 deletions src/com/opc_ua/opcua_local_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ class COPC_UA_Local_Handler : public COPC_UA_HandlerAbstract, public CThread {
*/
UA_StatusCode initializeActionForObjectStruct(std::shared_ptr<CActionInfo> &paActionInfo, CIEC_ANY &paMember);

/**
* Splits a browsepath into folders and node name. The non-existing folders are created in the local server
* @param paBrowsePath Browsepath to be splitted
* @param paNodeName Place to store the nodename
* @param paRreferencedNodes List of nodes that are used by this browsename. It will include all folders, but not the end node since it was not created yet
* @return UA_STATUSCODE_GOOD is no problem occurred, other value otherwise
*/
UA_StatusCode splitAndCreateFolders(const std::string &paBrowsePath, std::string &paNodeName, CSinglyLinkedList<UA_NodeId*> &paRreferencedNodes) const;

/**
* Default value for the namespace of the browsename for all created nodes
*/
Expand Down Expand Up @@ -597,15 +606,6 @@ class COPC_UA_Local_Handler : public COPC_UA_HandlerAbstract, public CThread {
*/
UA_StatusCode createFolders(const char *paFolders, CSinglyLinkedList<UA_NodeId*> &paCreatedNodeIds) const;

/**
* Splits a browsepath into folders and node name. The non-existing folders are created in the local server
* @param paBrowsePath Browsepath to be splitted
* @param paNodeName Place to store the nodename
* @param paRreferencedNodes List of nodes that are used by this browsename. It will include all folders, but not the end node since it was not created yet
* @return UA_STATUSCODE_GOOD is no problem occurred, other value otherwise
*/
UA_StatusCode splitAndCreateFolders(const std::string &paBrowsePath, std::string &paNodeName, CSinglyLinkedList<UA_NodeId*> &paRreferencedNodes) const;

/**
* Split a string into folders and node name. The provided place for store of the folder and node name are only
* changed if the result value is true
Expand Down

0 comments on commit dd3079d

Please sign in to comment.