ANSI C Based OPC UA Client/Server/PubSub SDK  1.9.4.474
uaprovider_demo_historyread.c
/*****************************************************************************
*
* Copyright (c) 2006-2023 Unified Automation GmbH. All rights reserved.
*
* Software License Agreement ("SLA") Version 2.8
*
* 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.8, 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.8/
*
* Project: OPC Ansi C DemoProvider for namespace
* 'http://www.unifiedautomation.com/DemoServer/'
*
****************************************************************************/
#include <uaserver_config.h>
#include <opcua_statuscodes.h>
#include <uabase_p_atomic.h>
#include <uaserver_basenode.h>
#include <uaserver_utilities.h>
#include <uaserver_historyread.h>
#include "uaprovider_demo_hooks.h"
#include "uaprovider_demo_userdata.h"
#if HAVE_DATA_LOGGER
#include <uaserver_datalogger.h>
#endif /* HAVE_DATA_LOGGER */
OPCUA_BEGIN_EXTERN_C
OpcUa_Void UaProvider_Demo_HistoryReadRawModifiedAsync_DeleteUserData(struct _UaServer_ContinuationPointHistoryInfo* pContinuationPointHistoryInfo)
{
OpcUa_ByteString_Clear(pContinuationPointHistoryInfo->pUserData);
OpcUa_Free(pContinuationPointHistoryInfo->pUserData);
return;
}
IFMETHODIMP(UaProvider_Demo_HistoryReadRawModifiedAsync)(UaServer_ProviderHistoryReadRawModifiedContext* a_pHistoryReadRawModifiedCtx)
{
OpcUa_Int32 i;
OpcUa_BaseNode *pNode = OpcUa_Null;
OpcUa_NodeId *pNodeId;
UaServer_AddressSpace *pAddressSpace = &(g_pDemoProvider->AddressSpace);
OpcUa_StatusCode uStatus = OpcUa_Good;
UaServer_Configuration *pConfig = UaServer_GetConfiguration(((UaServer_HistoryReadContext*)a_pHistoryReadRawModifiedCtx)->pUaServer);
OpcUa_ReturnErrorIfArgumentNull(a_pHistoryReadRawModifiedCtx);
/* we will send exactly one callback */
UaBase_Atomic_Increment(&a_pHistoryReadRawModifiedCtx->nOutstandingCbs);
/* process nodes */
for (i = 0; i < a_pHistoryReadRawModifiedCtx->NoOfNodesToRead; i++)
{
pNodeToRead = &a_pHistoryReadRawModifiedCtx->pNodesToRead[i];
pNodeId = &pNodeToRead->NodeId;
if (!UaServer_IsNamespaceOwner(g_pDemoProvider, pNodeId->NamespaceIndex))
continue;
UaServer_GetNode(pAddressSpace, pNodeId, &pNode);
if (pNode)
{
if (OpcUa_BaseNode_GetClass(pNode) != OpcUa_NodeClass_Variable ||
(OpcUa_Variable_GetAccessLevel(pNode) & OpcUa_AccessLevels_HistoryRead) == 0)
{
a_pHistoryReadRawModifiedCtx->pResponse->Results[i].StatusCode = OpcUa_BadNotReadable;
continue;
}
#if UASERVER_SUPPORT_AUTHORIZATION
/* Check if the user has the necessary permission to read the history */
if (!UaServer_UserMgt_IsHistoryReadable(OpcUa_BaseNode_GetINode(pNode), a_pHistoryReadRawModifiedCtx->pSession->UserIdentityData))
{
a_pHistoryReadRawModifiedCtx->pResponse->Results[i].StatusCode = OpcUa_BadNotReadable;
continue;
}
#endif
#if HAVE_DATA_LOGGER && UASERVER_DATALOGGER_SUPPORT_DATA
if (OpcUa_BaseNode_GetId(pNode)->IdentifierType == OpcUa_IdentifierType_Numeric
|| OpcUa_BaseNode_GetId(pNode)->IdentifierType == OpcUa_IdentifierType_String)
{
OpcUa_HistoryReadResult *pHistoryResult = &a_pHistoryReadRawModifiedCtx->pResponse->Results[i];
UaProvider_Demo_UserData *pUserData = OpcUa_BaseNode_GetUserData(pNode);
if (pUserData && pUserData->UserDataType == UaProvider_Demo_UserDataType_HistoryDataLogger)
{
OpcUa_Int32 noOfHistoryContinuationPoints;
OpcUa_Int32 iCount;
OpcUa_ReadRawModifiedDetails *pHistoryReadRawModifiedDetails = a_pHistoryReadRawModifiedCtx->pHistoryReadRawModifiedDetails;
OpcUa_TimestampsToReturn TimestampsToReturn = a_pHistoryReadRawModifiedCtx->TimestampsToReturn;
UaServer_ContinuationPointHistoryInfo *pContinuationPointHistoryInfo = OpcUa_Null;
if (a_pHistoryReadRawModifiedCtx->pNodesToRead[i].ContinuationPoint.Data != OpcUa_Null)
{
noOfHistoryContinuationPoints = UaBase_RingBuffer_Count(&a_pHistoryReadRawModifiedCtx->pSession->HistoryContinuationPoints);
for (iCount = 0; iCount < noOfHistoryContinuationPoints; iCount++)
{
UaServer_ContinuationPointHistoryInfo* pTmpInfo = UaBase_RingBuffer_Pop(&a_pHistoryReadRawModifiedCtx->pSession->HistoryContinuationPoints);
if (OpcUa_ByteString_Compare(&pTmpInfo->ContinuationPoint, &a_pHistoryReadRawModifiedCtx->pNodesToRead[i].ContinuationPoint) == 0)
{
pContinuationPointHistoryInfo = pTmpInfo;
OpcUa_ByteString_Clear(&a_pHistoryReadRawModifiedCtx->pNodesToRead[i].ContinuationPoint);
OpcUa_ByteString_CopyTo(pContinuationPointHistoryInfo->pUserData, &a_pHistoryReadRawModifiedCtx->pNodesToRead[i].ContinuationPoint);
pHistoryReadRawModifiedDetails = UaServer_GetHistoryReadRawModifiedDetails(&pContinuationPointHistoryInfo->HistoryReadDetails);
TimestampsToReturn = pContinuationPointHistoryInfo->TimestampsToReturn;
break;
}
UaBase_RingBuffer_Push(&a_pHistoryReadRawModifiedCtx->pSession->HistoryContinuationPoints, pTmpInfo);
}
}
if (pContinuationPointHistoryInfo != OpcUa_Null &&
OpcUa_NodeId_Compare(&a_pHistoryReadRawModifiedCtx->pNodesToRead[i].NodeId, &pContinuationPointHistoryInfo->NodeId) != 0)
{
a_pHistoryReadRawModifiedCtx->pResponse->Results[i].StatusCode = OpcUa_BadContinuationPointInvalid;
continue;
}
pUserData->Data.HistoryDataLogger.DataLogger,
pUserData->Data.HistoryDataLogger.DataLogItem,
pHistoryReadRawModifiedDetails,
TimestampsToReturn,
a_pHistoryReadRawModifiedCtx->ReleaseContinuationPoints,
&a_pHistoryReadRawModifiedCtx->pNodesToRead[i],
pHistoryResult,
a_pHistoryReadRawModifiedCtx->RequestHeader.TimeoutHint);
a_pHistoryReadRawModifiedCtx->pResponse->Results[i].StatusCode = ret;
if (pContinuationPointHistoryInfo == OpcUa_Null)
{
if (pHistoryResult->ContinuationPoint.Data != OpcUa_Null)
{
/* only emit error if more than MaxHistoryContinuationPoints are used in one single HistoryRead call */
if (a_pHistoryReadRawModifiedCtx->nCreatedContinuationPoints == pConfig->uMaxHistoryContinuationPointsPerSession)
{
OpcUa_ByteString_Clear(&pHistoryResult->ContinuationPoint);
pHistoryResult->StatusCode = OpcUa_BadNoContinuationPoints;
}
pContinuationPointHistoryInfo = UaServer_ContinuationPointHistoryInfo_Create();
UaServer_ContinuationPointHistoryInfo_InitCPData(pContinuationPointHistoryInfo);
OpcUa_NodeId_CopyTo(&a_pHistoryReadRawModifiedCtx->pNodesToRead[i].NodeId, &pContinuationPointHistoryInfo->NodeId);
pContinuationPointHistoryInfo->fctDeleteUserData = UaProvider_Demo_HistoryReadRawModifiedAsync_DeleteUserData;
pContinuationPointHistoryInfo->pUserData = OpcUa_Alloc(sizeof(OpcUa_ByteString));
OpcUa_ByteString_Initialize(pContinuationPointHistoryInfo->pUserData);
OpcUa_ByteString_CopyTo(&pHistoryResult->ContinuationPoint, pContinuationPointHistoryInfo->pUserData);
OpcUa_ByteString_Clear(&pHistoryResult->ContinuationPoint);
pHistoryReadRawModifiedDetails = OpcUa_Null;
OpcUa_EncodeableObject_CreateExtension(&OpcUa_ReadRawModifiedDetails_EncodeableType,
&pContinuationPointHistoryInfo->HistoryReadDetails,
(OpcUa_Void**)&pHistoryReadRawModifiedDetails);
OpcUa_ReadRawModifiedDetails_CopyTo(a_pHistoryReadRawModifiedCtx->pHistoryReadRawModifiedDetails, pHistoryReadRawModifiedDetails);
pContinuationPointHistoryInfo->TimestampsToReturn = a_pHistoryReadRawModifiedCtx->TimestampsToReturn;
uStatus = UaServer_ContinuationPointHistoryInfo_AddToList(pContinuationPointHistoryInfo, (UaServer_PublicSession*)a_pHistoryReadRawModifiedCtx->pSession);
if (OpcUa_IsBad(uStatus))
{
UaServer_ContinuationPointHistoryInfo_Delete(pContinuationPointHistoryInfo);
pContinuationPointHistoryInfo = OpcUa_Null;
pHistoryResult->StatusCode = uStatus;
}
else
{
OpcUa_ByteString_CopyTo(&pContinuationPointHistoryInfo->ContinuationPoint, &pHistoryResult->ContinuationPoint);
a_pHistoryReadRawModifiedCtx->nCreatedContinuationPoints++;
}
}
}
else
{
if (pHistoryResult->ContinuationPoint.Data != OpcUa_Null)
{
OpcUa_ByteString_Clear(pContinuationPointHistoryInfo->pUserData);
OpcUa_ByteString_CopyTo(&pHistoryResult->ContinuationPoint, pContinuationPointHistoryInfo->pUserData);
OpcUa_ByteString_Clear(&pHistoryResult->ContinuationPoint);
uStatus = UaServer_ContinuationPointHistoryInfo_AddToList(pContinuationPointHistoryInfo, (UaServer_PublicSession*)a_pHistoryReadRawModifiedCtx->pSession);
if (OpcUa_IsBad(uStatus))
{
UaServer_ContinuationPointHistoryInfo_Delete(pContinuationPointHistoryInfo);
pContinuationPointHistoryInfo = OpcUa_Null;
pHistoryResult->StatusCode = uStatus;
}
else
{
OpcUa_ByteString_CopyTo(&pContinuationPointHistoryInfo->ContinuationPoint, &pHistoryResult->ContinuationPoint);
}
}
else
{
UaServer_ContinuationPointHistoryInfo_Delete(pContinuationPointHistoryInfo);
pContinuationPointHistoryInfo = OpcUa_Null;
}
}
}
else
{
a_pHistoryReadRawModifiedCtx->pResponse->Results[i].StatusCode = OpcUa_BadNotReadable;
}
}
#endif /* HAVE_DATA_LOGGER && UASERVER_DATALOGGER_SUPPORT_DATA */
}
}
/* send callback */
UaServer_HistoryReadRawModifiedComplete(a_pHistoryReadRawModifiedCtx);
return OpcUa_Good;
}
IFMETHODIMP(UaProvider_Demo_HistoryReadEventAsync)(UaServer_ProviderHistoryReadEventContext* a_pHistoryReadEventCtx)
{
OpcUa_Int32 i;
OpcUa_BaseNode *pNode = OpcUa_Null;
OpcUa_NodeId *pNodeId;
UaServer_AddressSpace *pAddressSpace = &(g_pDemoProvider->AddressSpace);
OpcUa_ReturnErrorIfArgumentNull(a_pHistoryReadEventCtx);
/* we will send exactly one callback */
UaBase_Atomic_Increment(&a_pHistoryReadEventCtx->nOutstandingCbs);
/* process nodes */
for (i = 0; i < a_pHistoryReadEventCtx->NoOfNodesToRead; i++)
{
pNodeToRead = &a_pHistoryReadEventCtx->pNodesToRead[i];
pNodeId = &pNodeToRead->NodeId;
if (!UaServer_IsNamespaceOwner(g_pDemoProvider, pNodeId->NamespaceIndex))
continue;
UaServer_GetNode(pAddressSpace, pNodeId, &pNode);
if (pNode)
{
if (OpcUa_BaseNode_GetClass(pNode) != OpcUa_NodeClass_Object ||
(OpcUa_Object_GetEventNotifier(pNode) & OpcUa_EventNotifiers_HistoryRead) == 0)
{
a_pHistoryReadEventCtx->pResponse->Results[i].StatusCode = OpcUa_BadNotReadable;
continue;
}
#if UASERVER_SUPPORT_AUTHORIZATION
/* Check if the user has the necessary permission to read the event history */
if (!UaServer_UserMgt_IsHistoryReadable(OpcUa_BaseNode_GetINode(pNode), a_pHistoryReadEventCtx->pSession->UserIdentityData))
{
a_pHistoryReadEventCtx->pResponse->Results[i].StatusCode = OpcUa_BadNotReadable;
continue;
}
#endif
/* TODO */
}
}
/* send callback */
UaServer_HistoryReadEventComplete(a_pHistoryReadEventCtx);
return OpcUa_Good;
}
IFMETHODIMP(UaProvider_Demo_HistoryReadProcessedAsync)(UaServer_ProviderHistoryReadProcessedContext* a_pHistoryReadProcessedCtx)
{
OpcUa_Int32 i;
OpcUa_BaseNode *pNode = OpcUa_Null;
OpcUa_NodeId *pNodeId;
UaServer_AddressSpace *pAddressSpace = &(g_pDemoProvider->AddressSpace);
OpcUa_ReturnErrorIfArgumentNull(a_pHistoryReadProcessedCtx);
/* we will send exactly one callback */
UaBase_Atomic_Increment(&a_pHistoryReadProcessedCtx->nOutstandingCbs);
/* process nodes */
for (i = 0; i < a_pHistoryReadProcessedCtx->NoOfNodesToRead; i++)
{
pNodeToRead = &a_pHistoryReadProcessedCtx->pNodesToRead[i];
pNodeId = &pNodeToRead->NodeId;
if (!UaServer_IsNamespaceOwner(g_pDemoProvider, pNodeId->NamespaceIndex))
continue;
UaServer_GetNode(pAddressSpace, pNodeId, &pNode);
if (pNode)
{
if (OpcUa_BaseNode_GetClass(pNode) != OpcUa_NodeClass_Variable ||
(OpcUa_Variable_GetAccessLevel(pNode) & OpcUa_AccessLevels_HistoryRead) == 0)
{
a_pHistoryReadProcessedCtx->pResponse->Results[i].StatusCode = OpcUa_BadNotReadable;
continue;
}
#if UASERVER_SUPPORT_AUTHORIZATION
/* Check if the user has the necessary permission to read the event history */
if (!UaServer_UserMgt_IsHistoryReadable(OpcUa_BaseNode_GetINode(pNode), a_pHistoryReadProcessedCtx->pSession->UserIdentityData))
{
a_pHistoryReadProcessedCtx->pResponse->Results[i].StatusCode = OpcUa_BadUserAccessDenied;
continue;
}
#endif
/* TODO */
a_pHistoryReadProcessedCtx->pResponse->Results[i].StatusCode = OpcUa_BadNotImplemented;
}
}
/* send callback */
UaServer_HistoryReadProcessedComplete(a_pHistoryReadProcessedCtx);
return OpcUa_Good;
}
IFMETHODIMP(UaProvider_Demo_HistoryReadAtTimeAsync)(UaServer_ProviderHistoryReadAtTimeContext* a_pHistoryReadAtTimeCtx)
{
OpcUa_Int32 i;
OpcUa_BaseNode *pNode = OpcUa_Null;
OpcUa_NodeId *pNodeId;
UaServer_AddressSpace *pAddressSpace = &(g_pDemoProvider->AddressSpace);
OpcUa_ReturnErrorIfArgumentNull(a_pHistoryReadAtTimeCtx);
/* we will send exactly one callback */
UaBase_Atomic_Increment(&a_pHistoryReadAtTimeCtx->nOutstandingCbs);
/* process nodes */
for (i = 0; i < a_pHistoryReadAtTimeCtx->NoOfNodesToRead; i++)
{
pNodeToRead = &a_pHistoryReadAtTimeCtx->pNodesToRead[i];
pNodeId = &pNodeToRead->NodeId;
if (!UaServer_IsNamespaceOwner(g_pDemoProvider, pNodeId->NamespaceIndex))
continue;
UaServer_GetNode(pAddressSpace, pNodeId, &pNode);
if (pNode)
{
if (OpcUa_BaseNode_GetClass(pNode) != OpcUa_NodeClass_Variable ||
(OpcUa_Variable_GetAccessLevel(pNode) & OpcUa_AccessLevels_HistoryRead) == 0)
{
a_pHistoryReadAtTimeCtx->pResponse->Results[i].StatusCode = OpcUa_BadNotReadable;
continue;
}
#if UASERVER_SUPPORT_AUTHORIZATION
/* Check if the user has the necessary permission to read the history */
if (!UaServer_UserMgt_IsHistoryReadable(OpcUa_BaseNode_GetINode(pNode), a_pHistoryReadAtTimeCtx->pSession->UserIdentityData))
{
a_pHistoryReadAtTimeCtx->pResponse->Results[i].StatusCode = OpcUa_BadNotReadable;
continue;
}
#endif
/* TODO */
a_pHistoryReadAtTimeCtx->pResponse->Results[i].StatusCode = OpcUa_BadNotImplemented;
}
}
/* send callback */
UaServer_HistoryReadAtTimeComplete(a_pHistoryReadAtTimeCtx);
return OpcUa_Good;
}
OPCUA_END_EXTERN_C