Current section
Files
Jump to
Current section
Files
src/opcua_server.erl
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% @doc Helper function for OPCUA servers
%%% @end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(opcua_server).
%% TODO %%
%%
%% - Implemente a plugable service API that whould handle all the nodes under
%% some mount point node, delegating all node handling to some callback module.
%% - Add suport for method calls.
%% - Add support for object instanciation from defined type, with instanciation
%% of all properties and components defined.
%% - Add support for object deletion with all its properties.
%% - Add some notifications of changes so a plugable service could react
%% to changes made to there managed nodes. Ideally, there should be a way
%% for the service to be able to validate the changes before they even take
%% place, so the service can ensure consistency and access managment.
%%% INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-include("opcua.hrl").
-include("opcua_internal.hrl").
%%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% API
-export([add_object/2, add_object/3]).
-export([del_object/1]).
-export([add_variable/5]).
-export([add_property/4]).
-export([set_value/2]).
%%% API FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
add_object(Name, TypeSpec) ->
add_object(?OBJ_OBJECTS_FOLDER, Name, TypeSpec).
add_object(ParentSpec, Name, TypeSpec) when is_binary(Name) ->
NodeId = opcua_server_registry:next_node_id(),
TypeId = opcua_node:id(TypeSpec),
ParentId = opcua_node:id(ParentSpec),
opcua_server_space:add_nodes([#opcua_node{
node_id = NodeId,
origin = local,
browse_name = Name,
node_class = #opcua_object{}
}]),
opcua_server_space:add_references([
#opcua_reference{
type_id = ?NNID(?REF_HAS_TYPE_DEFINITION),
source_id = NodeId,
target_id = TypeId
},
#opcua_reference{
type_id = ?NNID(?REF_HAS_CHILD),
source_id = ParentId,
target_id = NodeId
}
]),
NodeId.
del_object(ObjSpec) ->
NodeId = opcua_node:id(ObjSpec),
opcua_server_space:del_nodes([NodeId]),
NodeId.
add_variable(ObjSpec, Name, VarTypeSpec, ValueTypeSpec, Value) ->
NodeId = opcua_server_registry:next_node_id(),
ParentId = opcua_node:id(ObjSpec),
VarTypeId = opcua_node:id(VarTypeSpec),
ValueTypeId = opcua_node:id(ValueTypeSpec),
opcua_server_space:add_nodes([#opcua_node{
node_id = NodeId,
origin = local,
browse_name = Name,
node_class = #opcua_variable{
data_type = ValueTypeId,
value = Value
}
}]),
opcua_server_space:add_references([
#opcua_reference{
type_id = ?NNID(?REF_HAS_TYPE_DEFINITION),
source_id = NodeId,
target_id = VarTypeId
},
#opcua_reference{
type_id = ?NNID(?REF_HAS_PROPERTY),
source_id = ParentId,
target_id = NodeId
}
]),
NodeId.
add_property(ObjSpec, Name, ValueTypeSpec, Value) ->
add_variable(ObjSpec, Name, ?TYPE_PROPERTY, ValueTypeSpec, Value).
set_value(VarSpec, Value) ->
VarId = opcua_node:id(VarSpec),
Node = opcua_server_space:node(VarId),
#opcua_node{node_class = Variable} = Node,
%TODO: Maybe some type checking here ?
opcua_server_space:add_nodes([Node#opcua_node{
node_class = Variable#opcua_variable{
value = Value
}
}]).