#include <uaserver_config.h>
#include <opcua_statuscodes.h>
#include <uabase_p_atomic.h>
#include <uaserver_monitoring.h>
#include <uaserver_monitoreditemmanager.h>
#include <uaserver_basenode.h>
#include <uaserver_utilities.h>
#include "custom_provider_helper.h"
OPCUA_BEGIN_EXTERN_C
#if OPCUA_USE_SYNCHRONISATION
static OpcUa_Mutex g_mtxList;
# define LOCK_LIST() OpcUa_Mutex_Lock(g_mtxList)
# define UNLOCK_LIST() OpcUa_Mutex_Unlock(g_mtxList)
#else
# define LOCK_LIST()
# define UNLOCK_LIST()
#endif
#define NUM_SAMPLINGRATES 7
static OpcUa_Int g_aiSamplingRates[NUM_SAMPLINGRATES] = {50, 100, 250, 500, 1000, 2500, 5000};
static OpcUa_Timer g_hSamplingTimers[NUM_SAMPLINGRATES];
static UaBase_Vector g_vecSamplingLists[NUM_SAMPLINGRATES];
IFMETHODIMP(CustomProvider_TimerCallback)(OpcUa_Void *a_pvCallbackData,
OpcUa_Timer a_hTimer,
OpcUa_UInt32 a_msecElapsed);
{
OpcUa_UInt32 i;
OpcUa_InitializeStatus(OpcUa_Module_Server, "CustomProvider_Subscription_Initialize");
#if OPCUA_USE_SYNCHRONISATION
uStatus = OpcUa_Mutex_Create(&g_mtxList);
OpcUa_GotoErrorIfBad(uStatus);
#endif
for (i = 0; i < NUM_SAMPLINGRATES; i++)
{
uStatus = OpcUa_Timer_Create(&g_hSamplingTimers[i],
g_aiSamplingRates[i],
CustomProvider_TimerCallback,
OpcUa_Null,
&g_vecSamplingLists[i]);
OpcUa_GotoErrorIfBad(uStatus);
}
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
{
OpcUa_UInt32 i;
OpcUa_InitializeStatus(OpcUa_Module_Server, "CustomProvider_Subscription_Cleanup");
#if OPCUA_USE_SYNCHRONISATION
OpcUa_Mutex_Delete(&g_mtxList);
#endif
for (i = 0; i < NUM_SAMPLINGRATES; i++)
{
OpcUa_Timer_Delete(&g_hSamplingTimers[i]);
}
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
IFMETHODIMP(CustomProvider_AddItem)(UaServer_MonitoredItem *a_pItem)
{
OpcUa_UInt32 i = 0;
OpcUa_UInt32 iDist = 0;
OpcUa_UInt32 iTmp = 0;
OpcUa_UInt32 iRevised = 0;
OpcUa_BaseNode *pNode = OpcUa_Null;
OpcUa_InitializeStatus(OpcUa_Module_Server, "CustomProvider_AddItem");
OpcUa_ReturnErrorIfArgumentNull(a_pItem);
iDist =
UaBase_P_Abs(a_pItem->iSamplingInterval - g_aiSamplingRates[0]);
for (i = 1; i < NUM_SAMPLINGRATES; i++)
{
iTmp =
UaBase_P_Abs(a_pItem->iSamplingInterval - g_aiSamplingRates[i]);
if (iTmp < iDist)
{
iDist = iTmp;
iRevised = i;
}
}
a_pItem->iSamplingInterval = g_aiSamplingRates[iRevised];
if (pNode)
{
if (a_pItem->ItemType == DATA)
{
UaServer_MonitoredItemData* pMonitoredItemData = (UaServer_MonitoredItemData*)a_pItem;
if (OpcUa_BaseNode_GetClass(pNode) == OpcUa_NodeClass_Variable &&
pMonitoredItemData->AttributeId == OpcUa_Attributes_Value)
{
OpcUa_DataVariable* pVariable = (OpcUa_DataVariable*)pNode;
{
uStatus = OpcUa_BadNotReadable;
}
if (OpcUa_IsGood(uStatus) && pMonitoredItemData->NoOfIndexRanges > 0)
{
pMonitoredItemData->IndexRanges,
pMonitoredItemData->NoOfIndexRanges);
}
if (OpcUa_IsGood(uStatus) &&
{
{
uStatus = OpcUa_BadMonitoredItemFilterUnsupported;
}
else
{
{
case OpcUaType_SByte:
case OpcUaType_Byte:
case OpcUaType_Int16:
case OpcUaType_UInt16:
case OpcUaType_Int32:
case OpcUaType_UInt32:
case OpcUaType_Int64:
case OpcUaType_UInt64:
case OpcUaType_Float:
case OpcUaType_Double:
break;
default:
uStatus = OpcUa_BadFilterNotAllowed;
break;
}
}
}
if (OpcUa_IsGood(uStatus))
{
LOCK_LIST();
a_pItem->uProviderHandle =
UaBase_Vector_Add(&g_vecSamplingLists[iRevised], pMonitoredItemData);
UNLOCK_LIST();
}
}
else
{
OpcUa_Variant_Initialize(¤tValue);
{
uStatus = OpcUa_BadNotReadable;
}
if (OpcUa_IsGood(uStatus) &&
{
uStatus = OpcUa_BadFilterNotAllowed;
}
if (OpcUa_IsGood(uStatus) && pMonitoredItemData->NoOfIndexRanges > 0)
{
uStatus = OpcUa_BadIndexRangeNoData;
}
if (OpcUa_IsGood(uStatus))
{
pNode,
¤tValue,
}
if (OpcUa_IsGood(uStatus))
{
LOCK_LIST();
a_pItem->uProviderHandle =
UaBase_Vector_Add(&g_vecSamplingLists[iRevised], pMonitoredItemData);
UNLOCK_LIST();
}
OpcUa_Variant_Clear(¤tValue);
}
}
}
else
{
uStatus = OpcUa_BadNodeIdUnknown;
}
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
IFMETHODIMP(CustomProvider_RemoveItem)(UaServer_MonitoredItem *a_pItem)
{
UaBase_Vector *pVec = 0;
OpcUa_UInt32 size;
OpcUa_UInt32 i;
OpcUa_InitializeStatus(OpcUa_Module_Server, "CustomProvider_RemoveItem");
OpcUa_ReturnErrorIfArgumentNull(a_pItem);
for (i = 0; i < NUM_SAMPLINGRATES; i++)
{
if (g_aiSamplingRates[i] == a_pItem->iSamplingInterval)
{
pVec = &g_vecSamplingLists[i];
break;
}
}
if (pVec == OpcUa_Null)
{
return OpcUa_BadNotFound;
}
if (a_pItem->ItemType == DATA)
{
LOCK_LIST();
if (a_pItem->uProviderHandle < size)
{
if (a_pItem->uProviderHandle < size - 1)
{
pTmpItem->uProviderHandle = a_pItem->uProviderHandle;
}
}
else
{
uStatus = OpcUa_BadInternalError;
}
UNLOCK_LIST();
}
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
IFMETHODIMP(CustomProvider_Subscribe)(UaServer_ProviderSubscribeContext *a_pCtx)
{
OpcUa_InitializeStatus(OpcUa_Module_Server, "CustomProvider_Subscribe");
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
OpcUa_Void CustomProvider_SampleData(OpcUa_Void* a_pvCallbackData)
{
unsigned int i = 0;
UaBase_Vector *pVecList = OpcUa_Null;
UaServer_MonitoredItemData *pMonitoredItemData = OpcUa_Null;
OpcUa_Variable *pVariable = OpcUa_Null;
unsigned int size;
pVecList = (UaBase_Vector*)a_pvCallbackData;
LOCK_LIST();
for (i = 0; i < size; i++)
{
{
continue;
}
&pMonitoredItemData->NodeId,
(OpcUa_BaseNode**)&pVariable);
if (pVariable)
{
OpcUa_DataValue_Initialize(pValue);
if (pMonitoredItemData->AttributeId == OpcUa_Attributes_Value)
{
}
else
{
(OpcUa_BaseNode*)pVariable,
}
if (pMonitoredItemData->AttributeId == OpcUa_Attributes_Value)
{
}
}
}
UNLOCK_LIST();
}
IFMETHODIMP(CustomProvider_TimerCallback)(OpcUa_Void *a_pvCallbackData,
OpcUa_Timer a_hTimer,
OpcUa_UInt32 a_msecElapsed)
{
OpcUa_InitializeStatus(OpcUa_Module_Server, "CustomProvider_TimerCallback");
OpcUa_ReferenceParameter(a_hTimer);
OpcUa_ReferenceParameter(a_msecElapsed);
CustomProvider_SampleData(a_pvCallbackData);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
OPCUA_END_EXTERN_C