High Performance OPC UA Server SDK  1.1.1.177
custom_provider_nodes.c
/*****************************************************************************
* *
* Copyright (c) 2006-2016 Unified Automation GmbH. All rights reserved. *
* *
* Software License Agreement ("SLA") Version 2.6 *
* *
* 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.6, 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.6/ *
* *
*****************************************************************************/
#include <memory/memory.h>
#include <uabase/statuscodes.h>
#include <uabase/nodeid.h>
#include <uabase/variant.h>
#include <uabase/accesslevel.h>
#include <uabase/structure/nodeclass.h>
#include <uabase/structure/range.h>
#include <uabase/identifiers.h>
#include <uabase/valuerank.h>
#include <uaserver/addressspace/addressspace.h>
#include <uaserver/addressspace/object.h>
#include <uaserver/addressspace/variable.h>
#include "custom_provider.h"
#include "custom_provider_store.h"
#include "custom_provider_nodes.h"
#include "custom_provider_identifiers.h"
/*
* @brief Create a property node EURange.
* @param parent Node to add the property to.
* @param identifier Numeric identifier for the property.
* @param low Initial minimum value of the range.
* @param high Initial maximum value of the range.
* @return 0 on success or errorcode on failure.
*/
static int custom_provider_create_eurange(ua_node_t parent, uint32_t identifier, double low, double high)
{
struct ua_nodeid datatype, nodeid;
struct ua_range *eurange = NULL;
struct ua_variant property;
ua_node_t node;
int ret;
unsigned int valueidx;
ua_nodeid_set_numeric(&nodeid, g_custom_provider_nsidx, identifier);
/* create a node from class variable with mandatory attributes */
&nodeid, /* nodeid for the new node */
UA_NODECLASS_VARIABLE, /* nodeclass of the new node */
0, /* ns index for browsename is namespace zero */
"EURange", /* browsename */
NULL, /* displayname, NULL for same as browsename */
UA_NODE_PROPERTYTYPE, /* typedefinition is propertytype */
parent, /* parent node of the new node */
UA_NODE_HASPROPERTY); /* new node is referenced with hasproperty by parent */
if (node == UA_NODE_INVALID) goto out;
ua_nodeid_set_numeric(&datatype, 0, UA_ID_RANGE);
/* set mandatory attributes for nodeclass variable */
if (ret != 0) goto out;
/* allocate memory for ua_range struct */
eurange = IPC_ALLOC(eurange);
if (eurange == NULL) return UA_EBADNOMEM;
/* set minimum/maximum of the range */
eurange->low = low;
eurange->high = high;
/* attach range to an ua_variant */
ret = ua_variant_attach_extensionobject(&property, eurange, &datatype);
if (ret != 0) goto out;
/* attach the ua_variant to the memorystore */
ret = ua_memorystore_attach_new_value(&g_memorystore, &property, node);
if (ret != 0) goto out;
/* update value store with range info*/
ret = ua_variable_get_value_index(parent, &valueidx);
if (ret != 0) goto out;
ret = custom_store_set_range(valueidx, (uint32_t)low, (uint32_t)high);
if (ret != 0) goto out;
return 0;
out:
ipc_free(eurange);
return -1;
}
/*
* @brief Create a new variable node representing a value of the device.
* @param identifier Numeric identifier for the node.
* @param parent Node to add the new node to.
* @param name Name of the new node, used as browsename and displayname.
* @param valueidx Index in the value array of the device.
* @param initial_value Initial value.
* @return New node on success or UA_NODE_INVALID on failure.
*/
static ua_node_t custom_provider_create_variable(uint32_t identifier, ua_node_t parent, const char *name, unsigned int valueidx, uint32_t initial_value)
{
struct ua_nodeid datatype, nodeid;
ua_node_t node;
int ret;
ua_nodeid_set_numeric(&nodeid, g_custom_provider_nsidx, identifier);
/* create a node from class variable with mandatory attributes */
&nodeid, /* nodeid for the new node */
UA_NODECLASS_VARIABLE, /* nodeclass of the new node */
nodeid.nsindex, /* ns index for browsename is same as for nodeid */
name, /* browsename */
NULL, /* displayname, NULL for same as browsename */
UA_NODE_BASEDATAVARIABLETYPE, /* typedefinition is basedatavariabletype */
parent, /* parent node of the new node */
UA_NODE_ORGANIZES); /* new node is referenced with organizes by parent */
if (node == UA_NODE_INVALID) return UA_NODE_INVALID;
ua_nodeid_set_numeric(&datatype, 0, UA_ID_UINT32);
/* set mandatory attributes for nodeclass variable */
node, /* newly created node to set attributes to */
&datatype, /* datatype is uint32 */
UA_VALUERANK_SCALAR, /* valuerank: scalar */
UA_ACCESSLEVEL_CURRENTREAD | UA_ACCESSLEVEL_CURRENTWRITE, /* allow read and write for the value */
false); /* historizing is not supported for this node */
if (ret != 0) return UA_NODE_INVALID;
/* set initial value */
ret = custom_store_set_initial_value(valueidx, initial_value);
if (ret != 0) return UA_NODE_INVALID;
/* write the storeindex to the node */
ret = ua_variable_set_store_index(node, g_custom_store_idx);
if (ret != 0) return UA_NODE_INVALID;
/* write the valueindex to the node */
ret = ua_variable_set_value_index(node, valueidx);
if (ret != 0) return UA_NODE_INVALID;
return node;
}
/* create nodes in the custom provider namespace */
int custom_provider_create_nodes(void)
{
ua_node_t folder, node;
struct ua_nodeid nodeid;
int ret;
/* create a folder for the new nodes */
ua_nodeid_set_numeric(&nodeid, g_custom_provider_nsidx, CUSTOM_NODES_ID);
folder = ua_object_create_folder(&nodeid, UA_NODE_OBJECTSFOLDER, "CustomNodes");
if (folder == UA_NODE_INVALID) return UA_EBAD;
/* create new variable node */
node = custom_provider_create_variable(CUSTOM_VARIABLE1_ID, folder, "Variable1", 0, 0);
if (node == UA_NODE_INVALID) return UA_EBAD;
/* create property eurange and add it to the new node */
ret = custom_provider_create_eurange(node, CUSTOM_EURANGE_VAR1_ID, 0.0, 50.0);
if (ret != 0) return ret;
node = custom_provider_create_variable(CUSTOM_VARIABLE2_ID, folder, "Variable2", 1, 5);
if (node == UA_NODE_INVALID) return UA_EBAD;
ret = custom_provider_create_eurange(node, CUSTOM_EURANG_VAR2_ID, 0.0, 100.0);
if (ret != 0) return ret;
node = custom_provider_create_variable(CUSTOM_VARIABLE3_ID, folder, "Variable3", 2, 93738);
if (node == UA_NODE_INVALID) return UA_EBAD;
ret = custom_provider_create_eurange(node, CUSTOM_VARIABLE3_ID, 0.0, 100000.0);
if (ret != 0) return ret;
return 0;
}