UA ANSI C Server Professional  1.4.0.285
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
custom_provider_read.c
/******************************************************************************
**
** Copyright (C) 2011-2014 Unified Automation GmbH. All Rights Reserved.
** Web: http://www.unifiedautomation.com
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Project: OPC Ansi C OPC Server Examples
**
******************************************************************************/
#include <uaserver_config.h>
#include <opcua_statuscodes.h>
#include <uaserver_read.h>
#include <uaserver_basenode.h>
#include <uaserver_utilities.h>
#include <uaserver_p_atomic.h>
#include "custom_provider_helper.h"
OPCUA_BEGIN_EXTERN_C
IFMETHODIMP(CustomProvider_ReadAsync)(UaServer_ProviderReadContext *a_pReadCtx)
{
OpcUa_ReadRequest *pReq;
OpcUa_ReadResponse *pRes;
OpcUa_Int32 i;
OpcUa_BaseNode *pNode;
OpcUa_NodeId *pNodeId = OpcUa_Null;
UaServer_AddressSpace *pAddressSpace = &(g_pCustomProvider->AddressSpace);
OpcUa_InitializeStatus(OpcUa_Module_Server, "CustomProvider_ReadAsync");
OpcUa_ReturnErrorIfArgumentNull(a_pReadCtx);
pReq = a_pReadCtx->pRequest;
pRes = a_pReadCtx->pResponse;
/* We will send exactly one callback */
UaServer_Atomic_Increment(&a_pReadCtx->nOutstandingCbs);
/* Iterate over nodes and check if the provider is responsible for processing them */
for (i = 0; i < pReq->NoOfNodesToRead; i++)
{
if (pReq->NodesToRead[i].NodeId.NamespaceIndex == g_uCustomProvider_NamespaceIndex)
{
pNodeId = &(pReq->NodesToRead[i].NodeId);
UaServer_GetNode(pAddressSpace, pNodeId, &pNode);
if (pNode)
{
UserDataCommon *pUserData = OpcUa_Null;
if ( (a_pReadCtx->pRequest->NodesToRead[i].AttributeId == OpcUa_Attributes_Value &&
OpcUa_BaseNode_GetType(pNode) == eVariable &&
(OpcUa_Variable_GetAccessLevel(pNode) & OpcUa_AccessLevels_CurrentRead) == 0) )
{
pRes->Results[i].StatusCode = OpcUa_BadNotReadable;
continue;
}
pUserData = (UserDataCommon*)OpcUa_BaseNode_GetUserData(pNode);
if (pUserData != OpcUa_Null &&
a_pReadCtx->pRequest->NodesToRead[i].AttributeId == OpcUa_Attributes_Value)
{
switch (pUserData->Type)
{
case UserDataTemperature:
{
TemperatureSensor *pSensor = (TemperatureSensor*)pUserData;
pRes->Results[i].Value.Datatype = OpcUaType_Double;
pRes->Results[i].Value.Value.Double = *pSensor->pValue;
pRes->Results[i].StatusCode = OpcUa_Good;
break;
}
case UserDataMachineSwitch:
{
MachineSwitch *pSwitch = (MachineSwitch*)pUserData;
pRes->Results[i].Value.Datatype = OpcUaType_Boolean;
pRes->Results[i].Value.Value.Boolean = *pSwitch->pValue;
pRes->Results[i].StatusCode = OpcUa_Good;
break;
}
default:
{
pRes->Results[i].StatusCode = OpcUa_BadNotReadable;
break;
}
}
/* Set timestamps */
if (OpcUa_IsGood(pRes->Results[i].StatusCode))
{
if (a_pReadCtx->pRequest->TimestampsToReturn == OpcUa_TimestampsToReturn_Source ||
a_pReadCtx->pRequest->TimestampsToReturn == OpcUa_TimestampsToReturn_Both)
{
pRes->Results[i].SourceTimestamp = OpcUa_DateTime_UtcNow();
}
if (a_pReadCtx->pRequest->TimestampsToReturn == OpcUa_TimestampsToReturn_Server ||
a_pReadCtx->pRequest->TimestampsToReturn == OpcUa_TimestampsToReturn_Both)
{
pRes->Results[i].ServerTimestamp = OpcUa_DateTime_UtcNow();
}
}
}
else
{
/* Use the SDK's helper function to process the request */
UaServer_ReadInternal(pNode, a_pReadCtx, i);
}
}
else
{
pRes->Results[i].StatusCode = OpcUa_BadNodeIdUnknown;
}
}
}
/* Send callback */
UaServer_ReadComplete(a_pReadCtx);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
OPCUA_END_EXTERN_C