#include <uaserver_config.h>
#include <opcua_statuscodes.h>
#include <opcua_attributes.h>
#include <uabase_p_atomic.h>
#include <uaserver_basenode.h>
#include <uaserver_utilities.h>
#include <uaserver_monitoring.h>
#include <uaserver_monitoreditemmanager.h>
#include "uaprovider_oversampling_helper.h"
#include "uaprovider_oversampling_identifiers_1.h"
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <time.h>
#define SIGTIMER SIGALRM
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_UInt32 g_aiSamplingRates[NUM_SAMPLINGRATES] = {1, 50, 100, 250, 500, 1000, 2500};
static timer_t g_hSamplingTimers[NUM_SAMPLINGRATES];
static pthread_t g_timerthreadid;
static pthread_attr_t g_timerthreadattr;
static volatile int g_bExitTimerThread = 0;
double g_Voltage = 0.0;
double g_Current = 0.0;
#define TIMER_OVERRUN_TRACE 0
static void UaProvider_OverSampling_SampleData(
UaBase_Vector *pvecList)
{
unsigned int i = 0;
OpcUa_Variable *pVariable = OpcUa_Null;
unsigned int size;
if (pvecList == &g_vecSamplingLists[0])
{
g_Voltage += 0.1;
g_Current += 0.17;
}
LOCK_LIST();
for (i = 0; i < size; i++)
{
{
continue;
}
UaServer_GetNode(&g_pOverSamplingProvider->AddressSpace, &pMonitoredItemData->
NodeId, (OpcUa_BaseNode**)&pVariable);
if (pVariable)
{
#if UASERVER_SUPPORT_AUTHORIZATION
#endif
if (pValue == 0) break;
OpcUa_DataValue_Initialize(pValue);
if (pMonitoredItemData->
AttributeId == OpcUa_Attributes_Value)
{
#if UASERVER_SUPPORT_AUTHORIZATION
{
continue;
}
#endif
switch (pMonitoredItemData->
NodeId.Identifier.Numeric)
{
case OverSampling_Objects_S1KHz_Voltage:
break;
case OverSampling_Objects_S1KHz_Current:
break;
default:
break;
}
}
else
{
#if UASERVER_SUPPORT_AUTHORIZATION
{
continue;
}
#endif
(OpcUa_BaseNode*)pVariable,
}
}
else
{
if (pValue == 0) break;
OpcUa_DataValue_Initialize(pValue);
}
}
UNLOCK_LIST();
}
void* timer_thread (void *arg)
{
sigset_t waitset;
int sig;
siginfo_t info;
int iIndex;
OpcUa_ReferenceParameter(arg);
sigemptyset( &waitset );
sigaddset( &waitset, SIGTIMER );
sigprocmask( SIG_BLOCK, &waitset, NULL );
while (g_bExitTimerThread == 0)
{
sig = sigwaitinfo( &waitset, &info );
switch(sig)
{
case SIGTIMER:
iIndex = info.si_value.sival_int;
if (iIndex < 0 || iIndex >= NUM_SAMPLINGRATES) break;
pvecList = &g_vecSamplingLists[iIndex];
if (info.si_code == SI_TIMER)
{
#if TIMER_OVERRUN_TRACE
timer_t timerid;
timerid = g_hSamplingTimers[iIndex];
if (timer_getoverrun(timerid) > 0)
{
fprintf(stderr, "timer overrun\n");
}
#endif
UaProvider_OverSampling_SampleData(pvecList);
}
break;
default:
perror("sigwaitinfo");
break;
}
}
return 0;
}
{
OpcUa_UInt32 i;
struct sigevent se;
struct itimerspec interval;
int ret;
sigset_t waitset;
OpcUa_InitializeStatus(OpcUa_Module_Server, "UaProvider_OverSampling_Subscription_Initialize");
#if OPCUA_USE_SYNCHRONISATION
uStatus = OpcUa_Mutex_Create(&g_mtxList);
OpcUa_GotoErrorIfBad(uStatus);
#endif
LOCK_LIST();
sigemptyset( &waitset );
sigaddset( &waitset, SIGTIMER );
sigprocmask( SIG_BLOCK, &waitset, NULL );
pthread_attr_init(&g_timerthreadattr);
pthread_attr_setstacksize(&g_timerthreadattr, 1024*1024);
pthread_create(&g_timerthreadid, &g_timerthreadattr, timer_thread, 0);
for (i = 0; i < NUM_SAMPLINGRATES; i++)
{
OpcUa_MemSet(&se, 0, sizeof(struct sigevent));
se.sigev_notify = SIGEV_SIGNAL;
se.sigev_signo = SIGTIMER;
se.sigev_value.sival_int = i;
ret = timer_create(CLOCK_MONOTONIC, &se, &g_hSamplingTimers[i]);
if (ret != 0)
{
perror("timer_create");
}
interval.it_interval.tv_sec = g_aiSamplingRates[i] / 1000;
interval.it_interval.tv_nsec = (g_aiSamplingRates[i] % 1000) * 1000000;
interval.it_value.tv_sec = interval.it_interval.tv_sec;
interval.it_value.tv_nsec = interval.it_interval.tv_nsec;
ret = timer_settime(g_hSamplingTimers[i], 0, &interval, 0);
if (ret != 0)
{
perror("timer_settime");
}
}
UNLOCK_LIST();
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
{
OpcUa_UInt32 i;
void *retval = 0;
OpcUa_InitializeStatus(OpcUa_Module_Server, "UaProvider_OverSampling_Subscription_Cleanup");
g_bExitTimerThread = 1;
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "wait for timer thread to terminate\n");
pthread_join(g_timerthreadid, &retval);
LOCK_LIST();
for (i = 0; i < NUM_SAMPLINGRATES; i++)
{
timer_delete(g_hSamplingTimers[i]);
}
UNLOCK_LIST();
#if OPCUA_USE_SYNCHRONISATION
OpcUa_Mutex_Delete(&g_mtxList);
#endif
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
{
OpcUa_BaseNode *pNode = OpcUa_Null, *pProperty = OpcUa_Null;
OpcUa_QualifiedName_Initialize(&qnEURange);
OpcUa_String_AttachReadOnly(&qnEURange.
Name, OpcUa_BrowseName_EURange);
if (pNode)
{
unsigned int iReference;
{
&& pReference->
refType.Identifier.Numeric == OpcUaId_HasProperty
&& OpcUa_BaseNode_GetClass(pReference->
target.
pNode) == OpcUa_NodeClass_Variable)
{
{
break;
}
}
}
if (pProperty)
{
if (pValue->
Datatype == OpcUaType_ExtensionObject
&& pValue->
ArrayType == OpcUa_VariantArrayType_Scalar
&& pValue->
Value.ExtensionObject != OpcUa_Null
&& pValue->
Value.ExtensionObject->Body.EncodeableObject.Type == &OpcUa_Range_EncodeableType)
{
pRange = (
OpcUa_Range*)pValue->
Value.ExtensionObject->Body.EncodeableObject.Object;
}
}
}
return pRange;
}
{
OpcUa_Int i = 0;
OpcUa_Int iDist = 0;
OpcUa_Int iTmp = 0;
OpcUa_Int iRevised = 0;
OpcUa_BaseNode *pNode = OpcUa_Null;
OpcUa_InitializeStatus(OpcUa_Module_Server, "UaProvider_OverSampling_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)
{
if (OpcUa_BaseNode_GetClass(pNode) == OpcUa_NodeClass_Variable
&& pMonitoredItemData->
AttributeId == OpcUa_Attributes_Value)
{
OpcUa_DataVariable* pVariable = (OpcUa_DataVariable*)pNode;
{
}
{
{
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;
}
{
{
uStatus = OpcUa_BadDeadbandFilterInvalid;
}
}
}
{
OpcUa_Range *pRange = UaProvider_OverSampling_GetEURange(&pMonitoredItemData->
NodeId);
if (pRange)
{
}
else
{
uStatus = OpcUa_BadMonitoredItemFilterUnsupported;
}
}
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_BadFilterNotAllowed;
}
{
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;
}
{
unsigned int size;
unsigned int i;
OpcUa_InitializeStatus(OpcUa_Module_Server, "UaProvider_OverSampling_RemoveItem");
OpcUa_ReturnErrorIfArgumentNull(a_pItem);
for (i = 0; i < NUM_SAMPLINGRATES; i++)
{
if (g_aiSamplingRates[i] == (OpcUa_UInt32)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)
{
}
}
else
{
uStatus = OpcUa_BadInternalError;
}
UNLOCK_LIST();
}
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
{
OpcUa_InitializeStatus(OpcUa_Module_Server, "UaProvider_OverSampling_Subscribe");
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
OPCUA_END_EXTERN_C