blob: 326d904375c29f5be7b81ec2a291ae4f223e286c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 fortiss GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Jose Cabral - initial implementation
*******************************************************************************/
#ifndef SRC_MODULES_OPC_UA_OPCUA_ACTION_INFO_H_
#define SRC_MODULES_OPC_UA_OPCUA_ACTION_INFO_H_
#include <forte_sem.h>
#include "opcua_layer.h"
/**
* Each Communication FB (PUBLISH, SUBSCRIBE, CLIENT, SERVER) is considered an action to be executed in the OPC UA library, either locally or remotely.
* This class encapsulates all information needed to perform the action. It has a factory to create a new action from the parameters set in the ID
* of the FB
*/
class CActionInfo {
public:
/**
* Allowed type of actions. If a new action is to be added, it should go before eActionUnknown
*/
enum UA_ActionType {
eRead, //!< eRead Read a data variable
eWrite, //!< eWrite Write to a data variable
eCreateMethod, //!< eCreateMethod Create a method
eCallMethod, //!< eCallMethod Call a method
eSubscribe, //!< eSubscribe Subscribe to changes of a variable
eCreateObject, //!< eCreateObject Create an object
eCreateVariable, //!< eCreateObject Create a variable
eDeleteObject, //!< eDeleteObject Delete an object
eDeleteVariable, //!< eDeleteObject Delete a variable
eActionUnknown, //!< eActionUnknown The provided action is unknown. This is used also to set the length of known actions
};
/**
* 2-Tuple to reference a specific node in an OPC UA server composed of the node ID and browsepath of the node
*/
struct CNodePairInfo {
CNodePairInfo(UA_NodeId *paNodeId, const char *paBrowsePath) :
mNodeId(paNodeId), mBrowsePath(paBrowsePath) {
}
UA_NodeId *mNodeId;
CIEC_STRING mBrowsePath;
};
/**
* Constructor of the class.
* @param paLayer The layer that creates and executes the action
* @param paAction The action to be executed
* @param paEndpoint The endpoint of a remote OPC UA in case the action is to be executed remotely. An empty endpoint means that the action is to be executed locally
*/
explicit CActionInfo(COPC_UA_Layer &paLayer, UA_ActionType paAction, const CIEC_STRING &paEndpoint);
/**
* Destructor of the class
*/
virtual ~CActionInfo();
/**
* Getter of the action type
* @return Action type
*/
UA_ActionType getAction() const {
return mAction;
}
/**
* Getter of the layer
* @return Layer
*/
COPC_UA_Layer& getLayer() {
return mLayer;
}
/**
* Getter of the enpoint
* @return A constant reference of the endpoint
*/
const CIEC_STRING& getEndpoint() const {
return mEndpoint;
}
/**
* Getter of the list of node pair information
* @return List of node pair information
*/
CSinglyLinkedList<CNodePairInfo*>& getNodePairInfo() {
return mNodePair;
}
/**
* Gets the amount of node pair in the action
* @return Amount of node pair in the action
*/
size_t getNoOfNodePairs() const {
size_t noOfPairs = 0;
for(CSinglyLinkedList<CNodePairInfo*>::Iterator it = mNodePair.begin(); it != mNodePair.end(); ++it, noOfPairs++)
;
return noOfPairs;
}
/**
* Indicates if the action is to be executed locally or remotely. This function is used by the layer to decide which handler to use (local or remote)
* @return True if the action is to be executed remotely, false otherwise
*/
bool isRemote() const;
/**
* Factory to retrieve an action type from the parameters defined in the ID data input of the FB. The ID has the format ACTION;[ENDPOINT#];BROWSENAME,NODEID;[BROSWENAME,NODEID];...
* @param paParams Parameters set in the ID of the FB (string contained in the square brackets of opc_ua[...])
* @param paLayer The layer that creates and executes the action
* @param paTypes A list of type converters of the connections of the FB of the action (SDs/RDs)
* @return
*/
static CActionInfo* getActionInfoFromParams(const char *paParams, COPC_UA_Layer &paLayer);
/**
* Retrieves the array of CIEC_ANY to be sent
* @return the array of CIEC_ANY to be sent
*/
const CIEC_ANY* getDataToSend() const;
/**
* Retrieves the array of CIEC_ANY where to receive the data
* @return array of CIEC_ANY where to receive the data
*/
CIEC_ANY* getDataToReceive() const;
/**
* Retrieves the size of the array to send
* @return size of the array to send
*/
size_t getSendSize() const;
/**
* Retrieves the size of the array to receive
* @return size of the array to receive
*/
size_t getReceiveSize() const;
/**
* String representations of the actions and which should be provided as the first part of the ID
*/
static const char *const mActionNames[eActionUnknown];
private:
/**
* Copy constructor is private and not defined to avoid its usage
*/
CActionInfo(const CActionInfo &paObj);
/**
* Assignment operator is private and not defined to avoid its usage
*/
CActionInfo& operator=(const CActionInfo &paOther);
/**
* Checks if the action is valid regarding requirements for the amount of node pairs, endpoint value and the type of action
* @return True if the action is valid, false otherwise
*/
bool checkAction() const;
/**
* Checks if the provided node pair information is valid
* @return True if the node pair information is valid, false otherwise
*/
bool checkNodePairInfo() const;
/**
* Specific check for read action
* @param paFbType The type of FB that wants to executed the read action
* @param paNoOfRDs Number of RDs present in the FB
* @param paNoOfSDs Number of SDs present in the FB
* @return True if the read action is valid, false otherwise
*/
bool checkReadAction(forte::com_infra::EComServiceType paFbType, unsigned int paNoOfRDs, unsigned int paNoOfSDs) const;
/**
* Specific check for write action
* @param paFbType The type of FB that wants to executed the write action
* @param paNoOfRDs Number of RDs present in the FB
* @param paNoOfSDs Number of SDs present in the FB
* @return True if the write action is valid, false otherwise
*/
bool checkWriteAction(forte::com_infra::EComServiceType paFbType, unsigned int paNoOfRDs, unsigned int paNoOfSDs) const;
/**
* Specific check for create method action
* @param paFbType The type of FB that wants to executed the create method action
* @param paNoOfRDs Number of RDs present in the FB
* @param paNoOfSDs Number of SDs present in the FB
* @return True if the create method action is valid, false otherwise
*/
bool checkCreateMethodAction(forte::com_infra::EComServiceType paFbType, unsigned int paNoOfRDs, unsigned int paNoOfSDs) const;
/**
* Specific check for call method action
* @param paFbType The type of FB that wants to executed the call method action
* @param paNoOfRDs Number of RDs present in the FB
* @param paNoOfSDs Number of SDs present in the FB
* @return True if the call method action is valid, false otherwise
*/
bool checkCallMethodAction(forte::com_infra::EComServiceType paFbType, unsigned int paNoOfRDs, unsigned int paNoOfSDs) const;
/**
* Specific check for subscribe action
* @param paFbType The type of FB that wants to executed the subscribe action
* @param paNoOfRDs Number of RDs present in the FB
* @param paNoOfSDs Number of SDs present in the FB
* @return True if the subscribe action is valid, false otherwise
*/
bool checkSubscribeAction(forte::com_infra::EComServiceType paFbType, unsigned int paNoOfRDs, unsigned int paNoOfSDs) const;
/**
* Specific check for create object action
* @param paFbType The type of FB that wants to executed the create object action
* @param paNoOfRDs Number of RDs present in the FB
* @param paNoOfSDs Number of SDs present in the FB
* @return True if the create object action is valid, false otherwise
*/
bool checkCreateObjectAction(forte::com_infra::EComServiceType paFbType, unsigned int paNoOfRDs, unsigned int paNoOfSDs) const;
/**
* Specific check for create variable action
* @param paFbType The type of FB that wants to executed the create variable action
* @param paNoOfRDs Number of RDs present in the FB
* @param paNoOfSDs Number of SDs present in the FB
* @return True if the create variable action is valid, false otherwise
*/
bool checkCreateVariableAction(forte::com_infra::EComServiceType paFbType, unsigned int paNoOfRDs, unsigned int paNoOfSDs) const;
/**
* Specific check for delete node action
* @param paFbType The type of FB that wants to executed the delete node action
* @param paNoOfRDs Number of RDs present in the FB
* @param paNoOfSDs Number of SDs present in the FB
* @return True if the delete node action is valid, false otherwise
*/
bool checkDeleteNodeAction(forte::com_infra::EComServiceType paFbType, unsigned int paNoOfRDs, unsigned int paNoOfSDs) const;
/**
* The type of action to execute
*/
UA_ActionType mAction;
/**
* The layer that created the action
*/
COPC_UA_Layer &mLayer;
/**
* Empty if the action is executed locally, other value otherwise
*/
CIEC_STRING mEndpoint;
/**
* List of the node pair information about the nodes the action is accessing
*/
CSinglyLinkedList<CNodePairInfo*> mNodePair;
static const size_t scmMinimumAmounOfParameters = 2; //at least two are needed
/**
* Internal class to parse the parameters that are passed to the factory
*/
class CActionParser {
public:
enum IDPositions {
eActionType = 0,
eEndpoint,
eNodePairs
};
/**
* Retrieves the action type from a string defined in mActionNames
* @param paParams The string source
* @return Type according to the string parameter. eActionUnknown is returned if paParams doesn't match any value in mActionNames
*/
static UA_ActionType getActionEnum(const char *paParams);
/**
* Retrieves the endpoint from a string. The endpoint is signalized by a # character at the end of the string
* @param paEndpoint Source where the endpoint is present
* @param paResult Place to store the endpoint
* @return True if an endpoint was found, false otherwise
*/
static bool getEndpoint(const char *paEndpoint, CIEC_STRING &paResult);
/**
* Checks if a pair in a string form is valid and stores it in the result list. The node pair has format BROWSENAME,NODEID where BROWSENAME is a path string. @see parseNodeId for the format of NODEID
* @param paPair Source string containing the node pair information
* @param paResult Place to store a new allocated node pair info if the source was valid
* @return True if paPair contained a valid node pair information, false otherwise
*/
static bool handlePair(const char *paPair, CSinglyLinkedList<CNodePairInfo*> &paResult);
private:
/**
* Parse a node ID in a string format and returns a new allocated UA_NodeId pointer. The format of the node ID is as follow: <namespaceIndex>:<identifiertype>=<identifier> where namespaceIndex is a number, identifier depends on identifiertype. @see parseIdentifier for the format of identifiertype
* @param paNodeIdString The string source of the node ID
* @return 0 if the source string is invalid, a new allocated UA_NodeId with the information from the source otherwise
*/
static UA_NodeId* parseNodeId(const char *paNodeIdString);
/**
* Parse the namespace of the node ID from the string source
* @param paNamespace Source string containing the namespace
* @param paResult Place to store the result
* @return True if the source string has a valid namespace, false otherwise
*/
static bool parseNamespace(const char *paNamespace, UA_NodeId &paResult);
/**
* Parse the identifier of the node ID from the string source. Allowed values for identifier are [i, s, g] (numeric, string and bytestring node ID type respectively). GUID type is not supported
* @param paIdentifier Source string containing the identifier
* @param paResult Place to store the result
* @return True if the source string has a valid identifier, false otherwise
*/
static bool parseIdentifier(const char *paIdentifier, UA_NodeId &paResult);
enum NodePairPositions {
eBrowseName = 0,
eNodeId,
eMaxNumberOfPositions
};
enum NodeIdPositions {
eNamespace = 0,
eIdenfier,
eMaxNumberOfNodeIdPositions
};
enum NodeIdItenfierPositions {
eIdenfierType = 0,
eIdenfierValue,
eMaxNumberOfNodeIdIdenfiertPositions
};
};
};
/**
* Special case of an action because more information is needed
*/
class CLocalMethodInfo : public CActionInfo {
public:
/**
* Constructor of the class
* @param paLayer The layer that creates and executes the action
* @param paEndpoint The endpoint of a remote OPC UA in case the action is to be executed remotely. An empty endpoint means that the action is to be executed locally
* @param paTypes A list of type converters of the connections of the FB of the action (SDs/RDs)
*/
explicit CLocalMethodInfo(COPC_UA_Layer &paLayer, const CIEC_STRING &paEndpoint);
/**
* Destructor of the class
*/
~CLocalMethodInfo();
/**
* Getter for the semaphore of the action
* @return the semaphore of the action
*/
forte::arch::CSemaphore& getResultReady();
private:
/**
* Copy constructor is private and not defined to avoid its usage
*/
CLocalMethodInfo(const CLocalMethodInfo &paObj);
/**
* Assignment operator is private and not defined to avoid its usage
*/
CLocalMethodInfo& operator=(const CLocalMethodInfo &other);
/**
* When a method is called, it waits with this semaphore until the response comes back to the FB, when this semaphore is increased indicating the method has finished
*/
forte::arch::CSemaphore mResultIsReady;
};
#endif /* SRC_MODULES_OPC_UA_OPCUA_ACTION_INFO_H_ */