How to implement Query Service to Server?
Moderator: uasdkcpp
-
- Hero Member
- Posts: 20
- Joined: 07 Feb 2013, 11:01
How to implement Query Service to Server?
Hello,
What steps should I take to implement the Query service to server? How can I add my own QueryFirst/QueryNext handlers? There is a hard-coded array of supported services UaServer_SupportedServices[] in UAModule/uaserver.cpp. Should this class be copy-pasted or is there an easier way to go?
Thank You
What steps should I take to implement the Query service to server? How can I add my own QueryFirst/QueryNext handlers? There is a hard-coded array of supported services UaServer_SupportedServices[] in UAModule/uaserver.cpp. Should this class be copy-pasted or is there an easier way to go?
Thank You
- Support Team
- Hero Member
- Posts: 3068
- Joined: 18 Mar 2011, 15:09
Re:How to implement Query Service to Server?
Hello Toni,
This is the first request for supporting the QueryServiceSet in the C++ SDK.
We checked the necessary changes for passing on a Query request to the user specific code and there are several places that need to be extended.
There is the service handling in the Stub and the Server object, the continuation point handling in the session and the code that is necessary to pass on the query request to your code.
We can provide you a patch with a first prototype next week if you are interested.
What client would be used for testing on your side?
Best Regards,
Unified Automation Support Team
This is the first request for supporting the QueryServiceSet in the C++ SDK.
We checked the necessary changes for passing on a Query request to the user specific code and there are several places that need to be extended.
There is the service handling in the Stub and the Server object, the continuation point handling in the session and the code that is necessary to pass on the query request to your code.
We can provide you a patch with a first prototype next week if you are interested.
What client would be used for testing on your side?
Best Regards,
Unified Automation Support Team
Last edited by Support Team on 07 Feb 2013, 10:48, edited 1 time in total.
Best regards
Unified Automation Support Team
Unified Automation Support Team
-
- Hero Member
- Posts: 20
- Joined: 07 Feb 2013, 11:01
Re:How to implement Query Service to Server?
Hi,
Thanks for quick reply. Yes, I'd be very in interested in this patch, but to which version would it be? I am currently developing over 1.2.1, and I am not sure if I can to migrate to 1.3.0. I suspect there may not be enough work resources left to adapt with the changes in the Event Management.
The query client would be a quick and dirty test client that is set up from scratch. If you can suggest some, I'd be interested aswell?-)
Thanks
Toni
Thanks for quick reply. Yes, I'd be very in interested in this patch, but to which version would it be? I am currently developing over 1.2.1, and I am not sure if I can to migrate to 1.3.0. I suspect there may not be enough work resources left to adapt with the changes in the Event Management.
The query client would be a quick and dirty test client that is set up from scratch. If you can suggest some, I'd be interested aswell?-)
Thanks
Toni
- Support Team
- Hero Member
- Posts: 3068
- Joined: 18 Mar 2011, 15:09
Re:How to implement Query Service to Server?
Hello Toni,
The patch will be part of the upcoming service release for version 1.3 (V1.3.1). But we applied the patch also to V1.2.1 and can provide you a patch for this version as well. Please send an email to support@unifiedautomation.com to get the patch.
Here are the steps to get the query call in your own code based on the \"server hello world\" example:
Step (1)
Copy patch \"patchQuery_CppSdk1_2_1.patch\" to \"SdkInstallsrc\"
Apply patch
Step(2)
Copy the following files to
SdkInstallincludeuaserver
From SdkInstallsrcuaserveruaservercppuamodule
SdkInstallincludeuabase
From SdkInstallsrcuabaseuabasecpp
Compile SDK
Step(4)
Add the following classes to your project
Code header:
Code cpp:
Step(5)
Add the following code to servermain.cpp before calling pServer->start();
Step(6)
Compile server
Set breakpoint in MyUaTransactionManager::beginQuery()
Call QueryFirst from a client
This query call should end up in MyUaTransactionManager::beginQuery()
The patch will be part of the upcoming service release for version 1.3 (V1.3.1). But we applied the patch also to V1.2.1 and can provide you a patch for this version as well. Please send an email to support@unifiedautomation.com to get the patch.
Here are the steps to get the query call in your own code based on the \"server hello world\" example:
Step (1)
Copy patch \"patchQuery_CppSdk1_2_1.patch\" to \"SdkInstallsrc\"
Apply patch
Step(2)
Copy the following files to
SdkInstallincludeuaserver
From SdkInstallsrcuaserveruaservercppuamodule
- uamonitoreditem.h
- uaserver.h
- uasubscription.h
- uasubscriptionmanager.h
- uatransactionmanager.h
- continuationpoint.h
- session.h
SdkInstallincludeuabase
From SdkInstallsrcuabaseuabasecpp
- uaarraytemplates.h
Compile SDK
Step(4)
Add the following classes to your project
Code header:
Code: Select all
#ifndef __QUERY_H__
#define __QUERY_H__
#include \"uatransactionmanager.h\"
#include \"uaserver.h\"
#include \"opcserver.h\"
// Class implementing beginQuery() by overwriting UaTransactionManager::beginQuery()
class MyUaTransactionManager: public UaTransactionManager
{
public:
MyUaTransactionManager(ServerManager*, UaSubscriptionManager*);
virtual ~MyUaTransactionManager();
// Overwrite UaTransactionManager::beginQuery()
UaStatus beginQuery(UaQueryContext*);
};
// Class used to create the custom TransactionManager by overwriting UaServer::createUaTransactionManager
class MyUaServer: public UaServer
{
public:
MyUaServer();
virtual ~MyUaServer();
UaTransactionManager* createUaTransactionManager(ServerManager*, UaSubscriptionManager*);
};
// Callback interface implementation for OpcServer class to create custom UaServer object
class MyOpcServerCallback: public OpcServerCallback
{
public:
MyOpcServerCallback();
virtual ~MyOpcServerCallback();
Session* createSession(OpcUa_Int32 sessionID, const UaNodeId &authenticationToken);
UaStatus logonSessionUser(Session* pSession, UaUserIdentityToken* pUserIdentityToken);
UaServer* createUaServer();
};
#endif // __QUERY_H__
Code: Select all
#include \"query.h\"
///////////////////////////////////////////////////////////
///// Class implementing the custom query function ////////
MyUaTransactionManager::MyUaTransactionManager(
ServerManager* pServerManager,
UaSubscriptionManager* pUaSubscriptionManager)
: UaTransactionManager(pServerManager, pUaSubscriptionManager)
{
}
MyUaTransactionManager::~MyUaTransactionManager()
{
}
UaStatus MyUaTransactionManager::beginQuery(UaQueryContext* pUaQueryContext)
{
// Implement query here
return OpcUa_BadServiceUnsupported;
}
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///// Helper class to create custom transaction manager ///
MyUaServer::MyUaServer()
{
}
MyUaServer::~MyUaServer()
{
}
UaTransactionManager* MyUaServer::createUaTransactionManager(
ServerManager* pServerManager,
UaSubscriptionManager* pUaSubscriptionManager)
{
// Create custom UaTransactionManager object
return new MyUaTransactionManager(pServerManager, pUaSubscriptionManager);
}
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
// -- Callback for OpcServer object to create custom ------
// -- objects and to implement user authentication --------
MyOpcServerCallback::MyOpcServerCallback()
{
}
MyOpcServerCallback::~MyOpcServerCallback()
{
}
Session* MyOpcServerCallback::createSession(
OpcUa_Int32 sessionID,
const UaNodeId &authenticationToken)
{
return new UaSession(sessionID, authenticationToken);
}
UaStatus MyOpcServerCallback::logonSessionUser(
Session* pSession,
UaUserIdentityToken* pUserIdentityToken)
{
// Implement user validation here if needed
return OpcUa_BadUserAccessDenied;
}
UaServer* MyOpcServerCallback::createUaServer()
{
// Create custom UaServer object
return new MyUaServer();
}
///////////////////////////////////////////////////////////
Add the following code to servermain.cpp before calling pServer->start();
Code: Select all
MyOpcServerCallback serverCallback;
pServer->setCallback(&serverCallback);
// Start server object
ret = pServer->start();
Compile server
Set breakpoint in MyUaTransactionManager::beginQuery()
Call QueryFirst from a client
This query call should end up in MyUaTransactionManager::beginQuery()
Last edited by Support Team on 07 Feb 2013, 10:48, edited 1 time in total.
Best regards
Unified Automation Support Team
Unified Automation Support Team
- Support Team
- Hero Member
- Posts: 3068
- Joined: 18 Mar 2011, 15:09
Re:How to implement Query Service to Server?
Here is also some pseudo sample code. It is not a full implementation but it provides sample code for the context handling.
Fell free to post more sample code from your query implementation.
Fell free to post more sample code from your query implementation.
Code: Select all
// We need a user data class storing information for a continuation point
class MyContinuationPointData: public ContinuationPointUserDataBase
{
public:
MyContinuationPointData(){}
virtual ~MyContinuationPointData(){}
// Replace the member with the information you
// need to continue
int lastPosition;
};
UaStatus MyUaTransactionManager::beginQuery(UaQueryContext* pUaQueryContext)
{
UaStatus ret;
// Pseudo sample code for implementing the query
// Should be executed in a worker thread
//
bool moreResults = false;
int lastPosition = 0;
// Check if it is a QueryNext
if ( pUaQueryContext->getQueryType() == UaQueryContext::QueryNext )
{
// Get stored context of previous query
ContinuationPointUserDataBase* pUserData = pUaQueryContext->m_pQueryContext->detachUserData();
MyContinuationPointData* pCPData = (MyContinuationPointData*)pUserData;
lastPosition = pCPData->lastPosition;
delete pCPData;
}
// Check if it is a QueryFirst
if ( pUaQueryContext->getQueryType() == UaQueryContext::QueryFirst )
{
UaQueryFirstContext* pQueryFirstContext = (UaQueryFirstContext*)pUaQueryContext;
// Verify NodeTypes[]
pUaQueryContext->m_pQueryContext->noOfNodeTypes();
pUaQueryContext->m_pQueryContext->pNodeTypes();
// Set parsing results
pQueryFirstContext->m_parsingResults;
// Verify Filter
pUaQueryContext->m_pQueryContext->pFilter();
// Set FilterResult
pQueryFirstContext->m_filterResult;
}
// -------------------------------------
// Execute or continue query
// -------------------------------------
// Set results
pUaQueryContext->m_queryDataSets.create(1);
if ( moreResults )
{
MyContinuationPointData* pCPData = new MyContinuationPointData;
pCPData->lastPosition = lastPosition;
pUaQueryContext->m_pQueryContext->setUserData(pCPData);
}
// Send the response to the client
pUaQueryContext->sendResponse();
// Delete query context if response was sent
// Do not send a response or delete this object if UaTransactionManager::beginQuery returns an error
delete pUaQueryContext;
return ret;
}
Last edited by Support Team on 07 Feb 2013, 10:48, edited 1 time in total.
Best regards
Unified Automation Support Team
Unified Automation Support Team
- Support Team
- Hero Member
- Posts: 3068
- Joined: 18 Mar 2011, 15:09
Re:How to implement Query Service to Server?
We added Query support also to the client side but the patch there requires V1.3 of the C++ SDK.
Best Regards,
Unified Automation Support Team
Best Regards,
Unified Automation Support Team
Last edited by Support Team on 07 Feb 2013, 10:48, edited 1 time in total.
Best regards
Unified Automation Support Team
Unified Automation Support Team
-
- Hero Member
- Posts: 20
- Joined: 07 Feb 2013, 11:01
Re:How to implement Query Service to Server?
Thanks a lot for the great examples B)
They've helped to get started.
Toni
They've helped to get started.
Toni
-
- Hero Member
- Posts: 20
- Joined: 07 Feb 2013, 11:01
Re:How to implement Query Service to Server?
Hi,
I am not sure if this is a forgotten feature or misunderstanding on my behalf, but I cannot get the array size of the BrowsePath in UaSimpleAttributeOperand.
There is a setter for any index, and there is a getter for the whole array as a raw memory pointer. But I cannot iterate the raw array without knowing its size (NoOfBrowsePath).
For now, I can work-around with getSimpleAttributeOperand(ptr, false);
Also, in FilterOperandType there is "SimpleAttribute", but not "Attribute". This is probably omited for a reason? I cannot diffrentiate the two in the spec, except for the editors annotation in the latter.
I am not sure if this is a forgotten feature or misunderstanding on my behalf, but I cannot get the array size of the BrowsePath in UaSimpleAttributeOperand.
There is a setter for any index, and there is a getter for the whole array as a raw memory pointer. But I cannot iterate the raw array without knowing its size (NoOfBrowsePath).
Code: Select all
class UABASE_EXPORT UaSimpleAttributeOperand: public UaFilterOperand
{
...
void setBrowsePathElement(OpcUa_UInt32 index, const UaQualifiedName& name, OpcUa_UInt32 arraySize);
const OpcUa_QualifiedName* browsePath() const;
}
Also, in FilterOperandType there is "SimpleAttribute", but not "Attribute". This is probably omited for a reason? I cannot diffrentiate the two in the spec, except for the editors annotation in the latter.
- Support Team
- Hero Member
- Posts: 3068
- Joined: 18 Mar 2011, 15:09
Re:How to implement Query Service to Server?
You are right. The getter for the array size is missing.
We will add the getter to the next service release version.
To add the missing method you should add the following to the class declaration:
and the following to the class implementation:
Best Regards,
Unified Automation Support Team
We will add the getter to the next service release version.
To add the missing method you should add the following to the class declaration:
Code: Select all
OpcUa_UInt32 noOfBrowsePath()const;
const OpcUa_QualifiedName* browsePath() const;
Code: Select all
OpcUa_UInt32 UaSimpleAttributeOperand::noOfBrowsePath()const
{
return m_browsePath.length();
}
Unified Automation Support Team
Best regards
Unified Automation Support Team
Unified Automation Support Team