Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring application service interface #65

Closed
huebl opened this issue Dec 21, 2018 · 8 comments

Comments

@huebl
Copy link
Contributor

commented Dec 21, 2018

For the implementation of simple tasks, the application service interface is partly too complicated. Therefore, w rework should be done. The following parts should be revised.

  • ServiceTransactionNamespace

  • ServiceTransactionRegisterForwardNode

  • ServiceTransactionRegisterForwardMethod

  • ServiceTransactionRegisterForwardGlobal

  • ServiceTransactionCreateNodeInstance

  • ServiceTransactionDelNodeInstance

  • ServiceTransactionFireEvent

  • ServiceTransactionBrowsePathToNodeId

  • Documentation

@huebl huebl added the enhancement label Dec 21, 2018

@flipback

This comment has been minimized.

Copy link
Member

commented Dec 21, 2018

Related issues #59 , #64 , #58

@huebl huebl referenced this issue Dec 27, 2018
8 of 8 tasks complete

@huebl huebl added this to To do in Release-3.7.0 Dec 29, 2018

@huebl

This comment has been minimized.

Copy link
Contributor Author

commented Dec 29, 2018

The Node Id consists of the ID and the namespace index. When starting the server, the ID is always the same, but the namespace index is not. For this reason, before accessing a variable, a mapping must be made between the Namespace Name and the Index namespace. The class GetNamespaceinfo is used for this.

	bool
	TestFolderLib::getNamespaceInfo(void)
	{
		GetNamespaceInfo getNamespaceInfo;

		if (!getNamespaceInfo.query(applicationServiceIf_)) {
			std::cout << "NamespaceInfoResponse error" << std::endl;
			return false;
		}

		namespaceIndex_ = getNamespaceInfo.getNamespaceIndex("http://ASNeG-Demo.de/Test-Server-Lib/");
		if (namespaceIndex_) {
			std::cout << "namespace index not found: http://ASNeG-Demo.de/Test-Server-Lib/" << std::endl;
			return false;
		}

		return true;
	}

@huebl huebl moved this from To do to In progress in Release-3.7.0 Dec 29, 2018

@huebl

This comment has been minimized.

Copy link
Contributor Author

commented Dec 29, 2018

For nodes in the information model, various event functions can be registered. Functions can be registered for the following events.

  • read
  • write
  • historical read
  • historical write
  • historical read event
  • monitored item start
  • monitored item stop

Example:

	bool
	TestFolderLib::registerCallbacks(void)
	{
		RegisterForwardNode registerForwardNode(valueVec_);
		registerForwardNode.setReadCallback(boost::bind(&TestFolderLib::readValue, this, _1));
		registerForwardNode.setWriteCallback(boost::bind(&TestFolderLib::writeValue, this, _1));
		if (!registerForwardNode.query(applicationServiceIf_, true)) {
			std::cout << "registerForwardNode response error" << std::endl;
			return false;
		}
	    return true;
	}

	void
	TestFolderLib::readValue(ApplicationReadContext* applicationReadContext)
	{
        }

	void
	TestFolderLib::writeValue(ApplicationWriteContext* applicationWriteContext)
	{
        }
@huebl

This comment has been minimized.

Copy link
Contributor Author

commented Dec 30, 2018

OPC UA methods can be registered as follows.

	bool
	ServiceFunction::registerCallbacks(const OpcUaNodeId& objectNodeId, const OpcUaNodeId& methodNodeId)
	{
		RegisterForwardMethod registerForwardMethod(objectNodeId, methodNodeId);
		registerForwardMethod.setMethodCallback(boost::bind(&ServiceFunction::method, this, _1));
		if (!registerForwardMethod.query(applicationServiceIf_)) {
			std::cout << "registerForwardNode response error" << std::endl;
			return false;
		}
	    return true;
	}

	void
	ServiceFunction::method(ApplicationMethodContext* applicationMethodContext)
	{
        }
@huebl

This comment has been minimized.

Copy link
Contributor Author

commented Dec 30, 2018

For the information model, various event functions can be registered. Functions can be registered for the following events.

  • register server
  • find server
  • event item start
  • event item stop
  • authentication
  • autorization
  • close session
  • node new
  • node delete

Example:

	bool
	Authentication::registerAuthenticationCallback(void)
	{
		RegisterForwardGlobal registerForwardGlobal;
		registerForwardGlobal.setAuthenticationCallback(boost::bind(&Authentication::authenticationCallback, this, _1));
		registerForwardGlobal.setAutorizationCallback(boost::bind(&Authentication::autorizationCallback, this, _1));
		registerForwardGlobal.setCloseSessionCallback(boost::bind(&Authentication::closeSessionCallback, this, _1));
		if (!registerForwardGlobal.query(applicationServiceIf_)) {
			std::cout << "registerForwardGlobal response error" << std::endl;
			return false;
		}
	    return true;
	}

	void
	Authentication::authenticationCallback(ApplicationAuthenticationContext* applicationAuthenitcationContext)
	{
	}

	void
	Authentication::closeSessionCallback(ApplicationCloseSessionContext* applicationCloseSessionContext)
	{
	}

	void
	Authentication::autorizationCallback(ApplicationAutorizationContext* applicationAutorizationContext)
	{
	}
@huebl

This comment has been minimized.

Copy link
Contributor Author

commented Dec 30, 2018

Example to fire event:

		FireEvent fireEvent(OpcUaNodeId("Event12", namespaceIndex_), customerEventType);
		if (!fireEvent.fireEvent(applicationServiceIf_)) {
			std::cout << "event response error" << std::endl;
		}
@huebl

This comment has been minimized.

Copy link
Contributor Author

commented Dec 30, 2018

The browse path to node id service gets a node identifier for a given browse path.

Example:

		BrowsePathToNodeId browsePathToNodeId({
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("AckedState")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("AckedState"), OpcUaQualifiedName("Id")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("ConfirmedState")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("ConfirmedState"), OpcUaQualifiedName("Id")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("ActiveState")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("ActiveState"), OpcUaQualifiedName("Id")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("EnabledState")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("EnabledState"), OpcUaQualifiedName("Id")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("Comment")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("Comment"), OpcUaQualifiedName("SourceTimestamp")),

			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("Acknowledge")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("Confirm")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("AddComment")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("Enable")),
			BrowseName(OpcUaNodeId("AlarmObject", namespaceIndex_), OpcUaQualifiedName("Disable")),
		});

		if (!browsePathToNodeId.query(applicationServiceIf_, true)) {
			std::cout << "browse path to node id error" << std::endl;
			return false;
		}

		ackedStateNodeId_ = browsePathToNodeId.nodes()[0];
		ackedStateIdNodeId_ = browsePathToNodeId.nodes()[1];
		confirmedStateNodeId_ = browsePathToNodeId.nodes()[2];
		confirmedStateIdNodeId_ = browsePathToNodeId.nodes()[3];
		activeStateNodeId_ = browsePathToNodeId.nodes()[4];
		activeStateIdNodeId_ = browsePathToNodeId.nodes()[5];
		enabledStateNodeId_ = browsePathToNodeId.nodes()[6];
		enabledStateIdNodeId_ = browsePathToNodeId.nodes()[7];
		commentNodeId_ = browsePathToNodeId.nodes()[8];
		commentSourceTimestampNodeId_ = browsePathToNodeId.nodes()[9];

		acknowlegeNodeId_ = browsePathToNodeId.nodes()[10];
		confirmNodeId_ = browsePathToNodeId.nodes()[11];
		addCommentNodeId_ = browsePathToNodeId.nodes()[12];
		enabledNodeId_ = browsePathToNodeId.nodes()[13];
		disableNodeId_ = browsePathToNodeId.nodes()[14];
@huebl

This comment has been minimized.

Copy link
Contributor Author

commented Dec 31, 2018

Example to create and delete variables:

	void
	CreateDeleteNode::timerLoop(void)
	{
		if (nodesExist_) {

			DeleteNodeInstance deleteNodeInstance(OpcUaNodeId("Dynamic", 1));

			if (!deleteNodeInstance.query(applicationServiceIf_)) {
				std::cout << "deleteNodeInstance response error" << std::endl;
				return;
			}

			nodesExist_ = false;
		}
		else {

			CreateNodeInstance createNodeInstance(
				"DynamicVariable",								// name
				NodeClassType_Variable,							// node class
				OpcUaNodeId(85),								// parent node id (Objects)
				OpcUaNodeId("Dynamic", 1),						// node id
				OpcUaLocalizedText("en", "DynamicVariable"),	// dispplay name
				OpcUaQualifiedName("DynamicVariable", 1),		// browse name
				OpcUaNodeId(47),								// reference type id
				OpcUaNodeId(62)									// type node id
			);

			if (!createNodeInstance.query(applicationServiceIf_)) {
				std::cout << "createNodeInstance response error" << std::endl;
				return;
			}

			nodesExist_ = true;
		}
	}

@flipback flipback moved this from In progress to Done in Release-3.7.0 Mar 31, 2019

@flipback flipback closed this Apr 14, 2019

@huebl huebl added this to Done in Release-4.0.0 Jun 29, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
2 participants
You can’t perform that action at this time.