ANSI C UA Server SDK  1.6.0.341
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Modules Pages
oversampling_provider_write.c
/*****************************************************************************
*
* Copyright (c) 2006-2016 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: OPC Ansi C OverSamplingProvider for namespace
* 'http://www.unifiedautomation.com/OverSampling'
*
****************************************************************************/
#include <uaserver_config.h>
#include <pthread.h>
#include <errno.h>
#include <opcua_statuscodes.h>
#include <opcua_attributes.h>
#include <uabase_p_atomic.h>
#include <uaserver_basenode.h>
#include <uaserver_utilities.h>
#include <uaserver_write.h>
#include "uaprovider_oversampling_helper.h"
#include "uaprovider_oversampling_identifiers_1.h"
OpcUa_List g_WriteJobs;
pthread_t g_WriteThread;
pthread_attr_t g_WriteAttr;
pthread_mutex_t g_WriteMutex;
pthread_cond_t g_WriteCondition;
OPCUA_BEGIN_EXTERN_C
void* UaProvider_OverSampling_WriteThread(void *arg)
{
OpcUa_ReferenceParameter(arg);
while (1)
{
int i;
OpcUa_BaseNode *pNode;
OpcUa_NodeId *pNodeId;
OpcUa_WriteValue *pNodeToWrite;
UaServer_AddressSpace *pAddressSpace = &(g_pOverSamplingProvider->AddressSpace);
UaServer_ProviderWriteContext *pWriteCtx = OpcUa_Null;
pthread_mutex_lock(&g_WriteMutex);
pWriteCtx = (UaServer_ProviderWriteContext*)OpcUa_List_RemoveFirstElement(&g_WriteJobs);
while (!pWriteCtx && g_bShutdown == OpcUa_False)
{
pthread_cond_wait(&g_WriteCondition, &g_WriteMutex);
pWriteCtx = (UaServer_ProviderWriteContext*)OpcUa_List_RemoveFirstElement(&g_WriteJobs);
}
pthread_mutex_unlock(&g_WriteMutex);
if (g_bShutdown)
{
while (pWriteCtx)
{
pWriteCtx = (UaServer_ProviderWriteContext*)OpcUa_List_RemoveFirstElement(&g_WriteJobs);
}
break;
}
pReq = pWriteCtx->pRequest;
pRes = pWriteCtx->pResponse;
for (i = 0; i < pReq->NoOfNodesToWrite; i++)
{
pNodeToWrite = &pReq->NodesToWrite[i];
pNodeId = &pNodeToWrite->NodeId;
if (pNodeId->NamespaceIndex != g_UaProviderOverSampling_uNamespaceIndex1) continue;
UaServer_GetNode(pAddressSpace, pNodeId, &pNode);
if (pNode)
{
if (pNodeToWrite->AttributeId == OpcUa_Attributes_Value)
{
#if UASERVER_SUPPORT_AUTHORIZATION
if ((pNodeToWrite->AttributeId == OpcUa_Attributes_Value
|| (pNodeToWrite->AttributeId != OpcUa_Attributes_Value
{
pRes->Results[i] = OpcUa_BadNotWritable;
continue;
}
#endif
switch (pNodeToWrite->NodeId.Identifier.Numeric)
{
case OverSampling_Objects_S1KHz_Voltage:
case OverSampling_Objects_S1KHz_Current:
if (pNodeToWrite->Value.StatusCode == OpcUa_Good &&
pNodeToWrite->Value.Value.ArrayType == OpcUa_VariantArrayType_Scalar &&
pNodeToWrite->Value.Value.Datatype == OpcUaType_Double)
{
if (OpcUa_String_IsNull(&pNodeToWrite->IndexRange))
{
switch (pNodeToWrite->NodeId.Identifier.Numeric)
{
case OverSampling_Objects_S1KHz_Voltage:
g_Voltage = pNodeToWrite->Value.Value.Value.Double;
pRes->Results[i] = OpcUa_Good;
break;
case OverSampling_Objects_S1KHz_Current:
g_Current = pNodeToWrite->Value.Value.Value.Double;
pRes->Results[i] = OpcUa_Good;
break;
default:
break;
}
}
else
{
pRes->Results[i] = OpcUa_BadIndexRangeInvalid;
}
}
else
{
pRes->Results[i] = OpcUa_BadTypeMismatch;
}
break;
default:
UaServer_WriteInternal(pNode, pWriteCtx, i);
break;
}
}
else
{
UaServer_WriteInternal(pNode, pWriteCtx, i);
}
}
else
{
pRes->Results[i] = OpcUa_BadNodeIdUnknown;
}
}
/* send callback */
}
return 0;
}
IFMETHODIMP(UaProvider_OverSampling_WriteAsync)(UaServer_ProviderWriteContext* a_pWriteCtx)
{
/* we will send exactly one callback */
UaBase_Atomic_Increment(&a_pWriteCtx->nOutstandingCbs);
pthread_mutex_lock(&g_WriteMutex);
OpcUa_List_AddElementToEnd(&g_WriteJobs, a_pWriteCtx);
pthread_cond_signal(&g_WriteCondition);
pthread_mutex_unlock(&g_WriteMutex);
return OpcUa_Good;
}
OPCUA_END_EXTERN_C