ANSI C Based OPC UA Client/Server SDK  1.9.0.430
uaprovider_demo_simulation.c
/*****************************************************************************
* *
* Copyright (c) 2006-2019 Unified Automation GmbH. All rights reserved. *
* *
* Software License Agreement ("SLA") Version 2.7 *
* *
* 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.7, 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.7/ *
* *
* Project: Unified Automation ANSI C based OPC UA Server SDK *
* *
*****************************************************************************/
#include "uaprovider_demo_simulation.h"
#include <opcua_statuscodes.h>
#include <opcua_attributes.h>
#include <uabase_p_atomic.h>
#include <uabase_p_filesystem.h>
#include <uaserver_basenode.h>
#include <uaserver_utilities.h>
#if UASERVER_SUPPORT_UNITS
# include <uaserver_units.h>
#endif /* UASERVER_SUPPORT_UNITS */
#define _USE_MATH_DEFINES
#include <math.h>
#ifndef M_PI
# define M_PI 3.14159265
#endif
#include "uaprovider_demo.h"
#include "uaprovider_demo_helper.h"
#include "uaprovider_demo_identifiers_1.h"
#include "uaprovider_demo_types_1.h"
#include "uaprovider_demo_userdata.h"
#if UASERVER_SUPPORT_EVENTS
# include "uaprovider_demo_events_1.h"
# include "uaprovider_demo_alarmcondition.h"
#endif /* UASERVER_SUPPORT_EVENTS */
#if HAVE_DATA_LOGGER || UASERVER_SUPPORT_FILEIMPORTER
# include <uabase_settings.h>
#endif /* HAVE_DATA_LOGGER || UASERVER_SUPPORT_FILEIMPORTER */
#if HAVE_DATA_LOGGER
# include <uaserver_monitoring.h>
# include <uaserver_datalogger.h>
# if HAVE_DATA_LOGGER_FILE_BACKEND
# include <uaserver_filelogger.h>
# endif /* HAVE_DATA_LOGGER_FILE_BACKEND */
# if HAVE_DATA_LOGGER_SQLITE_BACKEND
# include <uaserver_sqlitelogger.h>
# endif /* HAVE_DATA_LOGGER_SQLITE_BACKEND */
static OpcUa_Boolean *g_pDataLoggerActive = 0;
#endif /* HAVE_DATA_LOGGER */
#if UASERVER_SUPPORT_FILEIMPORTER
# include <uaserver_fileimporter.h>
#endif /* UASERVER_SUPPORT_FILEIMPORTER */
/* timer handle */
static OpcUa_Timer g_hSimulationTimer = 0;
static OpcUa_UInt32 g_SimulationInterval = 50;
static OpcUa_UInt32 *g_pSimulationSpeed = 0;
static OpcUa_Boolean *g_pSimulationActive = 0;
static OpcUa_Timer g_hAnimationTimer = 0;
static OpcUa_UInt32 g_AnimationInterval = 50;
/* dynamic variables */
static OpcUa_Boolean *g_pDynBoolean = 0;
static OpcUa_SByte *g_pDynSByte = 0;
static OpcUa_Byte *g_pDynByte = 0;
static OpcUa_Int16 *g_pDynInt16 = 0;
static OpcUa_UInt16 *g_pDynUInt16 = 0;
static OpcUa_Int32 *g_pDynInt32 = 0;
static OpcUa_UInt32 *g_pDynUInt32 = 0;
static OpcUa_Int64 *g_pDynInt64 = 0;
static OpcUa_UInt64 *g_pDynUInt64 = 0;
static OpcUa_Float *g_pDynFloat = 0;
static OpcUa_Double *g_pDynDouble = 0;
static OpcUa_DateTime *g_pDynDateTime = 0;
static OpcUa_String *g_pDynString = 0;
static OpcUa_Guid **g_ppDynGuid = 0;
static OpcUa_ByteString *g_pDynByteString = 0;
static OpcUa_LocalizedText **g_ppDynLocalizedText = 0;
static OpcUa_QualifiedName **g_ppDynQualifiedName = 0;
static OpcUa_NodeId **g_ppDynNodeId = 0;
static OpcUa_ExpandedNodeId **g_ppDynExpandedNodeId = 0;
static OpcUa_StatusCode *g_pDynStatusCode = 0;
static OpcUa_XmlElement *g_pDynXmlElement = 0;
static OpcUa_Double *g_pDynamicValue = 0;
static OpcUa_StatusCode *g_pDynamicValue_Quality = 0;
static OpcUa_StatusCode *g_pStaticValue_Quality = 0;
static OpcUa_VariantArrayValue *g_pDynArrayBoolean = 0;
static OpcUa_VariantArrayValue *g_pDynArraySByte = 0;
static OpcUa_VariantArrayValue *g_pDynArrayByte = 0;
static OpcUa_VariantArrayValue *g_pDynArrayInt16 = 0;
static OpcUa_VariantArrayValue *g_pDynArrayUInt16 = 0;
static OpcUa_VariantArrayValue *g_pDynArrayInt32 = 0;
static OpcUa_VariantArrayValue *g_pDynArrayUInt32 = 0;
static OpcUa_VariantArrayValue *g_pDynArrayInt64 = 0;
static OpcUa_VariantArrayValue *g_pDynArrayUInt64 = 0;
static OpcUa_VariantArrayValue *g_pDynArrayFloat = 0;
static OpcUa_VariantArrayValue *g_pDynArrayDouble = 0;
static OpcUa_VariantArrayValue *g_pDynArrayDateTime = 0;
static OpcUa_VariantArrayValue *g_pDynArrayString = 0;
static OpcUa_VariantArrayValue *g_pDynArrayGuid = 0;
static OpcUa_VariantArrayValue *g_pDynArrayByteString = 0;
static OpcUa_VariantArrayValue *g_pDynArrayLocalizedText = 0;
static OpcUa_VariantArrayValue *g_pDynArrayQualifiedName = 0;
static OpcUa_VariantArrayValue *g_pDynArrayNodeId = 0;
static OpcUa_VariantArrayValue *g_pDynArrayExpandedNodeId = 0;
static OpcUa_VariantArrayValue *g_pDynArrayStatusCode = 0;
static OpcUa_VariantArrayValue *g_pDynArrayXmlElement = 0;
#if UAPROVIDER_DEMO_HAVE_MASS_ITEMS
/* massfolder dynamic variables */
static OpcUa_UInt32 *g_pMassDynUInt32[UAPROVIDER_DEMO_NUM_MASS_DYNAMIC_VARIABLES];
#endif /* UAPROVIDER_DEMO_HAVE_MASS_ITEMS */
/* history variables */
static OpcUa_Double *g_pHistoryDouble = 0;
static OpcUa_Byte *g_pHistoryByte = 0;
#if UAPROVIDER_DEMO_HAVE_ANIMATION_ITEM
static OpcUa_ByteString *g_pAnimation = 0;
#endif /* UAPROVIDER_DEMO_HAVE_ANIMATION_ITEM */
static BoilerType g_Boiler1;
#if HAVE_DATA_LOGGER
static OpcUa_Int g_hDataLogger = 0;
#endif /* HAVE_DATA_LOGGER */
#if UASERVER_SUPPORT_EVENTS
static Machine g_machine;
#endif
struct _ItemVariableMapping
{
void **ppVariable;
const char* szNodeId;
};
typedef struct _ItemVariableMapping ItemVariableMapping;
static ItemVariableMapping g_Items[] =
{
#if HAVE_DATA_LOGGER
{ (void**) &g_pDataLoggerActive, Demo_Objects_Demo_History_DataLoggerActive },
#endif /* HAVE_DATA_LOGGER */
{ (void**) &g_pSimulationSpeed, Demo_Objects_Demo_SimulationSpeed },
{ (void**) &g_pSimulationActive, Demo_Objects_Demo_SimulationActive },
{ (void**) &g_pDynBoolean, Demo_Objects_Demo_Dynamic_Scalar_Boolean },
{ (void**) &g_pDynByte, Demo_Objects_Demo_Dynamic_Scalar_Byte },
{ (void**) &g_pDynSByte, Demo_Objects_Demo_Dynamic_Scalar_SByte },
{ (void**) &g_pDynUInt16, Demo_Objects_Demo_Dynamic_Scalar_UInt16 },
{ (void**) &g_pDynInt16, Demo_Objects_Demo_Dynamic_Scalar_Int16 },
{ (void**) &g_pDynUInt32, Demo_Objects_Demo_Dynamic_Scalar_UInt32 },
{ (void**) &g_pDynInt32, Demo_Objects_Demo_Dynamic_Scalar_Int32 },
{ (void**) &g_pDynUInt64, Demo_Objects_Demo_Dynamic_Scalar_UInt64 },
{ (void**) &g_pDynInt64, Demo_Objects_Demo_Dynamic_Scalar_Int64 },
{ (void**) &g_pDynFloat, Demo_Objects_Demo_Dynamic_Scalar_Float },
{ (void**) &g_pDynDouble, Demo_Objects_Demo_Dynamic_Scalar_Double },
{ (void**) &g_pDynDateTime, Demo_Objects_Demo_Dynamic_Scalar_DateTime },
{ (void**) &g_pDynString, Demo_Objects_Demo_Dynamic_Scalar_String },
{ (void**) &g_pDynByteString, Demo_Objects_Demo_Dynamic_Scalar_ByteString },
{ (void**) &g_ppDynGuid, Demo_Objects_Demo_Dynamic_Scalar_Guid },
{ (void**) &g_ppDynLocalizedText, Demo_Objects_Demo_Dynamic_Scalar_LocalizedText },
{ (void**) &g_ppDynQualifiedName, Demo_Objects_Demo_Dynamic_Scalar_QualifiedName },
{ (void**) &g_ppDynNodeId, Demo_Objects_Demo_Dynamic_Scalar_NodeId },
{ (void**) &g_ppDynExpandedNodeId, Demo_Objects_Demo_Dynamic_Scalar_ExpandedNodeId },
{ (void**) &g_pDynStatusCode, Demo_Objects_Demo_Dynamic_Scalar_StatusCode },
{ (void**) &g_pDynXmlElement, Demo_Objects_Demo_Dynamic_Scalar_XmlElement },
{ (void**) &g_pDynamicValue, Demo_Objects_Demo_Dynamic_Scalar_Quality_DynamicValue },
{ (void**) &g_pDynArrayBoolean, Demo_Objects_Demo_Dynamic_Arrays_Boolean },
{ (void**) &g_pDynArrayByte, Demo_Objects_Demo_Dynamic_Arrays_Byte },
{ (void**) &g_pDynArraySByte, Demo_Objects_Demo_Dynamic_Arrays_SByte },
{ (void**) &g_pDynArrayUInt16, Demo_Objects_Demo_Dynamic_Arrays_UInt16 },
{ (void**) &g_pDynArrayInt16, Demo_Objects_Demo_Dynamic_Arrays_Int16 },
{ (void**) &g_pDynArrayUInt32, Demo_Objects_Demo_Dynamic_Arrays_UInt32 },
{ (void**) &g_pDynArrayInt32, Demo_Objects_Demo_Dynamic_Arrays_Int32 },
{ (void**) &g_pDynArrayUInt64, Demo_Objects_Demo_Dynamic_Arrays_UInt64 },
{ (void**) &g_pDynArrayInt64, Demo_Objects_Demo_Dynamic_Arrays_Int64 },
{ (void**) &g_pDynArrayFloat, Demo_Objects_Demo_Dynamic_Arrays_Float },
{ (void**) &g_pDynArrayDouble, Demo_Objects_Demo_Dynamic_Arrays_Double },
{ (void**) &g_pDynArrayGuid, Demo_Objects_Demo_Dynamic_Arrays_Guid },
{ (void**) &g_pDynArrayDateTime, Demo_Objects_Demo_Dynamic_Arrays_DateTime },
{ (void**) &g_pDynArrayString, Demo_Objects_Demo_Dynamic_Arrays_String },
{ (void**) &g_pDynArrayByteString, Demo_Objects_Demo_Dynamic_Arrays_ByteString },
{ (void**) &g_pDynArrayLocalizedText, Demo_Objects_Demo_Dynamic_Arrays_LocalizedText },
{ (void**) &g_pDynArrayQualifiedName, Demo_Objects_Demo_Dynamic_Arrays_QualifiedName },
{ (void**) &g_pDynArrayNodeId, Demo_Objects_Demo_Dynamic_Arrays_NodeId },
{ (void**) &g_pDynArrayExpandedNodeId, Demo_Objects_Demo_Dynamic_Arrays_ExpandedNodeId },
{ (void**) &g_pDynArrayStatusCode, Demo_Objects_Demo_Dynamic_Arrays_StatusCode },
{ (void**) &g_pDynArrayXmlElement, Demo_Objects_Demo_Dynamic_Arrays_XmlElement },
{ (void**) &g_pHistoryByte, Demo_Objects_Demo_History_ByteWithHistory },
{ (void**) &g_pHistoryDouble, Demo_Objects_Demo_History_DoubleWithHistory },
{ 0, 0 }
};
OPCUA_BEGIN_EXTERN_C
OpcUa_Variant* UaProvider_Demo_GetNodeValueNumeric(int id)
{
OpcUa_NodeId nodeId;
OpcUa_BaseNode *pNode = 0;
OpcUa_Variant *pVal = 0;
pNode = UaServer_GetNodeById(&nodeId);
if (pNode && OpcUa_BaseNode_GetType(pNode) == eVariable)
{
pVal = OpcUa_Variable_GetValue(pNode);
}
return pVal;
}
OpcUa_Variant* UaProvider_Demo_GetNodeValueString(const char *szId)
{
OpcUa_NodeId nodeId;
OpcUa_BaseNode *pNode = 0;
OpcUa_Variant *pVal = 0;
UaBase_CreateStringNodeIdEx(&nodeId, szId, g_UaProviderDemo_uNamespaceIndex1);
pNode = UaServer_GetNodeById(&nodeId);
if (pNode && OpcUa_BaseNode_GetType(pNode) == eVariable)
{
pVal = OpcUa_Variable_GetValue(pNode);
}
return pVal;
}
#if UAPROVIDER_DEMO_HAVE_MASS_ITEMS
OpcUa_StatusCode UaProvider_Demo_CreateNodes()
{
UaServer_AddressSpace *pAddressSpace = &(g_pDemoProvider->AddressSpace);
OpcUa_NodeId nodeId;
OpcUa_BaseNode *pNode = 0;
OpcUa_DataVariable *pVariable = 0;
char szName[50];
int i;
OpcUa_InitializeStatus(OpcUa_Module_Server, "UaProvider_Demo_CreateNodes");
OpcUa_Variant_Initialize(&value);
#if UAPROVIDER_DEMO_HAVE_ANIMATION_ITEM
/* store variable pointer for simulation */
pVal = UaProvider_Demo_GetNodeValueString(Demo_Objects_Demo_Dynamic_Scalar_ImageGIF);
if (pVal) g_pAnimation = &pVal->Value.ByteString;
#endif /* UAPROVIDER_DEMO_HAVE_ANIMATION_ITEM */
/* create mass folders nodes */
UaBase_CreateStringNodeId( &nodeId, Demo_Objects_Demo_Massfolder_Static );
pNode = UaServer_GetNodeById( &nodeId );
for (i=0; i<UAPROVIDER_DEMO_NUM_MASS_STATIC_VARIABLES; i++)
{
OpcUa_SnPrintfA(szName, 50, "Variable%03i", i);
uStatus = UaServer_CreateDataVariable(pAddressSpace, &pVariable, pNode, 20000 + i, g_UaProviderDemo_uNamespaceIndex1, szName);
OpcUa_GotoErrorIfBad(uStatus);
/* set datatype attribute */
OpcUa_Variable_SetDataType_Numeric(pVariable, OpcUaId_UInt32, 0);
/* set value attribute */
OpcUa_Variable_GetValue(pVariable)->Datatype = OpcUaType_UInt32;
OpcUa_Variable_GetValue(pVariable)->Value.UInt32 = 123;
/* set access level attribute */
OpcUa_Variable_SetAccessLevel(pVariable, OpcUa_AccessLevels_CurrentReadOrWrite);
}
/* create mass folders nodes */
UaBase_CreateStringNodeId( &nodeId, Demo_Objects_Demo_Massfolder_Dynamic );
pNode = UaServer_GetNodeById( &nodeId );
for (i=0; i<UAPROVIDER_DEMO_NUM_MASS_DYNAMIC_VARIABLES; i++)
{
OpcUa_SnPrintfA(szName, 50, "Variable%03i", i);
uStatus = UaServer_CreateDataVariable(pAddressSpace, &pVariable, pNode, 20000+UAPROVIDER_DEMO_NUM_MASS_STATIC_VARIABLES+i, g_UaProviderDemo_uNamespaceIndex1, szName);
OpcUa_GotoErrorIfBad(uStatus);
/* set datatype attribute */
OpcUa_Variable_SetDataType_Numeric(pVariable, OpcUaId_UInt32, 0);
/* set value attribute */
OpcUa_Variable_GetValue(pVariable)->Datatype = OpcUaType_UInt32;
OpcUa_Variable_GetValue(pVariable)->Value.UInt32 = 123;
/* set access level attribute */
OpcUa_Variable_SetAccessLevel(pVariable, OpcUa_AccessLevels_CurrentRead);
/* store variable pointer for simulation */
pVal = OpcUa_Variable_GetValue(pVariable);
if (pVal)
{
g_pMassDynUInt32[i] = &pVal->Value.UInt32;
}
}
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
#endif /* UAPROVIDER_DEMO_HAVE_MASS_ITEMS */
#if HAVE_DATA_LOGGER
/* Helper function for historizing demo variables. */
static OpcUa_StatusCode UaProvider_Demo_HistorizeItem(const OpcUa_CharA *szNodeId, OpcUa_Boolean bStartLogging)
{
OpcUa_NodeId nodeId;
OpcUa_BaseNode *pNode = 0;
UaProvider_Demo_UserData *pUserData = 0;
UaServer_DataLog *pDataLogItem;
OpcUa_Int32 iSamplingInterval = 500;
OpcUa_Byte AccessLevel;
OpcUa_Int hLogItem = 0;
OpcUa_InitializeStatus(OpcUa_Module_Server, "UaProvider_Demo_HistorizeItem");
UaBase_CreateStringNodeId(&nodeId, szNodeId);
pNode = UaServer_GetNodeById(&nodeId);
if (pNode && OpcUa_BaseNode_GetType(pNode) == eVariable)
{
/* read persistent configuration from datalogger */
if (UaServer_DataLogger_FindDataLogItem(g_hDataLogger, &nodeId, &pDataLogItem) == OpcUa_Good)
{
iSamplingInterval = (OpcUa_Int32)pDataLogItem->SamplingRate;
monitoringMode = pDataLogItem->Active == OpcUa_False ? OpcUa_MonitoringMode_Disabled : OpcUa_MonitoringMode_Reporting;
}
if (bStartLogging == OpcUa_False)
{
/* disable logging */
}
/* create datalog item if it does not already exist. */
iSamplingInterval,
monitoringMode,
100,
OpcUa_Null,
g_hDataLogger,
&hLogItem);
OpcUa_GotoErrorIfBad(uStatus);
/* store configuration in the node's userdata */
pUserData = UaProvider_Demo_UserData_HistoryDataLogger_Create(g_hDataLogger, hLogItem);
OpcUa_ReturnErrorIfAllocFailed(pUserData);
OpcUa_BaseNode_SetUserData(pNode, pUserData);
/* update node attributes */
OpcUa_Variable_SetHistorizing(pNode, bStartLogging);
AccessLevel = OpcUa_Variable_GetAccessLevel(pNode);
AccessLevel |= OpcUa_AccessLevels_HistoryRead;
OpcUa_Variable_SetAccessLevel(pNode, AccessLevel);
}
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
if (pUserData) OpcUa_Free(pUserData); /* //-V547 */
OpcUa_FinishErrorHandling;
}
static OpcUa_Void UaProvider_Demo_RemoveHistorizedItem(const OpcUa_CharA *szNodeId)
{
OpcUa_NodeId nodeId;
OpcUa_BaseNode *pNode;
UaProvider_Demo_UserData *pUserData;
UaBase_CreateStringNodeId(&nodeId, szNodeId);
pNode = UaServer_GetNodeById(&nodeId);
if (pNode)
{
pUserData = OpcUa_BaseNode_GetUserData(pNode);
if (pUserData && pUserData->UserDataType == UaProvider_Demo_UserDataType_HistoryDataLogger)
{
UaServer_DataLoggerItemData_Remove(pUserData->Data.HistoryDataLogger.DataLogger,
pUserData->Data.HistoryDataLogger.DataLogItem);
OpcUa_Free(pUserData);
OpcUa_BaseNode_SetUserData(pNode, OpcUa_Null);
}
}
}
static OpcUa_Void UaProvider_Demo_EnableHistorizedItem(const OpcUa_CharA *szNodeId, OpcUa_Boolean bEnabled)
{
OpcUa_NodeId nodeId;
OpcUa_BaseNode *pNode = 0;
UaProvider_Demo_UserData *pUserData = 0;
OpcUa_MonitoringMode monitoringMode;
UaServer_DataLog *pDataLogItem;
OpcUa_Int32 iSamplingInterval = 500;
UaBase_CreateStringNodeIdEx(&nodeId, szNodeId, g_UaProviderDemo_uNamespaceIndex1);
pNode = UaServer_GetNodeById(&nodeId);
if (pNode)
{
/* create user data object with data logger options */
pUserData = OpcUa_BaseNode_GetUserData(pNode);
if (pUserData == OpcUa_Null || pUserData->UserDataType != UaProvider_Demo_UserDataType_HistoryDataLogger) return;
/* read persistent configuration from datalogger */
if (UaServer_DataLogger_FindDataLogItem(g_hDataLogger, &nodeId, &pDataLogItem) == OpcUa_Good)
{
iSamplingInterval = (OpcUa_Int32)pDataLogItem->SamplingRate;
}
/* disable historization */
g_hDataLogger,
pUserData->Data.HistoryDataLogger.DataLogItem,
iSamplingInterval,
monitoringMode,
100,
OpcUa_Null);
/* update node attributes */
}
}
OpcUa_StatusCode UaProvider_Demo_SetupDataLogger()
{
UaBase_Settings settings;
OpcUa_Boolean bStartLogging;
char szDataLoggerPath[512] = "";
#if defined(__WIN32) || defined(WIN32)
UaBase_Settings_Initialize(&settings, "settings.ini");
#else
UaBase_Settings_Initialize(&settings, "settings.conf");
#endif
UaBase_Settings_BeginGroup(&settings, "DemoProvider");
UaBase_Settings_ReadBool(&settings, "StartLogging", &bStartLogging, OpcUa_False);
UaBase_Settings_ReadString(&settings, "DataLoggerPath", szDataLoggerPath, sizeof(szDataLoggerPath), "");
/* if szDataLoggerPath is empty, the settings file could not be read
this can result from a changed working directory */
if (szDataLoggerPath[0] == '\0') return OpcUa_Good;
/* create file logger */
#if HAVE_DATA_LOGGER_SQLITE_BACKEND
g_hDataLogger = UaServer_SQLiteLogger_Create( szDataLoggerPath, 600, 5);
#elif HAVE_DATA_LOGGER_FILE_BACKEND
g_hDataLogger = UaServer_FileLogger_Create( szDataLoggerPath );
#elif !defined(__VXWORKS__)
# error "Configuration error. No datalogger is configured."
#endif
OpcUa_ReturnErrorIfTrue(g_hDataLogger < 0, OpcUa_BadConfigurationError);
uStatus = UaProvider_Demo_HistorizeItem(Demo_Objects_Demo_History_ByteWithHistory, bStartLogging);
OpcUa_ReturnErrorIfBad(uStatus);
uStatus = UaProvider_Demo_HistorizeItem(Demo_Objects_Demo_History_DoubleWithHistory, bStartLogging);
OpcUa_ReturnErrorIfBad(uStatus);
uStatus = UaProvider_Demo_HistorizeItem(Demo_Objects_Demo_BoilerDemo_Boiler1_TemperatureSensor_Temperature, bStartLogging);
OpcUa_ReturnErrorIfBad(uStatus);
UaServer_DataLogger_Start(g_hDataLogger);
if (g_pDataLoggerActive) *g_pDataLoggerActive = bStartLogging;
return OpcUa_Good;
}
void UaProvider_Demo_CleanupDataLogger()
{
UaServer_DataLogger_Stop(g_hDataLogger);
UaProvider_Demo_RemoveHistorizedItem(Demo_Objects_Demo_History_ByteWithHistory);
UaProvider_Demo_RemoveHistorizedItem(Demo_Objects_Demo_History_DoubleWithHistory);
UaProvider_Demo_RemoveHistorizedItem(Demo_Objects_Demo_BoilerDemo_Boiler1_TemperatureSensor_Temperature);
UaServer_DataLogger_Delete(g_hDataLogger);
}
OpcUa_StatusCode UaProvider_Demo_StartLogging()
{
if (g_pDataLoggerActive == 0) return OpcUa_BadInternalError;
if (*g_pDataLoggerActive) return OpcUa_BadInvalidState;
*g_pDataLoggerActive = OpcUa_True;
/* enable items to start sampling */
UaProvider_Demo_EnableHistorizedItem(Demo_Objects_Demo_History_ByteWithHistory, OpcUa_True);
UaProvider_Demo_EnableHistorizedItem(Demo_Objects_Demo_History_DoubleWithHistory, OpcUa_True);
UaProvider_Demo_EnableHistorizedItem(Demo_Objects_Demo_BoilerDemo_Boiler1_TemperatureSensor_Temperature, OpcUa_True);
return OpcUa_Good;
}
OpcUa_StatusCode UaProvider_Demo_StopLogging()
{
if (g_pDataLoggerActive == 0) return OpcUa_BadInternalError;
if (*g_pDataLoggerActive == OpcUa_False) return OpcUa_BadInvalidState;
/* disable items to stop sampling*/
UaProvider_Demo_EnableHistorizedItem(Demo_Objects_Demo_History_ByteWithHistory, OpcUa_False);
UaProvider_Demo_EnableHistorizedItem(Demo_Objects_Demo_History_DoubleWithHistory, OpcUa_False);
UaProvider_Demo_EnableHistorizedItem(Demo_Objects_Demo_BoilerDemo_Boiler1_TemperatureSensor_Temperature, OpcUa_False);
*g_pDataLoggerActive = OpcUa_False;
return OpcUa_Good;
}
#endif /* HAVE_DATA_LOGGER */
#if UASERVER_SUPPORT_UNITS
/* The usage of UaServer_UnitIdFromCommonCode and UaServer_EUInformationFromUnitId is demonstrated here.
* The UaModeler generates correct type information, so this is only necessary for dynamically created
* EUInformation properties. */
void UaProvider_Demo_SetEngineeringUnits(const char *szNodeId, const char *szCommonCode)
{
OpcUa_Int32 UnitId = UaServer_UnitIdFromCommonCode(szCommonCode);
OpcUa_EUInformation *pEUInfoDst;
OpcUa_EUInformation *pEUInfoSrc;
pVal = UaProvider_Demo_GetNodeValueString(szNodeId);
if ( pVal
&& pVal->Datatype == OpcUaType_ExtensionObject
&& pVal->Value.ExtensionObject->Encoding == OpcUa_ExtensionObjectEncoding_EncodeableObject
&& pVal->Value.ExtensionObject->Body.EncodeableObject.Type->TypeId == OpcUaId_EUInformation)
{
pEUInfoSrc = UaServer_EUInformationFromUnitId(UnitId);
pEUInfoDst = (OpcUa_EUInformation*)pVal->Value.ExtensionObject->Body.EncodeableObject.Object;
if (pEUInfoSrc && pEUInfoDst)
{
OpcUa_EUInformation_Clear(pEUInfoDst);
OpcUa_MemCpy(pEUInfoDst, sizeof(OpcUa_EUInformation), pEUInfoSrc, sizeof(OpcUa_EUInformation));
}
}
}
#endif /* UASERVER_SUPPORT_UNITS */
OpcUa_StatusCode UaProvider_Demo_SetMultiStateDiscreteRange(const OpcUa_CharA *a_szNodeIdentifier,
OpcUa_UInt32 a_minValue,
OpcUa_UInt32 a_maxValue)
{
OpcUa_NodeId nodeid;
OpcUa_BaseNode *pNode;
UaProvider_Demo_UserData *pUserData;
UaBase_CreateStringNodeId(&nodeid, a_szNodeIdentifier);
pNode = UaServer_GetNodeById(&nodeid);
OpcUa_ReturnErrorIfNull(pNode, OpcUa_BadNotFound);
pUserData = UaProvider_Demo_UserData_MultiStateDiscrete_Create(a_minValue, a_maxValue);
OpcUa_ReturnErrorIfNull(pUserData, OpcUa_BadOutOfMemory);
OpcUa_BaseNode_SetUserData(pNode, pUserData);
return OpcUa_Good;
}
OpcUa_StatusCode UaProvider_Demo_SetMultiStateValueAsText(const OpcUa_CharA *a_szValueAsTextId,
const OpcUa_CharA *a_szEnumValuesId,
const OpcUa_CharA *a_szValueId)
{
OpcUa_Variant *pEnumValues, *pValue;
UaProvider_Demo_UserData *pUserData;
OpcUa_NodeId nodeid;
OpcUa_BaseNode *pNode;
pEnumValues = UaProvider_Demo_GetNodeValueString(a_szEnumValuesId);
OpcUa_ReturnErrorIfNull(pEnumValues, OpcUa_BadNotFound);
OpcUa_ReturnErrorIfTrue(pEnumValues->Datatype != OpcUaType_ExtensionObject ||
pEnumValues->ArrayType != OpcUa_VariantArrayType_Array, OpcUa_BadTypeMismatch);
pValue = UaProvider_Demo_GetNodeValueString(a_szValueId);
OpcUa_ReturnErrorIfNull(pValue, OpcUa_BadNotFound);
OpcUa_ReturnErrorIfTrue(pValue->ArrayType != OpcUa_VariantArrayType_Scalar, OpcUa_BadTypeMismatch);
UaBase_CreateStringNodeId(&nodeid, a_szValueAsTextId);
pNode = UaServer_GetNodeById(&nodeid);
OpcUa_ReturnErrorIfNull(pNode, OpcUa_BadNotFound);
pUserData = UaProvider_Demo_UserData_MultiStateValueAsText_Create(pEnumValues, pValue);
OpcUa_ReturnErrorIfNull(pUserData, OpcUa_BadOutOfMemory);
OpcUa_BaseNode_SetUserData(pNode, pUserData);
return OpcUa_Good;
}
OpcUa_StatusCode UaProvider_Demo_SetWorkOrderType_Reference(const OpcUa_CharA *a_szNodeIdentifier,
OpcUa_Variant *a_pValue,
WorkOrderTypeReference_Field a_field)
{
OpcUa_NodeId nodeid;
OpcUa_BaseNode *pNode;
UaProvider_Demo_UserData *pUserData;
UaBase_CreateStringNodeId(&nodeid, a_szNodeIdentifier);
pNode = UaServer_GetNodeById(&nodeid);
OpcUa_ReturnErrorIfNull(pNode, OpcUa_BadNotFound);
pUserData = UaProvider_Demo_UserData_WorkOrderTypeReference_Create(a_pValue, a_field);
OpcUa_ReturnErrorIfNull(pUserData, OpcUa_BadOutOfMemory);
OpcUa_BaseNode_SetUserData(pNode, pUserData);
return OpcUa_Good;
}
#define SET_MATRIX_VALUE(NODEID, DATATYPE) \
{ \
OpcUa_Int32 iNumArrayDimensions, iNumElements; \
OpcUa_UInt32 *pArrayDimensions; \
\
UaBase_CreateStringNodeId(&nodeid, NODEID); \
pNode = UaServer_GetNodeById(&nodeid); \
pValue = OpcUa_Variable_GetValue(pNode); \
iNumArrayDimensions = OpcUa_Variable_GetNumArrayDimensions(pNode); \
pArrayDimensions = OpcUa_Variable_GetArrayDimensions(pNode); \
\
OpcUa_Variant_Clear(pValue); \
iNumElements = 1; \
pValue->Datatype = OpcUaType_##DATATYPE; \
pValue->ArrayType = OpcUa_VariantArrayType_Matrix; \
pValue->Value.Matrix.Dimensions = OpcUa_Alloc(iNumArrayDimensions * sizeof(OpcUa_Int32)); \
OpcUa_GotoErrorIfAllocFailed(pValue->Value.Matrix.Dimensions); \
pValue->Value.Matrix.NoOfDimensions = iNumArrayDimensions; \
for (i = 0; i < iNumArrayDimensions; i++) \
{ \
pValue->Value.Matrix.Dimensions[i] = pArrayDimensions[i]; \
iNumElements *= pArrayDimensions[i]; \
} \
pValue->Value.Matrix.Value.DATATYPE##Array = OpcUa_Alloc(iNumElements * sizeof(OpcUa_##DATATYPE)); \
OpcUa_GotoErrorIfAllocFailed(pValue->Value.Matrix.Value.DATATYPE##Array); \
for (i = 0; i < iNumElements; i++) \
{ \
OpcUa_##DATATYPE##_Initialize(&pValue->Value.Matrix.Value.DATATYPE##Array[i]); \
} \
}
/* Set values of nodes that are currently not supported by UaModeler */
OpcUa_StatusCode UaProvider_Demo_SetupCustomNodeValues()
{
OpcUa_BaseNode *pNode = 0;
OpcUa_NodeId nodeid;
OpcUa_Int32 i;
#if UASERVER_ENABLE_DESCRIPTIONS
OpcUa_Int32 uLength = 80 * 1024;
OpcUa_CharA *szLongDesc;
#endif
OpcUa_Variant *pValue;
OpcUa_AxisInformation *pAxisInformation;
OpcUa_InitializeStatus(OpcUa_Module_Server, "UaProvider_Demo_SetupCustomNodeValues");
#if !OPCUA_VARIANT_OMIT_MATRIX
/* workaround for setting matrix values as currently the UaModeler does not support that */
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_Boolean, Boolean)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_Byte, Byte)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_ByteString, ByteString)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_DateTime, DateTime)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_Double, Double)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_ExpandedNodeId, ExpandedNodeId)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_Float, Float)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_Guid, Guid)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_Int16, Int16)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_Int32, Int32)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_Int64, Int64)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_LocalizedText, LocalizedText)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_NodeId, NodeId)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_QualifiedName, QualifiedName)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_SByte, SByte)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_StatusCode, StatusCode)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_String, String)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_UInt16, UInt16)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_UInt32, UInt32)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_UInt64, UInt64)
SET_MATRIX_VALUE(Demo_Objects_Demo_Static_Matrix_XmlElement, XmlElement)
/* create Vector structures */
{
OpcUa_Int32 iNumArrayDimensions, iNumElements;
OpcUa_UInt32 *pArrayDimensions;
UaBase_CreateStringNodeId(&nodeid, Demo_Objects_Demo_Static_Matrix_Vector);
pNode = UaServer_GetNodeById(&nodeid);
pValue = OpcUa_Variable_GetValue(pNode);
iNumArrayDimensions = OpcUa_Variable_GetNumArrayDimensions(pNode);
pArrayDimensions = OpcUa_Variable_GetArrayDimensions(pNode);
OpcUa_Variant_Clear(pValue);
iNumElements = 1;
pValue->Datatype = OpcUaType_ExtensionObject;
pValue->ArrayType = OpcUa_VariantArrayType_Matrix;
pValue->Value.Matrix.Dimensions = OpcUa_Alloc(iNumArrayDimensions * sizeof(OpcUa_Int32));
OpcUa_GotoErrorIfAllocFailed(pValue->Value.Matrix.Dimensions);
pValue->Value.Matrix.NoOfDimensions = iNumArrayDimensions;
for (i = 0; i < iNumArrayDimensions; i++)
{
pValue->Value.Matrix.Dimensions[i] = pArrayDimensions[i];
iNumElements *= pArrayDimensions[i];
}
pValue->Value.Matrix.Value.ExtensionObjectArray = OpcUa_Alloc(iNumElements * sizeof(OpcUa_ExtensionObject));
OpcUa_GotoErrorIfAllocFailed(pValue->Value.Matrix.Value.ExtensionObjectArray);
for (i = 0; i < iNumElements; i++)
{
Demo_Vector *pVector = OpcUa_Null;
OpcUa_ExtensionObject_Initialize(&pValue->Value.Matrix.Value.ExtensionObjectArray[i]);
uStatus = OpcUa_EncodeableObject_CreateExtension(&Demo_Vector_EncodeableType,
&pValue->Value.Matrix.Value.ExtensionObjectArray[i],
(OpcUa_Void**)&pVector);
OpcUa_GotoErrorIfBad(uStatus);
}
}
#endif /* !OPCUA_VARIANT_OMIT_MATRIX */
#if UASERVER_ENABLE_DESCRIPTIONS
/* set very long description */
UaBase_CreateStringNodeId(&nodeid, Demo_Objects_Demo_UnicodeTest_LongDescription);
pNode = UaServer_GetNodeById(&nodeid);
OpcUa_GotoErrorIfNull(pNode, OpcUa_BadNotFound);
szLongDesc = OpcUa_Alloc(uLength);
OpcUa_GotoErrorIfAllocFailed(szLongDesc);
for (i = 0; i < uLength; i++) { szLongDesc[i] = 'a' + (i % 26); }
szLongDesc[uLength - 1] = '\0';
uStatus = OpcUa_String_AttachToString(szLongDesc,
uLength - 1,
uLength,
OpcUa_False,
OpcUa_True,
&OpcUa_BaseNode_GetDescription(pNode)->Text);
OpcUa_GotoErrorIfBad(uStatus);
#endif /* UASERVER_ENABLE_DESCRIPTIONS */
#define SET_SCALAR_VALUE(NODEID, DATATYPE) \
pValue = UaProvider_Demo_GetNodeValueString(NODEID); \
OpcUa_GotoErrorIfNull(pValue, OpcUa_BadNotFound); \
OpcUa_Variant_Clear(pValue); \
OpcUa_Variant_Set##DATATYPE(pValue, 0);
#define SET_ARRAY_VALUE(NODEID, DATATYPE) \
pValue = UaProvider_Demo_GetNodeValueString(NODEID); \
OpcUa_GotoErrorIfNull(pValue, OpcUa_BadNotFound); \
OpcUa_Variant_Clear(pValue); \
pValue->Value.Array.Value.DATATYPE##Array = OpcUa_Alloc(10 * sizeof(OpcUa_##DATATYPE)); \
OpcUa_GotoErrorIfAllocFailed(pValue->Value.Array.Value.DATATYPE##Array); \
OpcUa_MemSet(pValue->Value.Array.Value.DATATYPE##Array, 0, 10 * sizeof(OpcUa_##DATATYPE)); \
pValue->Value.Array.Length = 10; \
pValue->Datatype = OpcUaType_##DATATYPE; \
pValue->ArrayType = OpcUa_VariantArrayType_Array;
/* 000_Static/Scalar */
SET_SCALAR_VALUE(Demo_Objects_Demo_Static_Scalar_BaseDataType, Int32);
SET_SCALAR_VALUE(Demo_Objects_Demo_Static_Scalar_Integer, Int32);
SET_SCALAR_VALUE(Demo_Objects_Demo_Static_Scalar_Number, UInt32);
SET_SCALAR_VALUE(Demo_Objects_Demo_Static_Scalar_UInteger, UInt32);
pValue = UaProvider_Demo_GetNodeValueString(Demo_Objects_Demo_Static_Scalar_Structures_Structure);
OpcUa_GotoErrorIfNull(pValue, OpcUa_BadNotFound);
uStatus = OpcUa_EncodeableObject_CreateExtension(&OpcUa_AxisInformation_EncodeableType,
pValue->Value.ExtensionObject,
(OpcUa_Void**)&pAxisInformation);
OpcUa_GotoErrorIfBad(uStatus);
/* 000_Static/Arrays */
SET_ARRAY_VALUE(Demo_Objects_Demo_Static_Arrays_BaseDataType, Int32);
SET_ARRAY_VALUE(Demo_Objects_Demo_Static_Arrays_Integer, Int32);
SET_ARRAY_VALUE(Demo_Objects_Demo_Static_Arrays_Number, UInt32);
SET_ARRAY_VALUE(Demo_Objects_Demo_Static_Arrays_UInteger, UInt32);
SET_ARRAY_VALUE(Demo_Objects_Demo_Static_Arrays_Structure, ExtensionObject);
for (i = 0; i < pValue->Value.Array.Length; i++)
{
uStatus = OpcUa_EncodeableObject_CreateExtension(&OpcUa_AxisInformation_EncodeableType,
&pValue->Value.Array.Value.ExtensionObjectArray[i],
(OpcUa_Void**)&pAxisInformation);
OpcUa_GotoErrorIfBad(uStatus);
}
/* 010_ComplianceTest/Static/All Profiles/Scalar */
SET_SCALAR_VALUE(Demo_Objects_Demo_CTT_Static_All_Profiles_Scalar_Variant, Int32);
SET_SCALAR_VALUE(Demo_Objects_Demo_CTT_Static_All_Profiles_Scalar_Integer, Int32);
SET_SCALAR_VALUE(Demo_Objects_Demo_CTT_Static_All_Profiles_Scalar_Number, UInt32);
SET_SCALAR_VALUE(Demo_Objects_Demo_CTT_Static_All_Profiles_Scalar_UInteger, UInt32);
/* 010_ComplianceTest/Static/All Profiles/Arrays */
SET_ARRAY_VALUE(Demo_Objects_Demo_CTT_Static_All_Profiles_Arrays_Variant, Variant);
for (i = 0; i < pValue->Value.Array.Length; i += 5)
{
OpcUa_Variant_SetBoolean(&pValue->Value.Array.Value.VariantArray[i + 0], OpcUa_False);
OpcUa_Variant_SetUInt16(&pValue->Value.Array.Value.VariantArray[i + 1], OpcUa_False);
OpcUa_Variant_SetUInt32(&pValue->Value.Array.Value.VariantArray[i + 2], OpcUa_False);
OpcUa_Variant_SetUInt64(&pValue->Value.Array.Value.VariantArray[i + 3], OpcUa_False);
OpcUa_Variant_SetString(&pValue->Value.Array.Value.VariantArray[i + 4], OpcUa_String_FromCString("sample string"));
}
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
OpcUa_StatusCode UaProvider_Demo_InitializeSimulation()
{
OpcUa_Variant *pVal = 0;
OpcUa_BaseNode *pNode = 0;
OpcUa_NodeId nodeid;
#if UASERVER_SUPPORT_EVENTS
UaServer_Event *pEvent = 0;
#endif
int iItem = 0;
OpcUa_InitializeStatus(OpcUa_Module_Server, "UaProvider_Demo_InitializeSimulation");
UaBase_SetDefaultNamespace(g_UaProviderDemo_uNamespaceIndex1);
#if UAPROVIDER_DEMO_HAVE_MASS_ITEMS
/* create dynamic nodes, that have not been modeled */
uStatus = UaProvider_Demo_CreateNodes();
OpcUa_GotoErrorIfBad(uStatus);
#endif /* UAPROVIDER_DEMO_HAVE_MASS_ITEMS */
/* connect C variables with Node values */
while (g_Items[iItem].ppVariable != 0)
{
pVal = UaProvider_Demo_GetNodeValueString(g_Items[iItem].szNodeId);
if (pVal)
{
if (pVal->ArrayType == OpcUa_VariantArrayType_Scalar)
{
/* assign union address */
*g_Items[iItem].ppVariable = &pVal->Value.Boolean;
}
else if (pVal->ArrayType == OpcUa_VariantArrayType_Array)
{
/* assign array address */
*g_Items[iItem].ppVariable = &pVal->Value.Array;
}
}
++iItem;
}
/* Boiler1 variables */
pVal = UaProvider_Demo_GetNodeValueString(Demo_Objects_Demo_BoilerDemo_Boiler1_TemperatureSensor_Temperature);
if (pVal) g_Boiler1.pTemperature = &pVal->Value.Double;
pVal = UaProvider_Demo_GetNodeValueString(Demo_Objects_Demo_BoilerDemo_Boiler1_TemperatureSetPoint);
if (pVal) g_Boiler1.pTemperatureSetPoint = &pVal->Value.Double;
pVal = UaProvider_Demo_GetNodeValueString(Demo_Objects_Demo_BoilerDemo_Boiler1_FillLevelSensor_FillLevel);
if (pVal) g_Boiler1.pFillLevel = &pVal->Value.Double;
pVal = UaProvider_Demo_GetNodeValueString(Demo_Objects_Demo_BoilerDemo_Boiler1_FillLevelSetPoint);
if (pVal) g_Boiler1.pFillLevelSetPoint = &pVal->Value.Double;
pVal = UaProvider_Demo_GetNodeValueString(Demo_Objects_Demo_BoilerDemo_Boiler1_HeaterStatus);
if (pVal) g_Boiler1.pHeaterStatus = &pVal->Value.Int32;
#if UASERVER_SUPPORT_UNITS
UaProvider_Demo_SetEngineeringUnits(Demo_Objects_Demo_BoilerDemo_Boiler1_TemperatureSensor_Temperature_EngineeringUnits, "CEL");
UaProvider_Demo_SetEngineeringUnits(Demo_Objects_Demo_BoilerDemo_Boiler1_FillLevelSensor_FillLevel_EngineeringUnits, "LTR");
#endif /* UASERVER_SUPPORT_UNITS */
UaBase_CreateStringNodeId(&nodeid, Demo_Objects_Demo_BoilerDemo_Boiler1);
pNode = UaServer_GetNodeById(&nodeid);
if (pNode)
{
UaProvider_Demo_UserData *pUserData = UaProvider_Demo_UserData_BoilerType_Create(&g_Boiler1);
OpcUa_BaseNode_SetUserData(pNode, pUserData);
}
if (g_Boiler1.pTemperature) *g_Boiler1.pTemperature = 20;
if (g_Boiler1.pTemperatureSetPoint) *g_Boiler1.pTemperatureSetPoint = 90;
if (g_Boiler1.pFillLevel) *g_Boiler1.pFillLevel = 10;
if (g_Boiler1.pFillLevelSetPoint) *g_Boiler1.pFillLevelSetPoint = 50;
#if UASERVER_SUPPORT_EVENTS
/* Machine variables */
UaBase_CreateNumericNodeId(&g_machine.NodeId, Demo_Objects_Demo_Events_Machine);
UaBase_CreateNumericNodeId(&g_machine.TemperatureSensor.NodeId, Demo_Objects_Demo_Events_Machine_TemperatureSensor);
UaBase_CreateNumericNodeId(&g_machine.HeaterSwitch.NodeId, Demo_Objects_Demo_Events_Machine_HeaterSwitch);
UaBase_CreateNumericNodeId(&g_machine.TemperatureSensor.HighAlarmId, 10001);
UaBase_CreateNumericNodeId(&g_machine.TemperatureSensor.LowAlarmId, 10002);
pVal = UaProvider_Demo_GetNodeValueNumeric(Demo_Objects_Demo_Events_Machine_TemperatureSensor_Temperature);
if (pVal)
{
pVal->Value.Double = 25.0;
g_machine.TemperatureSensor.pValue = &pVal->Value.Double;
}
pVal = UaProvider_Demo_GetNodeValueNumeric(Demo_Objects_Demo_Events_Machine_HeaterSwitch);
if (pVal)
{
g_machine.HeaterSwitch.pValue = &pVal->Value.Boolean;
}
/* create acknowledgeable condition type events */
UaBase_CreateNumericNodeIdEx(&nodeid, OpcUaId_AlarmConditionType, 0);
/* create acknowledgeable conditions used by this sensor */
pEvent = UaServer_Events_CreateEvent(&nodeid);
UaProvider_Demo_InitializeAlarmConditionTypeEvent(
pEvent,
&g_machine.TemperatureSensor.NodeId,
"Temperature Sensor",
&g_machine.TemperatureSensor.HighAlarmId,
"HighAlarm");
pEvent = UaServer_Events_CreateEvent(&nodeid);
UaProvider_Demo_InitializeAlarmConditionTypeEvent(
pEvent,
&g_machine.TemperatureSensor.NodeId,
"Temperature Sensor",
&g_machine.TemperatureSensor.LowAlarmId,
"LowAlarm");
#endif /* UASERVER_SUPPORT_EVENTS */
uStatus = UaProvider_Demo_SetMultiStateDiscreteRange(Demo_Objects_Demo_CTT_Static_DA_Profile_DiscreteType_MultiStateDiscrete1, 0, 4);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateDiscreteRange(Demo_Objects_Demo_CTT_Static_DA_Profile_DiscreteType_MultiStateDiscrete2, 0, 4);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateDiscreteRange(Demo_Objects_Demo_CTT_Static_DA_Profile_DiscreteType_MultiStateDiscrete3, 0, 2);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateDiscreteRange(Demo_Objects_Demo_CTT_Static_DA_Profile_DiscreteType_MultiStateDiscrete4, 0, 2);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateDiscreteRange(Demo_Objects_Demo_CTT_Static_DA_Profile_DiscreteType_MultiStateDiscrete5, 0, 2);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateValueAsText(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Byte_ValueAsText,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Byte_EnumValues,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Byte);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateValueAsText(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_SByte_ValueAsText,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_SByte_EnumValues,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_SByte);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateValueAsText(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int16_ValueAsText,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int16_EnumValues,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int16);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateValueAsText(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt16_ValueAsText,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt16_EnumValues,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt16);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateValueAsText(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int32_ValueAsText,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int32_EnumValues,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int32);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateValueAsText(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt32_ValueAsText,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt32_EnumValues,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt32);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateValueAsText(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int64_ValueAsText,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int64_EnumValues,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int64);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetMultiStateValueAsText(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt64_ValueAsText,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt64_EnumValues,
Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt64);
OpcUa_GotoErrorIfBad(uStatus);
/* set user data for nodes with changing status */
UaBase_CreateStringNodeId(&nodeid, Demo_Objects_Demo_Dynamic_Scalar_Quality_DynamicValue);
pNode = UaServer_GetNodeById(&nodeid);
if (pNode)
{
UaProvider_Demo_UserData *pUserData = UaProvider_Demo_UserData_Quality_Create(OpcUa_Good);
OpcUa_BaseNode_SetUserData(pNode, pUserData);
g_pDynamicValue_Quality = &pUserData->Data.Quality;
}
UaBase_CreateStringNodeId(&nodeid, Demo_Objects_Demo_Dynamic_Scalar_Quality_StaticValue);
pNode = UaServer_GetNodeById(&nodeid);
if (pNode)
{
UaProvider_Demo_UserData *pUserData = UaProvider_Demo_UserData_Quality_Create(OpcUa_Good);
OpcUa_BaseNode_SetUserData(pNode, pUserData);
g_pStaticValue_Quality = &pUserData->Data.Quality;
}
/* set user data for structures exposing their variables */
pVal = UaProvider_Demo_GetNodeValueString(Demo_Objects_Demo_WorkOrder_WorkOrderVariable);
if (pVal)
{
uStatus = UaProvider_Demo_SetWorkOrderType_Reference(Demo_Objects_Demo_WorkOrder_WorkOrderVariable_ID, pVal, WorkOrderTypeField_ID);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetWorkOrderType_Reference(Demo_Objects_Demo_WorkOrder_WorkOrderVariable_AssetID, pVal, WorkOrderTypeField_AssetID);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetWorkOrderType_Reference(Demo_Objects_Demo_WorkOrder_WorkOrderVariable_StartTime, pVal, WorkOrderTypeField_StartTime);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetWorkOrderType_Reference(Demo_Objects_Demo_WorkOrder_WorkOrderVariable_StatusComments, pVal, WorkOrderTypeField_StatusComments);
OpcUa_GotoErrorIfBad(uStatus);
}
pVal = UaProvider_Demo_GetNodeValueString(Demo_Objects_Demo_WorkOrder_WorkOrderVariable2);
if (pVal)
{
uStatus = UaProvider_Demo_SetWorkOrderType_Reference(Demo_Objects_Demo_WorkOrder_WorkOrderVariable2_ID, pVal, WorkOrderTypeField_ID);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetWorkOrderType_Reference(Demo_Objects_Demo_WorkOrder_WorkOrderVariable2_AssetID, pVal, WorkOrderTypeField_AssetID);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetWorkOrderType_Reference(Demo_Objects_Demo_WorkOrder_WorkOrderVariable2_StartTime, pVal, WorkOrderTypeField_StartTime);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaProvider_Demo_SetWorkOrderType_Reference(Demo_Objects_Demo_WorkOrder_WorkOrderVariable2_StatusComments, pVal, WorkOrderTypeField_StatusComments);
OpcUa_GotoErrorIfBad(uStatus);
}
#if HAVE_DATA_LOGGER
uStatus = UaProvider_Demo_SetupDataLogger();
OpcUa_GotoErrorIfBad(uStatus);
#endif /* HAVE_DATA_LOGGER */
/* at this moment we don't have generic file support, remove affected nodes */
UaBase_CreateStringNodeId(&nodeid, Demo_Objects_Demo_Files);
uStatus = UaServer_RemoveNodeById(&nodeid);
OpcUa_GotoErrorIfBad(uStatus);
/* set values of nodes that are not set by the generated code */
uStatus = UaProvider_Demo_SetupCustomNodeValues();
OpcUa_GotoErrorIfBad(uStatus);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
void UaProvider_Demo_CleanupSimulation()
{
#if UASERVER_SUPPORT_EVENTS
UaServer_Event *pEvent = 0;
pEvent = UaServer_Events_GetConditionByNodeId(g_UaProviderDemo_uNamespaceIndex1, &g_machine.TemperatureSensor.HighAlarmId);
if (pEvent) UaServer_Events_DeleteEvent(&pEvent);
pEvent = UaServer_Events_GetConditionByNodeId(g_UaProviderDemo_uNamespaceIndex1, &g_machine.TemperatureSensor.LowAlarmId);
if (pEvent) UaServer_Events_DeleteEvent(&pEvent);
#endif /* UASERVER_SUPPORT_EVENTS */
UaBase_SetDefaultNamespace(g_UaProviderDemo_uNamespaceIndex1);
#if HAVE_DATA_LOGGER
UaProvider_Demo_CleanupDataLogger();
#endif /* HAVE_DATA_LOGGER */
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_DiscreteType_MultiStateDiscrete1);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_DiscreteType_MultiStateDiscrete2);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_DiscreteType_MultiStateDiscrete3);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_DiscreteType_MultiStateDiscrete4);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_DiscreteType_MultiStateDiscrete5);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Byte_ValueAsText);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_SByte_ValueAsText);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int16_ValueAsText);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt16_ValueAsText);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int32_ValueAsText);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt32_ValueAsText);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_Int64_ValueAsText);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_CTT_Static_DA_Profile_MultiStateValueDiscreteType_UInt64_ValueAsText);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_Dynamic_Scalar_Quality_DynamicValue);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_Dynamic_Scalar_Quality_StaticValue);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_WorkOrder_WorkOrderVariable_ID);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_WorkOrder_WorkOrderVariable_AssetID);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_WorkOrder_WorkOrderVariable_StartTime);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_WorkOrder_WorkOrderVariable_StatusComments);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_WorkOrder_WorkOrderVariable2_ID);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_WorkOrder_WorkOrderVariable2_AssetID);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_WorkOrder_WorkOrderVariable2_StartTime);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_WorkOrder_WorkOrderVariable2_StatusComments);
UaProvider_Demo_UserData_Delete(Demo_Objects_Demo_BoilerDemo_Boiler1);
}
OpcUa_StatusCode UaProvider_Demo_StartSimulation()
{
if (g_hSimulationTimer != 0) return OpcUa_BadInvalidState;
ret = OpcUa_Timer_Create(
&g_hSimulationTimer,
g_SimulationInterval,
UaProvider_Demo_SimulationTimer,
OpcUa_Null,
OpcUa_Null );
if (g_pSimulationActive)
{
*g_pSimulationActive = OpcUa_True;
}
if (g_pSimulationSpeed)
{
*g_pSimulationSpeed = g_SimulationInterval;
}
return ret;
}
OpcUa_StatusCode UaProvider_Demo_StopSimulation()
{
if (g_hSimulationTimer == 0) return OpcUa_BadInvalidState;
ret = OpcUa_Timer_Delete(&g_hSimulationTimer);
if (g_pSimulationActive)
{
*g_pSimulationActive = OpcUa_False;
}
return ret;
}
OpcUa_StatusCode UaProvider_Demo_SetSimulationSpeed(OpcUa_UInt32 interval)
{
OpcUa_StatusCode ret = OpcUa_Good;
if (g_SimulationInterval == interval) return ret;
g_SimulationInterval = interval;
if (g_hSimulationTimer)
{
UaProvider_Demo_StopSimulation();
UaProvider_Demo_StartSimulation();
}
if (g_pSimulationSpeed)
{
*g_pSimulationSpeed = g_SimulationInterval;
}
return ret;
}
#if UAPROVIDER_DEMO_HAVE_ANIMATION_ITEM && UABASE_USE_FILESYSTEM
OpcUa_StatusCode UaProvider_Demo_StartAnimation()
{
if (g_hAnimationTimer != 0) return OpcUa_BadInvalidState;
ret = OpcUa_Timer_Create(
&g_hAnimationTimer,
g_AnimationInterval,
UaProvider_Demo_AnimationTimer,
OpcUa_Null,
OpcUa_Null );
return ret;
}
OpcUa_StatusCode UaProvider_Demo_StopAnimation()
{
if (g_hAnimationTimer == 0) return OpcUa_BadInvalidState;
ret = OpcUa_Timer_Delete(&g_hAnimationTimer);
return ret;
}
OpcUa_StatusCode UaProvider_Demo_SetAnimationSpeed(OpcUa_UInt32 interval)
{
OpcUa_StatusCode ret = OpcUa_Good;
if (g_AnimationInterval == interval) return ret;
g_AnimationInterval = interval;
if (g_hAnimationTimer)
{
UaProvider_Demo_StopAnimation();
UaProvider_Demo_StartAnimation();
}
return ret;
}
#endif /* UAPROVIDER_DEMO_HAVE_ANIMATION_ITEM && UABASE_USE_FILESYSTEM */
static void UaProvider_Demo_SimulateDynamicVariables()
{
static char szText[] = "*** stone - paper - scissors - lizard - spock ";
static char szTmp[] = " ";
static int len = sizeof(szText);
static int pos = 0;
int i;
#define INCREMENT_ARRAY(var, type) \
if (var && var->Length > 0) { \
var->Value.type##Array[0]++; \
for (i = 1; i < var->Length; i++) \
{ \
var->Value.type##Array[i] = var->Value.type##Array[i-1]+1; \
} \
}
/* simulate scalar values */
*g_pDynBoolean = ! *g_pDynBoolean;
(*g_pDynSByte)++;
(*g_pDynByte) -= 3;
(*g_pDynInt16) += 21;
(*g_pDynUInt16) -= 53;
(*g_pDynInt32)++;
(*g_pDynUInt32)++;
(*g_pDynInt64) += 2376452644LL;
(*g_pDynUInt64) -= 987654321ULL;
(*g_pDynFloat) += 0.1f;
(*g_pDynDouble) += 0.1;
switch (*g_pDynStatusCode)
{
case OpcUa_Good:
*g_pDynStatusCode = OpcUa_Bad; break;
case OpcUa_Bad:
*g_pDynStatusCode = OpcUa_BadInvalidArgument; break;
case OpcUa_BadInvalidArgument:
*g_pDynStatusCode = OpcUa_GoodMoreData | OpcUa_StatusCode_InfoType_DataValue | OpcUa_StatusCode_InfoBit_Overflow; break;
case OpcUa_GoodMoreData | OpcUa_StatusCode_InfoType_DataValue | OpcUa_StatusCode_InfoBit_Overflow:
*g_pDynStatusCode = OpcUa_Good; break;
}
*g_pDynamicValue_Quality = *g_pDynStatusCode;
*g_pStaticValue_Quality = *g_pDynStatusCode;
if (++pos >= len-1) pos = 0;
OpcUa_StrlCpyA( szTmp, szText+pos, len-pos );
OpcUa_StrlCpyA( szTmp+len-pos-1, szText, pos+1 );
OpcUa_String_AttachReadOnly( g_pDynString, szTmp);
*g_pDynDateTime = OpcUa_DateTime_UtcNow();
OpcUa_Guid_Create( *g_ppDynGuid );
if (g_pDynByteString->Length <= 0)
{
g_pDynByteString->Length = 0;
if (g_pDynByteString->Data) OpcUa_Free(g_pDynByteString->Data);
g_pDynByteString->Data = OpcUa_Alloc(sizeof(szTmp));
if (g_pDynByteString->Data)
{
g_pDynByteString->Length = sizeof(szTmp);
}
}
if (g_pDynByteString->Data)
{
OpcUa_MemCpy(
g_pDynByteString->Data, g_pDynByteString->Length,
szTmp, sizeof(szTmp)
);
}
if (g_pDynXmlElement->Length <= 0)
{
g_pDynXmlElement->Length = 0;
if (g_pDynXmlElement->Data) OpcUa_Free(g_pDynXmlElement->Data);
g_pDynXmlElement->Data = OpcUa_Alloc(sizeof(szTmp));
if (g_pDynXmlElement->Data)
{
g_pDynXmlElement->Length = sizeof(szTmp);
}
}
if (g_pDynXmlElement->Data)
{
OpcUa_MemCpy(
g_pDynXmlElement->Data, g_pDynXmlElement->Length,
szTmp, sizeof(szTmp)
);
}
(*g_pDynamicValue) += 0.1;
OpcUa_String_AttachReadOnly( &(*g_ppDynLocalizedText)->Text, szTmp);
(*g_ppDynQualifiedName)->NamespaceIndex++;
OpcUa_String_AttachReadOnly( &(*g_ppDynQualifiedName)->Name, szTmp);
(*g_ppDynNodeId)->NamespaceIndex++;
(*g_ppDynNodeId)->IdentifierType = OpcUa_IdentifierType_String;
OpcUa_String_AttachReadOnly( &(*g_ppDynNodeId)->Identifier.String, szTmp);
(*g_ppDynExpandedNodeId)->ServerIndex++;
(*g_ppDynExpandedNodeId)->NodeId.NamespaceIndex++;
(*g_ppDynExpandedNodeId)->NodeId.IdentifierType = OpcUa_IdentifierType_String;
OpcUa_String_AttachReadOnly( &(*g_ppDynExpandedNodeId)->NodeId.Identifier.String, szTmp);
/* simulate array values */
if (g_pDynArrayBoolean && g_pDynArrayBoolean->Length > 0)
{
g_pDynArrayBoolean->Value.BooleanArray[0] = !g_pDynArrayBoolean->Value.BooleanArray[0];
for (i = 1; i < g_pDynArrayBoolean->Length; i++)
{
g_pDynArrayBoolean->Value.BooleanArray[i] = !g_pDynArrayBoolean->Value.BooleanArray[i-1];
}
}
INCREMENT_ARRAY(g_pDynArrayByte, Byte);
INCREMENT_ARRAY(g_pDynArraySByte, SByte);
INCREMENT_ARRAY(g_pDynArrayUInt16, UInt16);
INCREMENT_ARRAY(g_pDynArrayInt16, Int16);
INCREMENT_ARRAY(g_pDynArrayUInt32, UInt32);
INCREMENT_ARRAY(g_pDynArrayInt32, Int32);
INCREMENT_ARRAY(g_pDynArrayUInt64, UInt64);
INCREMENT_ARRAY(g_pDynArrayInt64, Int64);
INCREMENT_ARRAY(g_pDynArrayFloat, Float);
INCREMENT_ARRAY(g_pDynArrayDouble, Double);
INCREMENT_ARRAY(g_pDynArrayStatusCode, StatusCode);
if (g_pDynArrayGuid)
{
for (i = 0; i < g_pDynArrayGuid->Length; i++)
{
OpcUa_Guid_Create(&g_pDynArrayGuid->Value.GuidArray[i]);
}
}
if (g_pDynArrayDateTime)
{
for (i = 0; i < g_pDynArrayDateTime->Length; i++)
{
g_pDynArrayDateTime->Value.DateTimeArray[i] = OpcUa_DateTime_UtcNow();
}
}
if (g_pDynArrayString)
{
for (i = 0; i < g_pDynArrayString->Length; i++)
{
OpcUa_String_AttachReadOnly( &g_pDynArrayString->Value.StringArray[i], szTmp);
}
}
if (g_pDynArrayByteString)
{
for (i = 0; i < g_pDynArrayByteString->Length; i++)
{
if (g_pDynArrayByteString->Value.ByteStringArray[i].Length <= 0)
{
g_pDynArrayByteString->Value.ByteStringArray[i].Length = 0;
if (g_pDynArrayByteString->Value.ByteStringArray[i].Data) OpcUa_Free(g_pDynArrayByteString->Value.ByteStringArray[i].Data);
g_pDynArrayByteString->Value.ByteStringArray[i].Data = OpcUa_Alloc(sizeof(szTmp));
if (g_pDynArrayByteString->Value.ByteStringArray[i].Data)
{
g_pDynArrayByteString->Value.ByteStringArray[i].Length = sizeof(szTmp);
}
}
if (g_pDynArrayByteString->Value.ByteStringArray[i].Data)
{
OpcUa_MemCpy(
g_pDynArrayByteString->Value.ByteStringArray[i].Data, g_pDynArrayByteString->Value.ByteStringArray[i].Length,
szTmp, sizeof(szTmp));
}
}
}
if (g_pDynArrayXmlElement)
{
for (i = 0; i < g_pDynArrayXmlElement->Length; i++)
{
if (g_pDynArrayXmlElement->Value.XmlElementArray[i].Length <= 0)
{
g_pDynArrayXmlElement->Value.XmlElementArray[i].Length = 0;
if (g_pDynArrayXmlElement->Value.XmlElementArray[i].Data) OpcUa_Free(g_pDynArrayXmlElement->Value.XmlElementArray[i].Data);
g_pDynArrayXmlElement->Value.XmlElementArray[i].Data = OpcUa_Alloc(sizeof(szTmp));
if (g_pDynArrayXmlElement->Value.XmlElementArray[i].Data)
{
g_pDynArrayXmlElement->Value.XmlElementArray[i].Length = sizeof(szTmp);
}
}
if (g_pDynArrayXmlElement->Value.XmlElementArray[i].Data)
{
OpcUa_MemCpy(
g_pDynArrayXmlElement->Value.XmlElementArray[i].Data, g_pDynArrayXmlElement->Value.XmlElementArray[i].Length,
szTmp, sizeof(szTmp)
);
}
}
}
if (g_pDynArrayLocalizedText)
{
for (i = 0; i < g_pDynArrayLocalizedText->Length; i++)
{
OpcUa_String_AttachReadOnly( &g_pDynArrayLocalizedText->Value.LocalizedTextArray[i].Text, szTmp);
}
}
if (g_pDynArrayQualifiedName)
{
for (i = 0; i < g_pDynArrayQualifiedName->Length; i++)
{
g_pDynArrayQualifiedName->Value.QualifiedNameArray[i].NamespaceIndex++;
OpcUa_String_AttachReadOnly( &g_pDynArrayQualifiedName->Value.QualifiedNameArray[i].Name, szTmp);
}
}
if (g_pDynArrayNodeId)
{
for (i = 0; i < g_pDynArrayNodeId->Length; i++)
{
g_pDynArrayNodeId->Value.NodeIdArray[i].NamespaceIndex++;
g_pDynArrayNodeId->Value.NodeIdArray[i].IdentifierType = OpcUa_IdentifierType_String;
OpcUa_String_AttachReadOnly( &g_pDynArrayNodeId->Value.NodeIdArray[i].Identifier.String, szTmp);
}
}
if (g_pDynArrayExpandedNodeId)
{
for (i = 0; i < g_pDynArrayExpandedNodeId->Length; i++)
{
g_pDynArrayExpandedNodeId->Value.ExpandedNodeIdArray[i].ServerIndex++;
g_pDynArrayExpandedNodeId->Value.ExpandedNodeIdArray[i].NodeId.NamespaceIndex++;
g_pDynArrayExpandedNodeId->Value.ExpandedNodeIdArray[i].NodeId.IdentifierType = OpcUa_IdentifierType_String;
OpcUa_String_AttachReadOnly( &g_pDynArrayExpandedNodeId->Value.ExpandedNodeIdArray[i].NodeId.Identifier.String, szTmp);
}
}
}
#if UAPROVIDER_DEMO_HAVE_MASS_ITEMS
static void UaProvider_Demo_SimulateMassfolderDynamicVariables()
{
int i;
OpcUa_UInt32 val = *g_pMassDynUInt32[0]+1;
for (i=0; i<UAPROVIDER_DEMO_NUM_MASS_DYNAMIC_VARIABLES; i++)
{
*g_pMassDynUInt32[i] = val;
}
}
#endif /* UAPROVIDER_DEMO_HAVE_MASS_ITEMS */
static void UaProvider_Demo_SimulateHistoryVariables()
{
static int t = 0;
static int mode = 1;
if (g_pHistoryByte) (*g_pHistoryByte) += (OpcUa_Byte)mode;
if (g_pHistoryDouble) (*g_pHistoryDouble) = 90 + 90 * sin(t*M_PI/180.0);
t++;
if ((t % 180) == 0) mode *= -1;
if (t == 360) t = 0;
}
static void UaProvider_Demo_SimulateBoiler( BoilerType *pBoiler )
{
double dtT;
double dtTDeadband = 2;
double C = 4187; /* [J/kgK] */
double dt = 10; /* [s] simulation speed */
double P = 1.5; /* [kW] */
double m;
double J = 1000 * P * dt; /* [J] */
if (pBoiler == 0) return;
if (pBoiler->pTemperature == 0) return;
if (pBoiler->pTemperatureSetPoint == 0) return;
if (pBoiler->pHeaterStatus == 0) return;
dtT = *pBoiler->pTemperature - *pBoiler->pTemperatureSetPoint;
m = *pBoiler->pFillLevel; /* [1l]=[1kg] */
/* heater control */
if ( dtT >= dtTDeadband )
{
*pBoiler->pHeaterStatus = Heater_Off;
}
else
{
*pBoiler->pHeaterStatus = Heater_Heating;
}
/* simulate heater */
if ( *pBoiler->pHeaterStatus == Heater_Heating )
{
if (m > 0)
{
dtT =J / ( C * m );
*pBoiler->pTemperature += dtT;
}
}
else
{
dtT = *pBoiler->pTemperature - 20;
*pBoiler->pTemperature -= dtT / 100.0;
}
/* simulate fill level */
if ( *pBoiler->pFillLevel < *pBoiler->pFillLevelSetPoint )
{
(*pBoiler->pFillLevel)++;
}
else if ( *pBoiler->pFillLevel > *pBoiler->pFillLevelSetPoint )
{
(*pBoiler->pFillLevel)--;
}
}
#if UAPROVIDER_DEMO_HAVE_ANIMATION_ITEM && UABASE_USE_FILESYSTEM
static void UaProvider_Demo_SimulateAnimation()
{
static int frame_counter = 0;
char filename[200] = {0};
UaBase_File *f;
OpcUa_SnPrintfA(filename, sizeof(filename), "animation/animation_%d.gif", frame_counter++);
f = UaBase_Fopen(filename, "rb");
if (f == OpcUa_Null)
{
frame_counter = 0;
OpcUa_SnPrintfA(filename, sizeof(filename), "animation/animation_%d.gif", frame_counter++);
f = UaBase_Fopen(filename, "rb");
}
#define MAX_ANIMATION_SIZE 56213
if (f)
{
if (g_pAnimation->Length != MAX_ANIMATION_SIZE || g_pAnimation->Data == 0)
{
if (g_pAnimation->Data)
{
OpcUa_Free(g_pAnimation->Data);
}
g_pAnimation->Data = OpcUa_Alloc(MAX_ANIMATION_SIZE);
}
if (g_pAnimation->Data != 0)
{
g_pAnimation->Length = (OpcUa_Int32)UaBase_Fread(g_pAnimation->Data, 1, MAX_ANIMATION_SIZE, f);
}
UaBase_Fclose(f);
}
}
#endif /* UAPROVIDER_DEMO_HAVE_ANIMATION_ITEM && UABASE_USE_FILESYSTEM */
IFMETHODIMP(UaProvider_Demo_SimulationTimer)(
OpcUa_Void* a_pvCallbackData,
OpcUa_Timer a_hTimer,
OpcUa_UInt32 a_msecElapsed )
{
OpcUa_ReferenceParameter(a_pvCallbackData);
OpcUa_ReferenceParameter(a_hTimer);
OpcUa_ReferenceParameter(a_msecElapsed);
UaProvider_Demo_SimulateDynamicVariables();
UaProvider_Demo_SimulateHistoryVariables();
#if UAPROVIDER_DEMO_HAVE_MASS_ITEMS
UaProvider_Demo_SimulateMassfolderDynamicVariables();
#endif /* UAPROVIDER_DEMO_HAVE_MASS_ITEMS */
UaProvider_Demo_SimulateBoiler(&g_Boiler1);
#if UASERVER_SUPPORT_EVENTS
UaProvider_Demo_SimulateMachine(&g_machine);
#endif /* UASERVER_SUPPORT_EVENTS */
return OpcUa_Good;
}
#if UAPROVIDER_DEMO_HAVE_ANIMATION_ITEM && UABASE_USE_FILESYSTEM
IFMETHODIMP(UaProvider_Demo_AnimationTimer)(
OpcUa_Void* a_pvCallbackData,
OpcUa_Timer a_hTimer,
OpcUa_UInt32 a_msecElapsed)
{
OpcUa_ReferenceParameter(a_pvCallbackData);
OpcUa_ReferenceParameter(a_hTimer);
OpcUa_ReferenceParameter(a_msecElapsed);
UaProvider_Demo_SimulateAnimation();
return OpcUa_Good;
}
#endif /* UAPROVIDER_DEMO_HAVE_ANIMATION_ITEM && UABASE_USE_FILESYSTEM */
#if UASERVER_SUPPORT_EVENTS
OpcUa_StatusCode UaProvider_Demo_SendModelChangeEvent(OpcUa_BaseNode *pParent, OpcUa_Byte verb)
{
OpcUa_StatusCode ret = OpcUa_Good;
OpcUa_NodeId *pParentId = OpcUa_Null;
UaServer_Event *pEvent = OpcUa_Null;
OpcUa_ModelChangeStructureDataType *pModelChanges = OpcUa_Null;
OpcUa_QualifiedName *pParentBrowseName = OpcUa_Null;
OpcUa_DateTime utcNow = OpcUa_DateTime_UtcNow();
OpcUa_ByteString bsEventId;
OpcUa_Variant modelChanges;
OpcUa_NodeId typeId;
OpcUa_ByteString_Initialize(&bsEventId);
OpcUa_Variant_Initialize(&modelChanges);
OpcUa_NodeId_Initialize(&typeId);
pParentId = OpcUa_BaseNode_GetId(pParent);
pParentBrowseName = OpcUa_BaseNode_GetBrowseName(pParent);
typeId.Identifier.Numeric = OpcUaId_GeneralModelChangeEventType;
pEvent = UaServer_Events_CreateEvent(&typeId);
UaServer_Events_SetEventType(pEvent, &typeId);
UaServer_Events_SetSourceNode(pEvent, pParentId);
UaServer_Events_SetSourceName(pEvent, OpcUa_String_GetRawString(&pParentBrowseName->Name));
UaServer_Events_SetMessage(pEvent, "", "The address space model has changed");
UaServer_Events_CreateEventId(OpcUa_Null, &bsEventId);
UaServer_Events_SetEventId(pEvent, &bsEventId);
OpcUa_ByteString_Clear(&bsEventId);
UaServer_Events_SetTime(pEvent, utcNow);
modelChanges.Datatype = OpcUaType_ExtensionObject;
modelChanges.ArrayType = OpcUa_VariantArrayType_Array;
modelChanges.Value.Array.Value.ExtensionObjectArray = (OpcUa_ExtensionObject*)OpcUa_Alloc(1 * sizeof(OpcUa_ExtensionObject));
OpcUa_ReturnErrorIfAllocFailed(modelChanges.Value.Array.Value.ExtensionObjectArray);
modelChanges.Value.Array.Length = 1;
OpcUa_ExtensionObject_Initialize(&modelChanges.Value.Array.Value.ExtensionObjectArray[0]);
ret = OpcUa_EncodeableObject_CreateExtension(&OpcUa_ModelChangeStructureDataType_EncodeableType,
&modelChanges.Value.Array.Value.ExtensionObjectArray[0],
(OpcUa_Void**)&pModelChanges);
OpcUa_ReturnErrorIfBad(ret);
pModelChanges->Verb = verb;
OpcUa_NodeId_CopyTo(pParentId, &pModelChanges->Affected);
pModelChanges->AffectedType.Identifier.Numeric = OpcUaId_FolderType;
UaServer_Events_SetEventField(pEvent, GeneralModelChangeEventTypeField_Changes, &modelChanges);
OpcUa_Variant_Clear(&modelChanges);
return ret;
}
OpcUa_Void UaProvider_Demo_SimulateMachine(Machine *a_pMachine)
{
OpcUa_Boolean *pSwitch = a_pMachine->HeaterSwitch.pValue;
OpcUa_Double *pTemp = a_pMachine->TemperatureSensor.pValue;
OpcUa_Double oldTemperature = *pTemp;
/* simulate sensors of a_pMachine */
if (*pSwitch == OpcUa_True && *pTemp < 110.0)
{
*pTemp += 0.5;
}
else if (*pSwitch == OpcUa_False && *pTemp > -10.0)
{
*pTemp -= 0.5;
}
/* check if the temperature has over-/underrun certain values and fire events if necessary */
if (oldTemperature < 100 && *pTemp >= 100)
{
UaServer_Event *pHighAlarm = UaServer_Events_GetConditionByNodeId(g_UaProviderDemo_uNamespaceIndex1,
&a_pMachine->TemperatureSensor.HighAlarmId);
if (pHighAlarm)
UaProvider_Demo_FireAlarmConditionTypeEvent(pHighAlarm);
}
if (oldTemperature > 0 && *pTemp <= 0)
{
UaServer_Event *pLowAlarm = UaServer_Events_GetConditionByNodeId(g_UaProviderDemo_uNamespaceIndex1,
&a_pMachine->TemperatureSensor.LowAlarmId);
if (pLowAlarm)
UaProvider_Demo_FireAlarmConditionTypeEvent(pLowAlarm);
}
if (oldTemperature >= 100 && *pTemp < 100)
{
UaServer_Event *pHighAlarm = UaServer_Events_GetConditionByNodeId(g_UaProviderDemo_uNamespaceIndex1,
&a_pMachine->TemperatureSensor.HighAlarmId);
if (pHighAlarm)
UaProvider_Demo_DisableAlarmConditionTypeEvent(pHighAlarm);
}
if (oldTemperature <= 0 && *pTemp > 0)
{
UaServer_Event *pLowAlarm = UaServer_Events_GetConditionByNodeId(g_UaProviderDemo_uNamespaceIndex1,
&a_pMachine->TemperatureSensor.LowAlarmId);
if (pLowAlarm)
UaProvider_Demo_DisableAlarmConditionTypeEvent(pLowAlarm);
}
}
#endif /* UASERVER_SUPPORT_EVENTS */
#if UASERVER_SUPPORT_FILEIMPORTER
int UaProvider_Demo_AddNamespaceCB(OpcUa_UInt16 nsidx, const char *szUri, UaServer_FileImporter_NodeStat *pStat, void *pUserData)
{
#if OPCUA_TRACE_ENABLE
char *szBinaryAddressSpacePath = pUserData;
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " NS%"OpcUa_PRIu16" (%s from %s):\n", nsidx, szUri, szBinaryAddressSpacePath);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Datatypes created\n", pStat->NoOfDatatypes);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Referencetypes created\n", pStat->NoOfReferencetypes);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Variabletypes created\n", pStat->NoOfVariabletypes);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Objecttypes created\n", pStat->NoOfObjecttypes);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Variables created\n", pStat->NoOfVariables);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Objects created\n", pStat->NoOfObjects);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Methods created\n", pStat->NoOfMethods);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Views created\n", pStat->NoOfViews);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" References created\n", pStat->NoOfReferences);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Numerics created\n", pStat->NoOfNumerics);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Strings created\n", pStat->NoOfStrings);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Guids created\n", pStat->NoOfGuids);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Opaque created\n", pStat->NoOfOpaque);
OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, " %"OpcUa_PRIu32" Dimensions created\n", pStat->NoOfDimensions);
#else /* OPCUA_TRACE_ENABLE */
OpcUa_ReferenceParameter(nsidx);
OpcUa_ReferenceParameter(szUri);
OpcUa_ReferenceParameter(pStat);
OpcUa_ReferenceParameter(pUserData);
#endif /* OPCUA_TRACE_ENABLE */
return 0;
}
int UaProvider_Demo_AddExtensionNamespaceCB(OpcUa_UInt16 nsidx, const char *szUri, void *pUserData)
{
OpcUa_ReferenceParameter(nsidx);
OpcUa_ReferenceParameter(szUri);
OpcUa_ReferenceParameter(pUserData);
return 0;
}
int UaProvider_Demo_AddNodeCB(OpcUa_BaseNode *pNode, UaServer_FileImporter_BaseNode *pNodeInfo, void *pUserData)
{
OpcUa_ReferenceParameter(pNode);
OpcUa_ReferenceParameter(pNodeInfo);
OpcUa_ReferenceParameter(pUserData);
return 0;
}
void UaProvider_Demo_ReportStatCB(UaServer_FileImporter_StatisticType type, size_t size, void *pUserData)
{
OpcUa_ReferenceParameter(type);
OpcUa_ReferenceParameter(size);
OpcUa_ReferenceParameter(pUserData);
}
OpcUa_StatusCode UaProvider_Demo_LoadBinaryAddressSpace()
{
UaBase_Settings settings;
char szBinaryAddressSpacePath[512] = "";
OpcUa_InitializeStatus(OpcUa_Module_Server, "UaProvider_Demo_LoadBinaryAddressSpace");
#if defined(__WIN32) || defined(WIN32)
UaBase_Settings_Initialize(&settings, "settings.ini");
#else
UaBase_Settings_Initialize(&settings, "settings.conf");
#endif
UaBase_Settings_BeginGroup(&settings, "DemoProvider");
UaBase_Settings_ReadString(&settings, "BinaryAddressSpacePath", szBinaryAddressSpacePath, sizeof(szBinaryAddressSpacePath), "");
/* nothing to do if setting is empty */
if (szBinaryAddressSpacePath[0] == '\0')
OpcUa_ReturnError(OpcUa_Good);
OpcUa_MemSet(&cb, 0, sizeof(cb));
cb.pfAddNamespaceCB = UaProvider_Demo_AddNamespaceCB;
cb.pfAddExtensionNamespaceCB = UaProvider_Demo_AddExtensionNamespaceCB;
cb.pfAddNodeCB = UaProvider_Demo_AddNodeCB;
cb.pfReportStatCB = UaProvider_Demo_ReportStatCB;
uStatus = UaServer_FileImporterSimple_Initialize(&fileImporter,
cb,
g_pDemoProvider,
UaServer_FileImporterSimple_LOADINGMODE_CREATE,
szBinaryAddressSpacePath);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaServer_FileImporterSimple_LoadFile(&fileImporter, szBinaryAddressSpacePath);
OpcUa_GotoErrorIfBad(uStatus);
UaServer_FileImporterSimple_Clear(&fileImporter);
OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
UaServer_FileImporterSimple_Clear(&fileImporter);
OpcUa_FinishErrorHandling;
}
#endif /* UASERVER_SUPPORT_FILEIMPORTER */
OPCUA_END_EXTERN_C