ANSI C UA Server SDK  1.5.1.313
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Modules Pages
custom_provider_call.c
/*****************************************************************************
* *
* Copyright (c) 2006-2015 Unified Automation GmbH. All rights reserved. *
* *
* Software License Agreement ("SLA") Version 2.5 *
* *
* Unless explicitly acquired and licensed from Licensor under another *
* license, the contents of this file are subject to the Software License *
* Agreement ("SLA") Version 2.5, or subsequent versions as allowed by the *
* SLA, and You may not copy or use this file in either source code or *
* executable form, except in compliance with the terms and conditions of *
* the SLA. *
* *
* All software distributed under the SLA is provided strictly on an "AS *
* IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, *
* AND LICENSOR HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT *
* LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR *
* PURPOSE, QUIET ENJOYMENT, OR NON-INFRINGEMENT. See the SLA for specific *
* language governing rights and limitations under the SLA. *
* *
* The complete license agreement can be found here: *
* http://unifiedautomation.com/License/SLA/2.5/ *
* *
* Project: Unified Automation ANSI C based OPC UA Server SDK *
* *
*****************************************************************************/
#include <uaserver_config.h>
#include <opcua_statuscodes.h>
#include <uaserver_call.h>
#include <uaserver_basenode.h>
#include <uaserver_utilities.h>
#include <uabase_p_atomic.h>
#include "custom_provider_helper.h"
OPCUA_BEGIN_EXTERN_C
OpcUa_StatusCode CustomProvider_CallAcknowledge(UaServer_Event *a_pEvent, OpcUa_CallMethodRequest* a_pRequest, OpcUa_CallMethodResult* a_pResult)
{
if (a_pRequest->NoOfInputArguments == 2)
{
a_pResult->StatusCode = OpcUa_Good;
a_pResult->NoOfInputArgumentResults = 2;
a_pResult->InputArgumentResults = (OpcUa_StatusCode*)OpcUa_Alloc(a_pResult->NoOfInputArgumentResults * sizeof(OpcUa_StatusCode));
OpcUa_MemSet(a_pResult->InputArgumentResults, 0, a_pResult->NoOfInputArgumentResults * sizeof(OpcUa_StatusCode));
if (a_pRequest->InputArguments[0].Datatype != OpcUaType_ByteString
|| a_pRequest->InputArguments[0].ArrayType != OpcUa_VariantArrayType_Scalar)
{
a_pResult->InputArgumentResults[0] = OpcUa_BadTypeMismatch;
a_pResult->StatusCode = OpcUa_BadTypeMismatch;
}
if (a_pRequest->InputArguments[1].Datatype != OpcUaType_LocalizedText
|| a_pRequest->InputArguments[1].ArrayType != OpcUa_VariantArrayType_Scalar)
{
a_pResult->InputArgumentResults[1] = OpcUa_BadTypeMismatch;
a_pResult->StatusCode = OpcUa_BadTypeMismatch;
}
/* check EventId */
if (OpcUa_IsGood(a_pResult->StatusCode))
{
OpcUa_ByteString *pEventId = UaServer_Events_GetEventId(a_pEvent);
if (OpcUa_ByteString_Compare(pEventId, &a_pRequest->InputArguments[0].Value.ByteString) != 0)
{
a_pResult->StatusCode = OpcUa_BadEventIdUnknown;
}
}
/* check AckedState */
if (OpcUa_IsGood(a_pResult->StatusCode))
{
OpcUa_Variant *pAckedState = (OpcUa_Variant*)UaBase_Vector_Get(&a_pEvent->EventFields, AcknowledgeableConditionTypeField_AckedState_Id);
a_pResult->StatusCode = OpcUa_BadConditionBranchAlreadyAcked;
if (pAckedState != OpcUa_Null
&& pAckedState->Datatype == OpcUaType_Boolean
&& pAckedState->ArrayType == OpcUa_VariantArrayType_Scalar
&& pAckedState->Value.Boolean == OpcUa_False)
{
a_pResult->StatusCode = OpcUa_Good;
}
}
if (OpcUa_IsGood(a_pResult->StatusCode))
{
OpcUa_Variant value;
OpcUa_NodeId *pSourceNode;
OpcUa_Variant_Initialize(&value);
value.Datatype = OpcUaType_LocalizedText;
value.Value.LocalizedText = (OpcUa_LocalizedText*)OpcUa_Alloc(sizeof(OpcUa_LocalizedText));
OpcUa_LocalizedText_Initialize(value.Value.LocalizedText);
OpcUa_String_StrnCat(&value.Value.LocalizedText->Text, OpcUa_String_FromCString("Acknowledged"), OPCUA_STRING_LENDONTCARE);
UaServer_Events_SetEventField(a_pEvent, AcknowledgeableConditionTypeField_AckedState, &value);
OpcUa_Variant_Clear(&value);
value.Datatype = OpcUaType_Boolean;
value.Value.Boolean = OpcUa_True;
UaServer_Events_SetEventField(a_pEvent, AcknowledgeableConditionTypeField_AckedState_Id, &value);
OpcUa_Variant_Clear(&value);
value.Datatype = OpcUaType_DateTime;
value.Value.DateTime = OpcUa_DateTime_UtcNow();
UaServer_Events_SetEventField(a_pEvent, AcknowledgeableConditionTypeField_AckedState_TransitionTime, &value);
OpcUa_Variant_Clear(&value);
value.Datatype = OpcUaType_LocalizedText;
value.Value.LocalizedText = (OpcUa_LocalizedText*)OpcUa_Alloc(sizeof(OpcUa_LocalizedText));
OpcUa_LocalizedText_Initialize(value.Value.LocalizedText);
OpcUa_LocalizedText_CopyTo(a_pRequest->InputArguments[1].Value.LocalizedText, value.Value.LocalizedText);
UaServer_Events_SetEventField(a_pEvent, ConditionTypeField_Comment, &value);
OpcUa_Variant_Clear(&value);
value.Datatype = OpcUaType_DateTime;
value.Value.DateTime = OpcUa_DateTime_UtcNow();
UaServer_Events_SetEventField(a_pEvent, ConditionTypeField_Comment_SourceTimestamp, &value);
OpcUa_Variant_Clear(&value);
/* get BaseNode of the SourceNode of the event and extract its UserData */
pSourceNode = ((OpcUa_Variant*)UaBase_Vector_Get(&a_pEvent->EventFields, BaseEventTypeField_SourceNode))->Value.NodeId;
if (pSourceNode != OpcUa_Null)
{
OpcUa_BaseNode *pBaseNode;
UaServer_GetNode(&g_pCustomProvider->AddressSpace, pSourceNode, &pBaseNode);
if (pBaseNode != OpcUa_Null)
{
UserDataCommon *pUserData = (UserDataCommon*)OpcUa_BaseNode_GetUserData(pBaseNode);
if (pUserData && pUserData->Type == UserDataMachine)
{
/* UserData is of type UserDataMachine, so the source of the event was a Machine.
now we can cast the UserData to a Machine struct and use it as needed. */
Machine *pMachineData = (Machine*)pUserData;
OpcUa_ReferenceParameter(pMachineData);
}
}
}
}
}
else
{
a_pResult->StatusCode = OpcUa_BadArgumentsMissing;
}
return OpcUa_Good;
}
IFMETHODIMP(CustomProvider_CallAsync)(UaServer_ProviderCallContext *a_pCallContext)
{
OpcUa_CallRequest *pRequest;
OpcUa_CallResponse *pResponse;
OpcUa_Int32 i;
OpcUa_BaseNode *pNode;
UaServer_AddressSpace *pAddressSpace = &(g_pCustomProvider->AddressSpace);
OpcUa_InitializeStatus(OpcUa_Module_Server, "CustomProvider_CallAsync");
OpcUa_ReturnErrorIfArgumentNull(a_pCallContext);
pRequest = a_pCallContext->pRequest;
pResponse = a_pCallContext->pResponse;
/* We will send exactly one callback */
UaBase_Atomic_Increment(&a_pCallContext->nOutstandingCbs);
/* Iterate over methods and check if the provider is responsible for processing them */
for (i = 0; i < pRequest->NoOfMethodsToCall; i++)
{
if (pRequest->MethodsToCall[i].MethodId.NamespaceIndex == g_uCustomProvider_NamespaceIndex &&
pRequest->MethodsToCall[i].ObjectId.NamespaceIndex == g_uCustomProvider_NamespaceIndex)
{
UaServer_GetNode(pAddressSpace, &pRequest->MethodsToCall[i].MethodId, &pNode);
if (pNode != OpcUa_Null)
{
UserDataCommon *pUserData = (UserDataCommon*)OpcUa_BaseNode_GetUserData(pNode);
if (pUserData != OpcUa_Null)
{
switch (pUserData->Type)
{
case UserDataMachine:
{
Machine *pMachine = (Machine*)pUserData;
/* Check if the method was called on the appropriate Machine */
if (OpcUa_NodeId_Compare(&pRequest->MethodsToCall[i].ObjectId, &pMachine->nodeId) != 0)
{
pResponse->Results[i].StatusCode = OpcUa_BadNotFound;
break;
}
/* Check input arguments */
if (pRequest->MethodsToCall[i].NoOfInputArguments == 1)
{
OpcUa_Variant *pInArg = &pRequest->MethodsToCall[i].InputArguments[0];
OpcUa_CallMethodResult *pResult = &pResponse->Results[i];
pResult->NoOfInputArgumentResults = 1;
pResult->InputArgumentResults = (OpcUa_StatusCode*)OpcUa_Alloc(sizeof(OpcUa_StatusCode));
if (pInArg->ArrayType == OpcUa_VariantArrayType_Scalar &&
pInArg->Datatype == OpcUaType_Boolean)
{
/* Set switch state */
*pMachine->pHeaterSwitch->pValue = pInArg->Value.Boolean;
pResult->InputArgumentResults[0] = OpcUa_Good;
}
else
{
pResult->InputArgumentResults[0] = OpcUa_BadTypeMismatch;
}
/* Fill output arguments */
pResult->NoOfOutputArguments = 1;
pResult->OutputArguments = (OpcUa_Variant*)OpcUa_Alloc(sizeof(OpcUa_Variant));
OpcUa_Variant_Initialize(&pResult->OutputArguments[0]);
pResult->OutputArguments[0].Datatype = OpcUaType_Double;
pResult->OutputArguments[0].Value.Double = *pMachine->pTemperatureSensor->pValue;
pResult->StatusCode = OpcUa_Good;
}
else
{
pResponse->Results[i].StatusCode = OpcUa_BadArgumentsMissing;
}
break;
}
default:
{
pResponse->Results[i].StatusCode = OpcUa_BadNotFound;
break;
}
}
}
}
}
else if (pRequest->MethodsToCall[i].ObjectId.NamespaceIndex == g_uCustomProvider_NamespaceIndex
&& pRequest->MethodsToCall[i].MethodId.NamespaceIndex == 0
&& pRequest->MethodsToCall[i].MethodId.IdentifierType == OpcUa_IdentifierType_Numeric)
{
switch (pRequest->MethodsToCall[i].MethodId.Identifier.Numeric)
{
case OpcUaId_AcknowledgeableConditionType_Acknowledge:
{
UaServer_Event *pEvent = UaServer_Events_GetConditionByNodeId(g_uCustomProvider_NamespaceIndex,
&pRequest->MethodsToCall[i].ObjectId);
if (pEvent != OpcUa_Null)
{
CustomProvider_CallAcknowledge(pEvent, &pRequest->MethodsToCall[i], &pResponse->Results[i]);
}
break;
}
default:
break;
}
}
}
/* Send callback */
UaServer_CallComplete(a_pCallContext);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
OPCUA_END_EXTERN_C